hujiulong / vue-3d-model

📷 vue.js 3D model viewer component
https://vue-3d-model.netlify.app
MIT License
2.48k stars 472 forks source link

Feature: background and the hdr environment #168

Open wangerzi opened 4 years ago

wangerzi commented 4 years ago

We can set texture to the background and enviroment property for three.js scene as this document three.js Scene.background

So, I want to create two props for model-mixin.vue, just like this

export default {
    props: {
         enviroment: String,
         background: String
    }
}

At first, we can support two format to load texture, cube map and the hdr.

If we have resouces path like this image

The enviroment and the background proerty allow two type of string

static/resources/textures/Park3Med/ static/resources/env.hdr

We can judge .hdr suffix to make sure what type is. If it's the cube map, we can use the CubeTextureLoader to load

const r = this.envirement;
      const urls = [
        `${r}px.jpg`, `${r}nx.jpg`,
        `${r}py.jpg`, `${r}ny.jpg`,
        `${r}pz.jpg`, `${r}nz.jpg`,
      ];
      // new RGBELoader()
      new THREE.CubeTextureLoader()
      // .setDataType(THREE.UnsignedByteType) // alt: FloatType, HalfFloatType
        .load(urls, (texture, textureData) => {
          texture.mapping = THREE.CubeRefractionMapping;

          this.scene.background = texture;
          this.scene.environment = texture;
      }

If it's the hdr file, we can use RGBELoader to load it.

const hdrPath = 'xxx.hdr';
const pmremGenerator = new PMREMGenerator(this.renderer);
      pmremGenerator.compileEquirectangularShader();
      new RGBELoader()
        .setDataType(THREE.UnsignedByteType)
        .load(hdrPath, (texture) => {
          const envMap = pmremGenerator.fromEquirectangular(texture).texture;

          this.scene.background = envMap;
          this.scene.environment = envMap;

          texture.dispose();
          pmremGenerator.dispose();
          this.render();
        });

Also, we should judge enviroment and the background isn't equal and create a load cache to aviod repeat texture load.

This is the three.js examples: gltf loader with hdr enviroment cube map

I'm already try to write the core code locally, and get this effect. image

How about this, is it ok? @hujiulong

hujiulong commented 4 years ago

Nice!

But I hope to clearly give the url of each image of the cube map by passing a string array, and this can also be distinguished from giving a single image(equirectangular map).

Equirectangular Map

<model-gltf
  src="xxx.gltf"
  background="https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/2294472375_24a3b8ef46_o.jpg"
/>

Cube Map

<model-gltf
  src="xxx.gltf"
  :background="[
    "xx/px.png", "xx/nx.png", 
    "xx/py.png", "xx/ny.png", 
    "xx/pz.png", "xx/nz.png", 
  ]"
/>

For .hdr files, we only need to treat it as a picture format, the above usage also supports hdr:

<model-gltf
  src="xxx.gltf"
  :background="[
    "xx/px.hdr", "xx/nx.hdr", 
    "xx/py.hdr", "xx/ny.hdr", 
    "xx/pz.hdr", "xx/nz.hdr", 
  ]"
/>

It can even support other formats, such as .exr. But the processing of these image formats requires additional code(RGBELoader or something), which will make the code base too large. I don't think they will be supported for now.

wangerzi commented 4 years ago

Great, it's better than my first design @hujiulong So we should define the background and environment prop as [String, Array].

I think we can distinguish this following types;

  1. "xxxxx/xx.hdr"
  2. "xxxx/full.png" -> I'm not sure have anyone want to load a wide view png picture to be a background.
  3. ["xx/px.hdr", "xx/nx.hdr", "xx/py.hdr", "xx/ny.hdr", "xx/pz.hdr", "xx/nz.hdr"]
  4. [ "xx/px.png", "xx/nx.png", "xx/py.png", "xx/ny.png", "xx/pz.png", "xx/nz.png", ]

So, at first we should check the prop value is correct, contain the support suffix check, the string array depth check, etc. And then load the texture and assign to scene properties.

