Bringing the world of 3D Graphics to Salesforce with WebGL integration
WebGL (Web Graphics Library) is a JavaScript API for rendering interactive 3D and 2D graphics within any compatible web browser without the use of plug-ins. WebGL introduces an API that closely conforms to OpenGL ES 2.0 that can be used in HTML5 <canvas>
elements.
WebGL programs consist of control code written in JavaScript and shader code (GLSL) that is executed on a computer's Graphics Processing Unit (GPU). WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background
This article will simply demonstrate the basic use of WebGL in Salesforce and possible use cases. It's assumed that you already have an understanding of the mathematics involved in 3D graphics, and this article doesn't pretend to try to teach you 3D graphics concepts itself.
But, why 3D Graphics into Salesforce?
Yeah! we obviously won't be looking at Accounts, Opportunities, Cases etc. in 3-Dimensions. There is no need of it :). With WebGL integration we are looking at a larger picture where Salesforce platform could be used to build a cloud-based 3D-PLM (Product Lifecycle Management) solution. Some possible use cases would be:
- A Gaming Company - where designers can share, discuss, review and comment on the 3D models (WebGL supported format) that they work on for a project
- Healthcare and Scientific R&D - can have an interactive CMS built on top of Salesforce where researchers and scientists can collaboratively store, share and study various Molecular structure of medicines, Human Anatomy, Physiology, Genetics, Clinical trials of new medicines etc.
- An Automobile Company - can keep track of the automobile parts that they manufacture/market/use in other products from design to manufacturing to quality to marketing
Demo - Its WebGL and not an embedded video player
WebGL Frameworks
Frameworks are available to create WebGL content quickly and easily without building from the ground up. Below are Javascript based Frameworks with Native 1.0 WebGL Implementation
- Three.js
- Whitestorm.js
- Babylon.js
- Clara.io
- CopperLicht
- JanusWeb
- OSG.JS
- PlayCanvas
Three.js
Three.js is the world's most popular JavaScript framework for displaying 3D content on the web, providing you with the power to display incredible models, games, music videos, scientific and data visualisations, or pretty much anything else you can imagine, right in your browser and on your smartphone
The Three.js library is a single JavaScript file. It can be included within a web page by linking to a local or remote copy
The following code creates a scene, adds a camera and a FBX Model to the scene, creates a WebGL renderer and adds its viewport in the document.body element.
<apex:page standardController="Case">
<html lang="en">
<head>
<title>WebGL Salesforce Integration</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/>
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a {
color: #046;
font-weight: bold;
}
</style>
</head>
<body>
<div id="info">
<a href="" target="_blank" rel="noopener">Motion Physics for Character CHX-AX-3BG</a>
</div>
<script src=""></script>
<script src=""></script>
<script src=""></script>
<script src=""></script>
<script src=""></script>
<script src=""></script>
<script>
if ( WEBGL.isWebGLAvailable() === false ) {
document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
var container, stats, controls;
var camera, scene, renderer, light;
var clock = new THREE.Clock();
var mixer;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( 100, 200, 300 );
controls = new THREE.OrbitControls( camera );
controls.target.set( 0, 100, 0 );
controls.update();
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 200, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 200, 100 );
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = - 100;
light.shadow.camera.left = - 120;
light.shadow.camera.right = 120;
scene.add( light );
// scene.add( new THREE.CameraHelper( light.shadow.camera ) );
// ground
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// model
var loader = new THREE.FBXLoader();
loader.load( 'https://threejs.org/examples/models/fbx/Samba Dancing.fbx', function ( object ) {
mixer = new THREE.AnimationMixer( object );
var action = mixer.clipAction( object.animations[ 0 ] );
action.play();
object.traverse( function ( child ) {
if ( child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
} );
scene.add( object );
} );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// stats
stats = new Stats();
container.appendChild( stats.dom );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if ( mixer ) mixer.update( delta );
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
</apex:page>