An Introduction to Augmented Reality with Viro
Tags: augmentedreality, ar, reactnative, javascript
Published: 2020-08-30 17:52:17

## Introduction

Augmented Reality (AR) is a tech used to superimpose computer-generated images on a user's view of the real world, providing a composite view. This can be viewable on a simple phone screen (think [Pokemon Go](https://pokemongolive.com/en/)) or with smart phone based Virtual Reality [headsets](https://www.amazon.com/Cell-Phone-VR-Headsets/b?ie=UTF8&node=14775002011).

Since Expo's [AR component is deprecated](https://docs.expo.io/versions/latest/sdk/AR/), [Viro Media](https://docs.viromedia.com/docs/quick-start) have taken charge as one of the fastest, easiest ways to get augmented reality up and running on your iOS or Android device. Their [documentation](https://docs.viromedia.com/docs/tutorial-ar) is impressively detailed and helpful.

## Setup

If you're in OSX:

```bash
brew install node
brew install watchman
```

If you're in Linux:

```bash
apt-get install node
apt-get install watchman
```

For all distributions:

```bash
npm install -g react-native-cli
npm install -g react-viro-cli
react-viro init ViroSample --verbose
cd ViroSample
npm start
```
Now within the /js/HelloWorldSceneAR.js file, change line 38 so that "Hello World!" is a message of your choosing:
```javascript
  _onInitialized(state, reason) {
    if (state == ViroConstants.TRACKING_NORMAL) {
      this.setState({
        text : "Happy Birthday" // was "Hello World"
      });
    } else if (state == ViroConstants.TRACKING_NONE) {
      // Handle loss of tracking
    }
  }
```
Then get the [iOS Viro Media App](https://itunes.apple.com/us/app/viro-media/id1163100576?mt=8) or the [Android Viro Media App](https://play.google.com/store/apps/details?id=com.viromedia.viromedia)
Open the Viro Media App, and press the icon in the top left, and then press "Enter Testbed". Scroll up in your Terminal to find your ngrok url, enter that into the text field, and press Go. You should see your message displayed on the scene!

![Happy Birthday text in front of a plant](https://dev-to-uploads.s3.amazonaws.com/i/3o5j5pk8pbo2jbc2houe.PNG)

![Happy Birthday text in front of a plant, side view](https://dev-to-uploads.s3.amazonaws.com/i/f9ltxkdky0z3d10ii04k.PNG)

## 3D Objects

Now that you've seen the message displayed on your phone, [download this file](https://s3-us-west-2.amazonaws.com/viro/Assets/res.zip), unzip it, and place it in your /ViroSample/js/ folder.

Now, replace the contents of your HelloWorldSceneAR.js with this code from the [docs](https://gist.github.com/dam00n/ff54340a053f731055887e4f78945978#file-gistfile1-txt):
```jsx
'use strict';

import React, { Component } from 'react';
import {StyleSheet} from 'react-native';
import {
  ViroARScene,
  ViroText,
  ViroMaterials,
  ViroBox,
  Viro3DObject,
  ViroAmbientLight,
  ViroSpotLight,
  ViroARPlaneSelector,
  ViroNode,
  ViroAnimations,
} from 'react-viro';
const createReactClass = require('create-react-class');
const HelloWorldSceneAR = createReactClass({
  getInitialState() {
    return {
      text : "Initializing AR..."
    };
  },

  render: function() {
    return (
      <ViroARScene onTrackingInitialized={()=>{this.setState({text : "Happy Birthday"})}}> // Again, change this text to your desired message
        <ViroText text={this.state.text} scale={[.1, .1, .1]} height={1} width={4} position={[0, .5, -1]} style={styles.helloWorldTextStyle} />

        <ViroAmbientLight color={"#aaaaaa"} />
        <ViroSpotLight innerAngle={5} outerAngle={90} direction={[0,-1,-.2]} position={[0, 3, 1]} color="#ffffff" castsShadow={true} />

          <Viro3DObject
            source={require('./res/emoji_smile/emoji_smile.vrx')}
            position={[0, 0, -1]}
            scale={[.2, .2, .2]}
            type="VRX"
            dragType="FixedDistance" onDrag={()=>{}} // allows user to drag 3D object around with finger
          />

      </ViroARScene>
    );
  },
});

const styles = StyleSheet.create({
  helloWorldTextStyle: {
    fontFamily: 'Arial',
    fontSize: 50,
    color: '#ffffff',
    textAlignVertical: 'center',
    textAlign: 'center',
  },
});

module.exports = HelloWorldSceneAR;
```

You should see a 3D smiley face beneath your message, like so:

![Hovering smiley face](https://dev-to-uploads.s3.amazonaws.com/i/g18z07no8k7x35ojsueg.PNG)

![Hovering smiley face beneath Happy Birthday text from side](https://dev-to-uploads.s3.amazonaws.com/i/vgyv8n6cskraxv7yi7n6.PNG)

## Plane Detection

Now, on line 38, add ``` <ViroARPlaneSelector />``` and reload. Save and reload test bed. You should see multiple planes detected as you move your device over different flat surfaces:
![Plane detected on floor](https://dev-to-uploads.s3.amazonaws.com/i/5ll1hisp6amudjh8065z.PNG)

Now, replace ```jsx <ViroARPlaneSelector />``` with ```jsx 
<ViroARPlaneSelector>
  <Viro3DObject
    source={require('./res/emoji_smile/emoji_smile.vrx')}
    position={[0, .1, 0]}
    scale={[.2, .2, .2]}
    type="VRX"
    dragType="FixedDistance" onDrag={()=>{}} />
</ViroARPlaneSelector>
```
Save, and load up another test bed. Now, when you tap a plane with your finger, all planes should disappear and a 3D object should be generated on the plane that was tapped.

![Plane detected on floor](https://dev-to-uploads.s3.amazonaws.com/i/glk9gacl2nkp789067zn.PNG)

![Tapped plane produced floating 3D smiley face](https://dev-to-uploads.s3.amazonaws.com/i/usbgfr726ur6mo81em3n.PNG)

Now replace 
```jsx 
<ViroARPlaneSelector>
  <Viro3DObject
    source={require('./res/emoji_smile/emoji_smile.vrx')}
    position={[0, .1, 0]}
    scale={[.2, .2, .2]}
    type="VRX"
    dragType="FixedDistance" onDrag={()=>{}} />
</ViroARPlaneSelector>
```

with ```jsx
        <ViroNode
          position={[0, 0, -1]}
          dragType="FixedToWorld"
          onDrag={() => {}}
        >
          <Viro3DObject
            source={require('./res/emoji_smile/emoji_smile.vrx')}
            position={[0, 0.1, 0]}
            scale={[0.2, 0.2, 0.2]}
            type="VRX"
          />
        </ViroNode>
```
Save, and load up another test bed. Note how dragging a 3D object around moves along detected places/surfaces.
![Smiley on floor](https://dev-to-uploads.s3.amazonaws.com/i/tqqyioabos3m6834j6nh.PNG)

![Dragged/Moved smiley on floor](https://dev-to-uploads.s3.amazonaws.com/i/2ouh9dtfr6ry7jqrvokt.PNG)

## Particles 

Now, let's add [particles](https://blog.viromedia.com/how-to-use-particles-to-enhance-your-ar-app-using-arkit-react-native-6c55c0278028)!

First, [download the particles res.zip file](https://s3-us-west-2.amazonaws.com/viro/Assets/Particles/res.zip), unzip it, and add the unzipped contents to your `/ViroSample/js/res/`.

Now, replace the code in HelloWorldSceneAR.js with the following:
```jsx
'use strict';

import React, { Component } from 'react';
import {StyleSheet} from 'react-native';
import PropTypes from 'prop-types';

import {
  ViroSceneNavigator,
  ViroARScene,
  ViroNode,
  ViroAmbientLight,
  ViroDirectionalLight,
  ViroText,
  ViroAnimations,
  ViroParticleEmitter,
  Viro3DObject,
} from 'react-viro';

'use strict';
const createReactClass = require('create-react-class');
const MainScene = createReactClass({

  getInitialState() {
    return {
    };
  },

  render: function() {
    return (
     <ViroARScene>
      <ViroAmbientLight color={"#aaaaaa"} />
      <ViroDirectionalLight color="#ffffff" direction={[0,-1,-.2]}/>

      <ViroNode position={[0,-.5,-1]} scale={[.5,.5,.5]} dragType="FixedToWorld" onDrag={()=>{}}>
         <Viro3DObject
           source={require('./res/object_bday_cake/object_bday_cake.vrx')}
           type="VRX"
         />

         <ViroNode position={[0.18,.67,0.004]} scale={[.4,.4,.4]}>
             <ViroParticleEmitter
               duration={1200}
               visible={true}
               run={true}
               loop={true}
               fixedToEmitter={false}

               image={{
                 source:require("./res/particle_fire.png"),
                 height:0.3,
                 width:0.3,
                 bloomThreshold:0.0
               }}

               spawnBehavior={{
                 particleLifetime:[500,500],
                 emissionRatePerSecond:[30, 40],
                 maxParticles:800
               }}

               particleAppearance={{
                 opacity:{
                   initialRange:[0.2, 0.2],
                   factor:"time",
                   interpolation:[
                     {endValue:0.2, interval:[0,200]},
                     {endValue:0.0, interval:[200,500]},
                   ]
                 },
                 scale:{
                   initialRange:[[1,1,1], [1,1,1]],
                   factor:"time",
                   interpolation:[
                     {endValue:[0,0,0], interval:[150,500]},
                   ]
                 },

               }}

               particlePhysics={{
                 velocity:{initialRange:[[0,.3,0], [0,.5,0]]}
               }}
             />
          </ViroNode>
        </ViroNode>
     </ViroARScene>
    );
  },
});

module.exports = MainScene;
```
Save, run `npm start` oncemore, re-open your new test bed, and voila! You will see a birthday cake with an animated flame at the top of the candle.

![Floating birthday cake with flame](https://dev-to-uploads.s3.amazonaws.com/i/a8wlotidr939h8wtyff6.PNG)

![Floating birthday cake with flame zoomed in on flame](https://dev-to-uploads.s3.amazonaws.com/i/e8svz260d5abhs2vje0v.PNG)

Now, let's add animated smoke to an object. Once more, replace the code in HelloWorldSceneAR.js with the following:
```jsx
'use strict';

import React, { Component } from 'react';
import {StyleSheet} from 'react-native';
import PropTypes from 'prop-types';

import {
  ViroSceneNavigator,
  ViroARScene,
  ViroNode,
  ViroAmbientLight,
  ViroDirectionalLight,
  ViroText,
  ViroAnimations,
  ViroParticleEmitter,
  Viro3DObject,
} from 'react-viro';

'use strict';
const createReactClass = require('create-react-class');
const MainScene = createReactClass({

  getInitialState() {
    return {
    };
  },

  render: function() {
    return (
     <ViroARScene>
      <ViroAmbientLight color={"#aaaaaa"} />
      <ViroDirectionalLight color="#ffffff" direction={[0,-1,-.2]}/>

      <ViroNode position={[0, 0, -2]} scale={[.5, .5, .5]} dragType="FixedToWorld" onDrag={()=>{}}>
        <Viro3DObject
          source={require('./res/emoji_angry_anim/emoji_angry_anim.vrx')}
          resources={[require('./res/emoji_angry_anim/emoji_angry_diffuse.png'),
                      require('./res/emoji_angry_anim/emoji_angry_normal.png'),
                      require('./res/emoji_angry_anim/emoji_angry_specular.png')]}
          type="VRX"
          animation={{name:"02", run:true, loop:true,}}
          />
          <ViroParticleEmitter
              position={[-.6, 0, .2]}
              scale={[.4, .2, .2]}
              duration={1100}
              delay={1100}
              visible={true}
              run={true}
              loop={true}
              fixedToEmitter={true}

              image={{
                source:require("./res/particle_smoke.png"),
                height:1,
                width:1,
              }}

              spawnBehavior={{
                particleLifetime:[500,500],
                emissionRatePerSecond:[200,200],
                maxParticles:200,
                spawnVolume:{
                  shape:"box",
                  params:[.7, .1, .1],
                  spawnOnSurface:false
                },
              }}

              particleAppearance={{
                opacity:{
                  initialRange:[0.0, 0.0],
                  interpolation:[
                    {endValue:0.4, interval:[0,200]},
                    {endValue:0.0, interval:[900,1500]}
                  ]
                },
              }}

              particlePhysics={{
                velocity:{initialRange:[[-2,2,0], [-2,-2,0]]},
                acceleration:{initialRange:[[0,0,0], [0,0,0]]}
              }}
          />

          <ViroParticleEmitter
              position={[.6, 0, .2]}
              scale={[.4, .2, .2]}
              duration={1100}
              delay={1100}
              visible={true}
              run={true}
              loop={true}
              fixedToEmitter={true}

              image={{
                source:require("./res/particle_smoke.png"),
                height:1,
                width:1,
              }}

              spawnBehavior={{
                particleLifetime:[500,500],
                emissionRatePerSecond:[200,200],
                maxParticles:200,
                spawnVolume:{
                  shape:"box",
                  params:[.7, .1, .1],
                  spawnOnSurface:false
                },
              }}

              particleAppearance={{
                opacity:{
                  initialRange:[0.0, 0.0],
                  interpolation:[
                    {endValue:0.4, interval:[0,200]},
                    {endValue:0.0, interval:[900,1500]}
                  ]
                },
              }}
              particlePhysics={{
                velocity:{initialRange:[[2,2,0], [2,-2,0]]},
                acceleration:{initialRange:[[0,0,0], [0,0,0]]}
              }}
          />
      </ViroNode>
     </ViroARScene>
    );
  },
});

module.exports = MainScene;
```
![Angry smiley face with smoke coming out of both ears](https://dev-to-uploads.s3.amazonaws.com/i/6lao5qz0vdax58luxp4n.PNG)

## Tweaking Parameters

Save, run `npm start`, and you should see an angry smiley face with smoke coming out of its ears intermittently.

Now, let's mess with a few settings. On line 88, if we change the `scale` parameter from its initial value of `[.4, .2, .2]` to `[.8, .4, .4]`, we can achieve more smoke coming out of the right side than the left:

![Smiley more smoke on right side](https://dev-to-uploads.s3.amazonaws.com/i/he5dwcfmou1s5bjw8uzd.PNG)

If we change the `duration` parameter on line 89, using a value of `2200` instead of `1100`, the smoke on the right side will be emitted for double the duration of the left side, so now they both are emitted at the same time, the right lasts twice as long as the left, and the left starts again just as the right stops. Then, when the left stops, the right starts. Thus, they alternate between being emitted concurrently and starting another emission as the other side ceases.

![Smiley smoke just on right side](https://dev-to-uploads.s3.amazonaws.com/i/j58qfno54uyetmy6iusi.PNG)

![Smiley smoke both sides](https://dev-to-uploads.s3.amazonaws.com/i/vqqfgmhp0q306wo5qm27.PNG)

![Smiley smoke just on left side](https://dev-to-uploads.s3.amazonaws.com/i/186148hno4qo82p5jb90.PNG)

Now, on line 104, change `emissionRatePerSecond:[200,200],` to `emissionRatePerSecond:[800,800],` and on line 105, change `maxParticles:200,` to `maxParticles:800,`. Now, the smoke coming out of the right side is significantly thicker and more filled in than that of the left: four times as many particles!

![Smiley more smoke on right side than left](https://dev-to-uploads.s3.amazonaws.com/i/vq6ofnqj3yof0kps5agg.PNG)

Now, on line 97, let's change `                source:require("./res/particle_smoke.png"),
` to `                source:require("./res/particles_flame.png"),
`. You will now see particles more reminiscent of fire coming out of the right side, whereas the left side remains smokey.

![Smiley with smoke coming out of left side and fire coming out of the right](https://dev-to-uploads.s3.amazonaws.com/i/ebdslmthnj8vgbupfw6t.PNG)

If you want to change the left side, just change the parameters within the `<ViroParticleEmitter></ViroParticleEmitter>` tags above, between lines 43-84. 

## Conclusion
ViroReact is a fast an easy way to set up AR on your smart phone. Today we went through initial setup, displaying text, displaying 3D objects, displaying particles, and changing the way the particles behave. For further customization, I recommend playing around with the image files in the `/res` folder with a photo editor such as Adobe Photoshop. For added creative inspiration, try adding [portals to your AR project](https://blog.viromedia.com/how-to-build-ar-portals-in-5-mins-w-react-native-viro-ar-b939850def94).