Fix Shader Material

I’d like to apply the shader material to the obj model. I tried it but it looks like this. It seems there is a problem in vertex shader. How can we apply the shader material correctly?
I have ported shader from here

This is My current code.

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(5, 10, 30);
const renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xaaaaaa, 0.3);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Set up lights
const ambient = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambient);

const p0 = new THREE.DirectionalLight(0xffffff, 0.5);
p0.position.set(10, 10, 10);
p0.lookAt(0, 0, 0);
scene.add(p0);

// White directional light at half intensity shining from the top.
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(0, 15, 0);
directionalLight.lookAt(0, 0, 0);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;

scene.add(directionalLight);

var grid = new THREE.GridHelper(100, 20, 0x0000ff, 0x808080);
scene.add(grid);

const orbitCcontrol = new OrbitControls(camera, renderer.domElement);
orbitCcontrol.update();
orbitCcontrol.addEventListener('change', render);
const shaderLoader = new THREE.FileLoader();
const vertex = `varying vec2 vUv; 
void main()
{
    vUv = uv;

    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
}
  `;
const frag = `uniform vec3 color;
uniform float uTime;
uniform vec2 iResolution;
varying vec2 vUv;


#define S(r,v) smoothstep(9./iResolution.y,0.,abs(v-(r)))

const vec2 s = vec2(1, 1.7320508); // 1.7320508 = sqrt(3)
const vec3 baseCol = vec3(.05098, .25098, .2784);
const float borderThickness = .02;
const float isolineOffset = .4;
const float isolineOffset2 = .325;

float calcHexDistance(vec2 p)
{
    p = abs(p);
    return max(dot(p, s * .5), p.x);
}

float random(vec2 co)
{
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

vec4 calcHexInfo(vec2 uv)
{
    vec4 hexCenter = round(vec4(uv, uv - vec2(.5, 1.)) / s.xyxy);
    vec4 offset = vec4(uv - hexCenter.xy * s, uv - (hexCenter.zw + .5) * s);
    return dot(offset.xy, offset.xy) < dot(offset.zw, offset.zw) ? vec4(offset.xy, hexCenter.xy) : vec4(offset.zw, hexCenter.zw);
}

void main(  )
{
    vec2 uv = 3. * (2. * gl_FragCoord.xy - iResolution.xy) / iResolution.y;
    uv.x += uTime * .25;
    
    vec4 hexInfo = calcHexInfo(uv);
    float totalDist = calcHexDistance(hexInfo.xy) + borderThickness;
    float rand = random(hexInfo.zw);
    
    float angle = atan(hexInfo.y, hexInfo.x) + rand * 5. + uTime;
    vec3 isoline = S(isolineOffset, totalDist) * baseCol * step(3. + rand * .5, mod(angle, 6.28))
        + S(isolineOffset2, totalDist)
                    * baseCol * step(4. + rand * 1.5, mod(angle + rand * 2., 6.28));
    
    float sinOffset = sin(uTime + rand * 8.);
    float aa = 5. / iResolution.y;
    
    gl_FragColor.rgb = (smoothstep(.51, .51 - aa, totalDist) + pow(1. - max(0., .5 - totalDist), 20.) * 1.5)
        * (baseCol + rand * vec3(0., .1, .09)) + isoline + baseCol * smoothstep(.2 + sinOffset, .2 + sinOffset - aa, totalDist);    
    gl_FragColor.a = 1.0; 
}`

const clock = new THREE.Clock();

const uniforms = {
    iResolution: {
        value: new THREE.Vector2()
    },
    uTime: { value: 0.0 }
  };


const material = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: vertex,
    fragmentShader: frag
});


const loader = new OBJLoader();
loader.load(
    './models/Q.obj',
    function (object) {
        const mesh = object.children[0];
        console.log("object: ", mesh);
        mesh.scale.set(0.01,0.01,0.01)
        mesh.material = material;
        scene.add(object);
    },
    function (xhr) {},
    function (error) {
        console.error('modelload', error);
    }
);

function render() {
    tick();
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}
function tick(){
    uniforms.iResolution.value.set(window.innerWidth, window.innerHeight);
    uniforms.uTime.value += clock.getDelta();
}

render();

The shader is applied correctly - but it depends on the UV coordinates on the model. If you’d like the effect to look “denser” - try multiplying the UV coordinates by some higher number:

vUv = uv * 10.0;

But the best solution to the issue would either to make the shader not rely on UV (ie. vUv) coordinates at all, using world position instead - or adjust UVs on the model in Blender.

Thanks for your reply. @mjurczyk
My original idea was applied the shader like this.

Current results doesn’t look like the 3D model.
As you mentioned, How can I make this shader code not rely on UV coordinates at all?

Try change uv to position.xz. Or like triplanar method.