Here I think of a problem, should we necessary import a vuex or the eventbus to manage the texture load cache?(PS: I checked the CubeLoader and RGBELoader will not cache the texture.)

Just like someone have two model to render, but they have the same background setting ["xx/px.hdr", "xx/nx.hdr", "xx/py.hdr", "xx/ny.hdr", "xx/pz.hdr", "xx/nz.hdr"]. We can't cache the texture on the component data, beacause every component have their own data.

hujiulong commented 4 years ago

I'm not sure have anyone want to load a wide view png picture to be a background

This is very common, such images can be taken using a 360° panoramic camera. You can see this example.

Here I think of a problem, should we necessary import a vuex or the eventbus to manage the texture load cache?(PS: I checked the CubeLoader and RGBELoader will not cache the texture.) Just like someone have two model to render, but they have the same background setting ["xx/px.hdr", "xx/nx.hdr", "xx/py.hdr", "xx/ny.hdr", "xx/pz.hdr", "xx/nz.hdr"]. We can't cache the texture on the component data, beacause every component have their own data.

I don’t think it is necessary, relying on the browser ’s cache is enough.

wangerzi commented 4 years ago

OK, thanks for response, I'm already known how to do and try to implement this feature. I'll comment this issue if I have another question!

wangerzi commented 4 years ago

Hello, there is a new situation @hujiulong

When I load the dae model or use the CubeTextureLoader to load urls, the environment can't take effect, and I'm confused about this, you can try it on My feature branch.

image

image

image

hujiulong commented 4 years ago

Ok, I'm a bit busy during this time, when I'm free I will see where the problem is.

geni94 commented 3 years ago

@wangerzi hey there, I'm having an issue with a .ply model and maybe you can help me out on finding the right setting.

I'm correctly loading my model but I'm failing to activate its vertexColors through this library. How were you able to colorize your .ply model? Thanks in advance.

wangerzi commented 3 years ago

@wangerzi hey there, I'm having an issue with a .ply model and maybe you can help me out on finding the right setting.

I'm correctly loading my model but I'm failing to activate its vertexColors through this library. How were you able to colorize your .ply model? Thanks in advance.

@geni94 Hi, I found vertexColors property at Material Object, in this project if you want to modify matrial object, you can use $refs to get the object in vue component, just like this.$refs.model.object.material.vertexColors = true.

I tried to modify the demo-ply.vue :

https://github.com/hujiulong/vue-3d-model/blob/40b077a3513f0830d1ba28a3c653b401b7ac97b2/examples/pages/demo-ply.vue#L1-L73

<template>
  <demo-block :vue-code="code" :html-code="htmlCode">
    <template slot="preview">
      <model-ply
        ref="model"
        :backgroundAlpha="0"
        @on-load="onLoad"
        :rotation="rotation"
        src="static/models/ply/binary/Lucy100k.ply"
      ></model-ply>
      <div class="example-loading" v-show="loading"></div>
    </template>
  </demo-block>
</template>

<script>
import DemoBlock from '../components/demo-block.vue';
import ModelPly from '../../src/model-ply.vue';

const code = `
<template>
    <model-ply src="static/models/ply/slotted_disk.ply"></model-ply>
</template>

<script>
    import { ModelPly } from 'vue-3d-model'

    export default {
        components: {
            ModelPly
        }
    }
<\/script>
`;

const htmlCode = `
<body>
    <div id="app">
        <model-ply src="static/models/ply/slotted_disk.ply"></model-ply>
    </div>
    #scripts#
    <script>
        new Vue({
            el: '#app'
        })
    <\/script>
</body>
`;

export default {
  name: 'demo-ply',
  data() {
    return {
      code,
      htmlCode,
      loading: true,
      rotation: {
        x: 0,
        y: Math.PI,
        z: 0,
      },
    };
  },
  methods: {
    onLoad() {
      this.loading = false;
      console.log(this.$refs);
      this.$refs.model.object.material.vertexColors = true;
    },
  },
  components: {
    ModelPly,
    DemoBlock,
  },
};
</script>

image