Shader material gives you a material as an output. You can apply this material to any mesh. It basically passes the data from your scene to the vertex and fragment shaders.
To get the shader material, the following class is called −
var myShaderMaterial = new BABYLON.ShaderMaterial(name, scene, route, options);
Consider the following parameters related to the shader material −
Name − A string, naming the shader.
Scene − The scene in which the shader is to be used.
Route − The route to the shader code in one of the three ways −
object - { vertex: "custom", fragment: "custom" }, used with BABYLON.Effect.ShadersStore["customVertexShader"] and BABYLON.Effect.ShadersStore["customFragmentShader"]
object - { vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }, used with shader code in <script> tags
string - "./COMMON_NAME",
The syntax mentioned in the end is used with external files COMMON_NAME.vertex.fx and COMMON_NAME.fragment.fx in the index.html folder.
Options − object containing attributes and uniforms arrays containing their names as strings.
The shader syntax with values look as shown below −
var shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, { vertex: "custom", fragment: "custom", }, { attributes: ["position", "normal", "uv"], uniforms: ["world", "worldView", "worldViewProjection", "view", "projection"] });
Attributes have to be in array form. These contain position, normal and uv which are vector3 3D floating point vectors.
vec2 − A two-dimensional vector of floating-point numbers.
vec3 − A three-dimensional vector of floating-point numbers.
mat4 − A matrix with 4 columns and 4 rows floating-point numbers.
gl_Position − It provides positional data for screen coordinates.
gl_FragColor − It provides colour data for the representation of a facet on screen.
The above are built in variables in GLSL language.
Since vertex positions need to be as accurate as possible, all floating-point numbers should be set as having high precision. This is done at the start of the code for each shader using – precision highp float. The precision highp float determines how much precision is used for a float.
The following demo is based on the first object method.
<!doctype html> <html> <head> <meta charset = "utf-8"> <title>BabylonJs - Basic Element-Creating Scene</title> <script src = "babylon.js"></script> <style> canvas {width: 100%; height: 100%;} </style> </head> <body> <canvas id = "renderCanvas"></canvas> <script type = "text/javascript"> //downloaded HDR files from :http://www.hdrlabs.com/sibl/archive.html var canvas = document.getElementById("renderCanvas"); var engine = new BABYLON.Engine(canvas, true); var createScene = function() { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.ArcRotateCamera( "Camera", Math.PI / 4, Math.PI / 4, 4, BABYLON.Vector3.Zero(), scene); camera.attachControl(canvas, true); var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene); BABYLON.Effect.ShadersStore["customVertexShader"] = "\r\n" + "precision highp float;\r\n" + "// Attributes\r\n" + "attribute vec3 position;\r\n" + "attribute vec2 uv;\r\n" + "// Uniforms\r\n" + "uniform mat4 worldViewProjection;\r\n" + "// Varying\r\n" + "varying vec2 vUV;\r\n" + "void main(void) { \r\n" + "gl_Position = worldViewProjection * vec4(position, 1.0);\r\n" + "vUV = uv;\r\n"+" } \r\n"; BABYLON.Effect.ShadersStore["customFragmentShader"] = "\r\n"+ "precision highp float;\r\n" + "varying vec2 vUV;\r\n" + "uniform sampler2D textureSampler;\r\n" + "void main(void) { \r\n"+ "gl_FragColor = texture2D(textureSampler, vUV);\r\n"+" } \r\n"; var shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, { vertex: "custom", fragment: "custom", }, { attributes: ["position", "normal", "uv"], uniforms: ["world", "worldView", "worldViewProjection", "view", "projection"] }); var mainTexture = new BABYLON.Texture("images/mat.jpg", scene); shaderMaterial.setTexture("textureSampler", mainTexture); shaderMaterial.backFaceCulling = false; var box = BABYLON.MeshBuilder.CreateBox("box", {}, scene); box.material = shaderMaterial; return scene; }; var scene = createScene(); engine.runRenderLoop(function() { scene.render(); }); </script> </body> </html>
The above line of code will generate the following output −
In this demo, we have used image mat.jpg. The images are stored in the images/ folder locally and are also pasted below for reference. You can download any image of your choice and use in the demo link.