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