vue-babylonjs icon indicating copy to clipboard operation
vue-babylonjs copied to clipboard

Shader on Imported Asset

Open robksawyer opened this issue 5 years ago • 2 comments

Can you tell me why the shader isn't being applied to my imported model? The model is imported fine, but no shader. Thanks for your time and any help!

<Scene @scene="onScene">
    <Camera type="universal"></Camera>
    <DirectionalLight diffuse="#0F0"></DirectionalLight>
    <HemisphericLight :direction="[100, 0, 100]"></HemisphericLight>
    <PointLight specular="#0F0"></PointLight>
    <SpotLight diffuse="#00F"></SpotLight>
    <Asset
      :src="publicPath"
      :scaling="myAsset.scaling"
      :position="myAsset.position"
      :rotation="myAsset.rotation"
    >
      <Animation property="rotation.y" :springiness="10" :duration="5" :end="Math.PI * 2"></Animation>
      <!-- Use the text content inside Vertex and Fragment components-->
      <!-- Unsafe caching, non-reactive-->
      <!-- USE A UNIQUE VALUE IN THE "name" PROPERTY FOR SAFE CACHING-->
      <!-- only recommended for prototyping-->
      <Shader name="silver_lake">
        <Vertex>
          precision highp float;

          // Attributes
          attribute vec3 position;
          attribute vec3 normal;
          attribute vec2 uv;

          // Uniforms
          uniform mat4 worldViewProjection;

          // Varying
          varying vec4 vPosition;
          varying vec3 vNormal;

          void main() {
            vec4 p = vec4( position, 1. );
            vPosition = p;
            vNormal = normal;
            gl_Position = worldViewProjection * p;
          }
        </Vertex>
        <Fragment>
          precision highp float;

          uniform mat4 worldView;

          varying vec4 vPosition;
          varying vec3 vNormal;

          uniform sampler2D textureSampler;
          uniform sampler2D refSampler;

          void main(void) {
            vec3 e = normalize( vec3( worldView * vPosition ) );
            vec3 n = normalize( worldView * vec4(vNormal, 0.0) ).xyz;
            vec3 r = reflect( e, n );
            float m = 2. * sqrt(
              pow( r.x, 2. ) +
              pow( r.y, 2. ) +
              pow( r.z + 1., 2. )
            );
            vec2 vN = r.xy / m + .5;
            vec3 base = texture2D( refSampler, vN).rgb;
            gl_FragColor = vec4( base, 1. );
          }
        </Fragment>
      </Shader>
    </Asset>
  </Scene>
<script>
import trophy from '../assets/Trophy.gltf'

export default {
  name: 'Trophy',
  data () {
    return {
      publicPath: trophy,
      myCamera: {
        checkCollisions: true,
        applyGravity: true,
      },
      myAsset: {
        scaling: [0.75, 0.75, 0.75],
        position: [ 0, -100, 500 ],
        rotation: [0, 180, 0],
      },
    }
  },
  methods: {
    onScene(scene) {
      // should be fired when the scene object has been initialized
      console.log('Scene loaded!');
    }
  },
}
</script>

robksawyer avatar Jun 24 '19 23:06 robksawyer

Is it possible that your imported asset has more than one mesh? In the case the asset has more than one mesh, a root mesh will be created. Pretty sure that's the best way to handle that case, but unfortunately that means you'd have to attach materials and shaders to the child meshes through Babylon.js directly.

BrainBacon avatar Jun 27 '19 17:06 BrainBacon

@robksawyer did you have any luck with the root mesh? If you can make a minimally reproducible example on Glitch or something and I could help you out when I have some free time? You could start off of this simple template.

BrainBacon avatar Jul 17 '19 04:07 BrainBacon