Shader material with morph targets

I tried to use shadermaterial with morph targets, with shadermaterial I just want to change the look of the object,not its geometry. I have not been successful in doing that. The morph targets stop working if I use shadermaterial . Is this a bug? how can I get away with this …

I have not found any solution or question asked about this

I used this vertex shader before

'varying vec2 vUv;\
		uniform float morphTargetInfluences[ 8 ];\
		void main() {\
			vUv = uv;\
			vec3 morphed = vec3( 0.0 );\
			\n#ifdef USE_MORPHTARGETS\n\
			morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\
			morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\
			morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\
			morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\
			morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\
			morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\
			morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\
			morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\
			\n#endif\n\
			morphed += position;\
			gl_Position = projectionMatrix * (modelViewMatrix * vec4( morphed, 1.0 ));\
		}'

these days it might need few tweaks (edit: specifically, after this pull request)

can you share the whole code?

if you do jsfiddle with MeshBasicMaterial, I could edit it

Actually, someon posted this:
Edit fiddle - JSFiddle - Code Playground

Fixed my shader issue, but i cannot use the Morphtargetinfluences for some reason, it seems a recurrent issue

Been trying using morphTargetinfluences, to no avail, what am i getting wrong?


const vShader = `
      attribute float size;
      varying vec3 vColor;
      uniform float morphTargetInfluences[ 5 ];
       #include <morphtarget_pars_vertex>

      void main() {
         #include <begin_vertex>
        #include <morphtarget_vertex>
        vec3 morphed = vec3( 0.0 );
    #ifdef USE_MORPHTARGETS
      transformed  += morphTarget0  * morphTargetInfluences[ 0 ];
      transformed  += morphTarget1  * morphTargetInfluences[ 1 ];
      transformed  +=  morphTarget2   * morphTargetInfluences[ 2 ];
      transformed  +=  morphTarget3   * morphTargetInfluences[ 3 ];

      #endif

      vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
      gl_PointSize = size   ;
      gl_Position = projectionMatrix * mvPosition;

          // gl_Position = vec4( transformed, 1.0 );

   }`

const fShader = `
      uniform vec3 color;
      uniform float alphaTest;
      uniform vec2 u_resolution;
      varying vec3 vColor;

      void main() {
      vec2 xy = gl_PointCoord.xy - vec2(0.5);
      float ll = length(xy);
      gl_FragColor = vec4(color * 10.0 , step(ll, 0.5 ) * alphaTest);
       
   }`


    const shaderMat = new ShaderMaterial( {

        uniforms: {
            color: { value: new Color( 0xffffff ) }, // pointTexture: { value: new THREE.TextureLoader().load( 'textures/sprites/disc.png' ) },
            alphaTest: { value: 0.025 } ,
            size: { value: minScale   },
            scale: { value: 1 },
            morphTargetInfluences: {value: [1.0, 0.0, 0.0, 0.0, 0.0]}

          },
            vertexShader: vShader,
            fragmentShader: fShader,
            blending: AdditiveBlending,
            depthTest: false,
            transparent: true,
             morphTargets: true
            //, lighting : true

        } );

      shaderMat.morphTargets = true;
        
 shaderMat.uniforms.morphTargetInfluences  =  group.children[0].morphTargetInfluences

from your shader you seem to have Points not Mesh, and I dont think morph targets are supported there. if so, you have to declare attributes manually and morph them by hand as well. scratch that, they are supported

yes, they are. My issue laid in the geometry :sweat_smile:, I have posted the code here:

you can include the following headers to make things work:

	<script type="x-shader/x-fragment" id="vertexShaderWhiteFluff">
		#include <common>
		#include <uv_pars_vertex>
		#include <uv2_pars_vertex>
		#include <displacementmap_pars_vertex>
		#include <color_pars_vertex>
		#include <fog_pars_vertex>
		#include <morphtarget_pars_vertex>
		#include <skinning_pars_vertex>
		#include <shadowmap_pars_vertex>
		#include <specularmap_pars_fragment>
		#include <logdepthbuf_pars_vertex>
		#include <clipping_planes_pars_vertex>		
	varying vec2 vUv;
	void main() {
		#include <beginnormal_vertex>
		#include <morphnormal_vertex>
		#include <begin_vertex>
		#include <morphtarget_vertex>
		vUv = uv;
		gl_Position = projectionMatrix * modelViewMatrix * vec4( transformed, 1.0 );
	}
	</script>
2 Likes

Thank you so much for this answer, this way has helped me fixed the issue

Hello i am using this shader
// Original by N8Programs
// https://twitter.com/N8Programs/status/1569865007042646018
// GitHub - N8python/diamonds

import * as THREE from “three”;
import { useLayoutEffect, useMemo, useRef } from “react”;
import { extend, useThree } from “@react-three/fiber”;
import { shaderMaterial } from “@react-three/drei”;
import {
MeshBVH,
MeshBVHUniformStruct,
shaderStructs,
shaderIntersectFunction,
SAH
} from “three-mesh-bvh”;

const DiamondMaterial = shaderMaterial(
{
envMap: null,
bounces: 3,
ior: 2.4,
correctMips: true,
aberrationStrength: 0.01,
fastChroma: true,
fresnel: 0,
bvh: new MeshBVHUniformStruct(),
color: new THREE.Color(“white”),
resolution: new THREE.Vector2()
},
/glsl/ `
varying vec3 vWorldPosition;
varying vec3 vNormal;
varying mat4 projectionMatrixInv;
varying mat4 viewMatrixInv;
varying vec3 viewDirection;

void main() {

projectionMatrixInv = inverse(projectionMatrix);
viewMatrixInv = inverse(viewMatrix);
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;    
vNormal = (viewMatrixInv * vec4(normalMatrix * normal, 0.0)).xyz;
viewDirection = normalize(vWorldPosition - cameraPosition);
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);

}, /*glsl*/
precision highp isampler2D;
precision highp usampler2D;
varying vec3 vWorldPosition;
varying vec3 vNormal;
uniform samplerCube envMap;
uniform float bounces;
{shaderStructs} {shaderIntersectFunction}
uniform BVH bvh;
uniform float ior;
uniform vec3 color;
uniform bool correctMips;
uniform vec2 resolution;
uniform float fresnel;
uniform float aberrationStrength;
uniform mat4 modelMatrix;
uniform bool fastChroma;
varying mat4 projectionMatrixInv;
varying mat4 viewMatrixInv;
varying vec3 viewDirection;

float fresnelFunc(vec3 viewDirection, vec3 worldNormal) {
return pow( 1.0 + dot( viewDirection, worldNormal), 10.0 );
}

vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 normal, float ior, mat4 modelMatrixInverse) {
vec3 rayOrigin = ro;
vec3 rayDirection = rd;
rayDirection = refract(rayDirection, normal, 1.0 / ior);
rayOrigin = vWorldPosition + rayDirection * 0.001;
rayOrigin = (modelMatrixInverse * vec4(rayOrigin, 1.0)).xyz;
rayDirection = normalize((modelMatrixInverse * vec4(rayDirection, 0.0)).xyz);
for(float i = 0.0; i < bounces; i++) {
uvec4 faceIndices = uvec4( 0u );
vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
vec3 barycoord = vec3( 0.0 );
float side = 1.0;
float dist = 0.0;
bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist );
vec3 hitPos = rayOrigin + rayDirection * max(dist - 0.001, 0.0);
// faceNormal *= side;
vec3 tempDir = refract(rayDirection, faceNormal, ior);
if (length(tempDir) != 0.0) {
rayDirection = tempDir;
break;
}
rayDirection = reflect(rayDirection, faceNormal);
rayOrigin = hitPos + rayDirection * 0.01;
}
rayDirection = normalize((modelMatrix * vec4(rayDirection, 0.0)).xyz);
return rayDirection;
}

void main() {
mat4 modelMatrixInverse = inverse(modelMatrix);
vec2 uv = gl_FragCoord.xy / resolution;
vec3 directionCamPerfect = (projectionMatrixInv * vec4(uv * 2.0 - 1.0, 0.0, 1.0)).xyz;
directionCamPerfect = (viewMatrixInv * vec4(directionCamPerfect, 0.0)).xyz;
directionCamPerfect = normalize(directionCamPerfect);
vec3 normal = vNormal;
vec3 rayOrigin = vec3(cameraPosition);
vec3 rayDirection = normalize(vWorldPosition - cameraPosition);
vec3 finalColor;
#ifdef CHROMATIC_ABERRATIONS
//vec3 rayDirectionR = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 - aberrationStrength), 1.0), modelMatrixInverse);
vec3 rayDirectionG = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), modelMatrixInverse);
//vec3 rayDirectionB = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 + aberrationStrength), 1.0), modelMatrixInverse);
vec3 rayDirectionR = normalize(rayDirectionG + 2.0 * vec3(aberrationStrength));
vec3 rayDirectionB = normalize(rayDirectionG - 2.0 * vec3(aberrationStrength));
if (!fastChroma) {
rayDirectionR = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 - aberrationStrength), 1.0), modelMatrixInverse);
rayDirectionB = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 + aberrationStrength), 1.0), modelMatrixInverse);
}
float finalColorR = textureGrad(envMap, rayDirectionR, dFdx(correctMips ? directionCamPerfect: rayDirection), dFdy(correctMips ? directionCamPerfect: rayDirection)).r;
float finalColorG = textureGrad(envMap, rayDirectionG, dFdx(correctMips ? directionCamPerfect: rayDirection), dFdy(correctMips ? directionCamPerfect: rayDirection)).g;
float finalColorB = textureGrad(envMap, rayDirectionB, dFdx(correctMips ? directionCamPerfect: rayDirection), dFdy(correctMips ? directionCamPerfect: rayDirection)).b;
finalColor = vec3(finalColorR, finalColorG, finalColorB) * color;
#else
rayDirection = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), modelMatrixInverse);
finalColor = textureGrad(envMap, rayDirection, dFdx(correctMips ? directionCamPerfect: rayDirection), dFdy(correctMips ? directionCamPerfect: rayDirection)).rgb;
finalColor *= color;
#endif
float nFresnel = fresnelFunc(viewDirection, normal * (1.0 - fresnel));
gl_FragColor = vec4(mix(finalColor, vec3(1.0), nFresnel), 1.0);

#include <tonemapping_fragment>
#include <encodings_fragment>

}`
);

extend({ DiamondMaterial });

export function RefractionMaterial({
frames = 1,
resolution = 256,
near = 0.1,
far = 1000,
aberrationStrength = 0,
…props
}) {
const material = useRef();
const { size } = useThree();
const defines = useMemo(() => {
const temp = {};
if (aberrationStrength > 0) temp.CHROMATIC_ABERRATIONS = “”;
return temp;
}, [aberrationStrength]);

useLayoutEffect(() => {
const geometry = material.current?.__r3f?.parent?.geometry;
if (geometry)
material.current.bvh.updateFrom(
new MeshBVH(geometry.toNonIndexed(), {
lazyGeneration: false,
strategy: SAH
})
);
}, );

return (
<diamondMaterial
key={JSON.stringify(!!aberrationStrength)}
defines={defines}
ref={material}
resolution={[size.width, size.height]}
aberrationStrength={aberrationStrength}
{…props}
/>
);
}

can you please guide me where i can add the header you’re posted ?