Categories
Uncategorised

Adding Variants to a GLB model and displaying them using ThreeJS

(This article is taken from my Udemy course ‘The ThreeJS Cookbook’ coming Summer 2023. Get the course assets from GitHub. I recommend using VSCode and the Live Server extension when working along with the recipe )

If you’re creating a ThreeJS app for a store. You may be selling an item that comes in a variety of finishes. The GLB format has an extension that allows you to embed multiple materials for an object, then with code you can allow the user to switch materials to view the item with different finishes.

Before we get into coding this recipe take a look at complete > Materials > variants.html . Using the dropdown selector you can view the chair in one of four different finishes. The code reads the options directly from the model file. You can use the same technique in your own GUI.

Before we look at the code let’s look at how we create a glb file that includes material variants. We’re going to use Blender, I’m using Blender 3.5 but anything from version 3.3 will be fine. You can download Blender for free at blender.org. Blender is a complex application but there are loads of tutorials available both free and paid.

In this recipe I assume you have some knowledge of Blender and I focus exclusively on variants. To keep things simple we’ll just create materials that change the colour of the default cube. 

First open Blender and choose the General new project. You’ll get a 2m grey cube centre screen. Right-click on the light and camera and choose Delete. Lights and cameras will be added using code when we create the ThreeJS app to display our model.

Using the buttons at the top right set the display to Material Preview mode.

Select Edit > Preferences…. Select Add-ons and type ‘gltf’ in the Search field. Make sure that for the Import-Export: glTF 2.0 format add-on that the Material Variants checkbox is checked. You can close the preferences panel now.

Select the Cube. Select the Materials tool, the chequered sphere. Click the white on black Material word and rename it Grey. 

Expand the Sidebar and select glTF Variants. In the new panel press the Add Material Variant button.

Rename the variant Grey.

In the materials panel slide down to find glTF Material Variants. Press the Add a new Variant Slot button.

The new variant should take the name you’ve renamed Grey.

Click the + button to add a new material. Rename it red and set the Base Color. 

Now select Grey and press the – button. You can now use the glTF Variants Sidebar tool to add a new variant. Rename it Red and then use the Material glTF Material Variants panel to Add a new Variant Slot.

Repeat from adding a new material for each variant. 

To test whether the variants are working, use the glTF Variants Sidebar panel. Select the variant you’re interested in and press the Display Variant button. You should see the cube change to your chosen material. Now choose File > Export > glTF 2.0 (.glb/.gltf), select a file location and name.

Time to focus on code. The assets include the chair we’ve seen that includes variants with different textures and roughness. We’ll use that in the coding. But feel free to use your model if you prefer.

Before we start coding take a look at a glTF formatted file assets > variant-cube.gltf. This is the text formatted version. Usually you save a file in binary format, a glB file. But it is easy to read a glTF file in any text editor. First notice the extensions object, and see this includes KHR_materials_variants. This object contains a variants array. Each entry in the array is an object with a single property, name. 

{
   "asset":{
      "generator":"Khronos glTF Blender I/O v3.5.30",
      "version":"2.0"
   },
   "extensionsUsed":[
      "KHR_materials_variants"
   ],
   "extensionsRequired":[
      "KHR_materials_variants"
   ],
   "extensions":{
      "KHR_materials_variants":{
         "variants":[
            {
               "name":"Red"
            },
            {
               "name":"Yellow"
            },
            {
               "name":"Default"
            }
         ]
      }
   },

The glTF structure includes, a scene and scenes array. Scene is simply and index into the scenes array. A scene includes a nodes array, which in this case has a single index. 

   "scene":0,
   "scenes":[
      {
         "name":"Scene",
         "nodes":[
            0
         ]
      }
   ],

The nodes array includes a series of objects. Here we have a properties mesh, an index into the meshes array and a name.

   "nodes":[
      {
         "mesh":0,
         "name":"Cube"
      }
   ],

Now the meat of our variants data. The materials array includes a series of objects. Here simply setting the pbrMetallicRoughness.baseColorFactor, metallicFactor and roughness

   "materials":[
      {
         "doubleSided":true,
         "name":"Red",
         "pbrMetallicRoughness":{
            "baseColorFactor":[
               0.8000000715255737,
               0.011036576703190804,
               0.00618034927174449,
               1
            ],
            "metallicFactor":0,
            "roughnessFactor":0.5
         }
      },
      {
         "doubleSided":true,
         "name":"Yellow",
         "pbrMetallicRoughness":{
            "baseColorFactor":[
               0.8000000715255737,
               0.6312862634658813,
               0,
               1
            ],
            "metallicFactor":0,
            "roughnessFactor":0.5
         }
      },
      {
         "doubleSided":true,
         "name":"Material",
         "pbrMetallicRoughness":{
            "baseColorFactor":[
               0.800000011920929,
               0.800000011920929,
               0.800000011920929,
               1
            ],
            "metallicFactor":0,
            "roughnessFactor":0.5
         }
      }
   ],

The meshes array contains each mesh in every scene. But in this simple example there is only the single Cube. Notice that the Cube has an extensions object, which contains a KHR_materials_variants object. This in turn contains a mappings array. Each entry in the mappings array contains a material index and a variants array containing a single index in this instance. 

   "meshes":[
      {
         "name":"Cube",
         "primitives":[
            {
               "attributes":{
                  "POSITION":0,
                  "TEXCOORD_0":1,
                  "NORMAL":2
               },
               "extensions":{
                  "KHR_materials_variants":{
                     "mappings":[
                        {
                           "material":0,
                           "variants":[
                              0
                           ]
                        },
                        {
                           "material":1,
                           "variants":[
                              1
                           ]
                        },
                        {
                           "material":2,
                           "variants":[
                              2
                           ]
                        }
                     ]
                  }
               },
               "indices":3,
               "material":2
            }
         ]
      }
   ],

The code we need to generate should read root level extensions object, look for KHR_materials_variants and read the names of the variants. Using this to populate a GUI. Then we need a function that given a variant name, finds the index of this variant. Then iterates over each mesh in the scene, checks if the mesh has a KHR_materials_variants extension. If it has then it checks the mappings object to see if its variants array includes the variant index found for the name given. If it does then we get the material using the index and apply it to the mesh. If that sounds complex it might be clearer once we’ve added the code. 

We’ll source the variant names from the root level extension first. First we create a new GUI using the lil-gui library. Then we grab a reference to the gltf.parser object. More about that later. After parsing, extensions are stored in the userData object for each Object3D instance in the hierarchy. We check if gltfExtensions is a gltf.userData property. If it is we attempt to assign the extension KHR_materials_variants. At this stage variantsExtension is either null if missing or a reference to the data. 

gui = new GUI();

const parser = gltf.parser;

let variantsExtension;

if ( 'gltfExtensions' in gltf.userData ){
  variantsExtension = gltf.userData.gltfExtensions[ 'KHR_materials_variants' ];
}

If variantsExtension is not null then we use the JavaScript array method map to return a new array containing just an array of names. Then we add a select control. The state object is defined at the start of the script with a single property variant.

if (variantsExtension != null){
   const variants = variantsExtension.variants.map( ( variant ) => variant.name );
   const variantsCtrl = gui.add( state, 'variant', variants ).name( 'Variant' );
}

If you try the app now you should get a list of variant names in the GUI. 

Now we need a function to call when a name is selected in the GUI. It needs a reference to the scene, the parser we stored, the variants extension and the variant name. We need to convert the variant name into an index, so we use the findIndex method of a JavaScript array. 

function selectVariant( scene, parser, extension, variantName ) {

   const variantIndex = extension.variants.findIndex( ( v ) => v.name.includes( variantName ) );

Now we can traverse the scene. We do this asynchronously since a scene may contain a lot of Object3D instances and we don’t want to hold up processing. The callback retrieves each object in the gltf scene. We’re only interested in meshes, so we check if the isMesh flag is set. And we need userData to contain a gltfExtensions object. If either of these checks fail we return from the callback for the current object and move on to the next. Then we assign meshVariantDef as the gltfExtensions object KHR_materials_variants. That’s the extension stored in the object definition. The one we saw that includes mappings.

scene.traverse( async ( object ) => {

if ( ! object.isMesh || ! object.userData.gltfExtensions ) return;

const meshVariantDef = object.userData.gltfExtensions[ 'KHR_materials_variants' ];

If meshVariantDef is null then we can also return. Now we store the current material as userData.originalMaterial, assuming this hasn’t already been set.

if ( ! meshVariantDef ) return;

if ( ! object.userData.originalMaterial ) {

   object.userData.originalMaterial = object.material;

}

To find the mapping we’re interested in we use the find method of a JavaScript array, searching through the variants array for one that includes the variantIndex.

const mapping = meshVariantDef.mappings
                .find( ( mapping ) => mapping.variants.includes( variantIndex ) );

If we find a mapping, we use the parser method getDependency, use material as the property and the mapping.material index. This returns the material in the materials array with the given index. The parser object also contains a method, assignFinalMaterial that ensures the material is correctly assigned and compiled. If mapping is not found then we restore the original material from the one we stored in userData. We also call render because this app doesn’t use a render loop. Instead we call render on each change.

if ( mapping ) {

   object.material = await parser.getDependency( 'material', mapping.material );
   parser.assignFinalMaterial( object );

} else {

   object.material = object.userData.originalMaterial;

}

render();

It just remains to update our GUI code to call this function on a change event. 

variantsCtrl.onChange( ( value ) => selectVariant( scene, parser, variantsExtension, value ) );

Now the GUI is populated and on a change event the variant name is passed to the selectVariant method. 

Variants are a great solution for allowing users to view an object using a variety of finishes.

Categories
Uncategorised

May the 4th Be With You!

It’s Star Wars Day. My courses are at Udemy’s Best Price for the next few days. Grab yourself a bargain and May the Fourth be with you!!

The Complete Guide to Unity’s Universal Render Pipeline

With URP to become Unity’s default pipeline learn how to use it in this course by the author of Unity’s URP e-books

https://www.udemy.com/course/unity-urp/?couponCode=MAY23_FOURTH

Create WebXR, VR and AR app, using the Wonderland Engine

Wonderland is a high performance engine for WebXR apps. The editor makes creating VR experiences super-easy. In this course I show you how.

https://www.udemy.com/course/webxr-wle/?couponCode=MAY23_FOURTH

Model viewer: Web 3D made easy

Model-viewer is a web component created by Google. It makes displaying user interact-able 3D models on a web page a walk in the park. In this course I show you how.

https://www.udemy.com/course/model-viewer/?couponCode=MAY23_FOURTH

The Beginners Guide to 3D Web Game Development with ThreeJS

Learn to write JavaScript code while having fun making 3D web games using the most popular Open Source WebGL library ThreeJS

https://www.udemy.com/course/beginners-3d-web-game-development-with-threejs/?couponCode=MAY23_FOURTH

Learn to write Unity Compute Shaders

Learn to harness the power of the GPU for processing intensive jobs.

https://www.udemy.com/course/compute-shaders/?couponCode=MAY23_FOURTH

Learn to Create WebXR, VR and AR, experiences with ThreeJS

Learn how to create VR and AR experiences that work directly from the browser, using the latest API from Google and Amazon and our favourite Open Source WebGL library, ThreeJS

https://www.udemy.com/course/learn-webxr/?couponCode=MAY23_FOURTH

Learn Unity Shaders from Scratch

Learn the black-art of Unity shaders in this comprehensive course on HLSL. Shaders for both the Built-in Render Pipeline and URP are included.

https://www.udemy.com/course/learn-unity-shaders-from-scratch/?couponCode=MAY23_FOURTH

Learn GLSL Shaders from Scratch

Learn how to harness the power of the GPU in your web pages by learning to code GLSL shaders.

https://www.udemy.com/course/learn-glsl-shaders-from-scratch/?couponCode=MAY23_FOURTH

Create a 3D Multi-Player Game using ThreeJS and SocketIO

Learn how to use nodeJS, socketIO and ThreeJS to create a 3d multi-player game

https://www.udemy.com/course/create-a-3d-multi-player-game-using-threejs-and-socketio/?couponCode=MAY23_FOURTH

Create HTML5 Games using Adobe Animate

Adobe Animate used to be Flash. Learn how you can use your Flash skills to create HTML5 games that use no plugins.

https://www.udemy.com/course/create-html5-games-using-adobe-animate/?couponCode=MAY23_FOURTH

Create a 3D Car Racing Game with ThreeJS and CannonJS

Learn to combine the physics engine CannonJS and ThreeJS to create a fun car racing game

https://www.udemy.com/course/create-a-3d-car-racing-game-with-threejs-and-cannonjs/?couponCode=MAY23_FOURTH

Create a 3D RPG Game with ThreeJS

Learn how to harness the ThreeJS library to create a 3D RPG game

https://www.udemy.com/course/create-a-3d-rpg-game-with-threejs/?couponCode=MAY23_FOURTH

HTML5 Game Development: Beginner to Pro

Learn how to create 2D games that work in the browser. From card games to puzzle games to action games.

https://www.udemy.com/course/html5-game-development-beginner-to-pro/?couponCode=MAY23_FOURTH

JavaScript in 12 Easy Lessons

New to JavaScript or coding then this FREE course is for you

https://www.udemy.com/course/javascript-in-12-easy-lessons/?referralCode=086EC53154E29AD37EA1

The ThreeJS Primer

New to ThreeJS then this FREE course is for you

https://www.udemy.com/course/the-threejs-primer/?referralCode=ABB270C1AE32EF9E7174

Categories
Uncategorised

Happy Lunar New Year!

Just an update to my 36,000 students. I’m currently developing a course teaching how to get the best from Unity’s Universal Render Pipeline (URP). It’s based on the e-book I wrote for Unity.

Introduction to the Universal Render Pipeline for Advanced Unity Creators.

The course, aimed more at intermediate level, is going well and should be live in March.

If you plan to do the course then take a look at these two tutorial videos on YouTube as a taster to what to expect.

Converting custom shaders to URP

Make your shaders Scriptable Render Pipeline Batcher compatible. This step by step video tutorial will show you how to convert a custom unlit Built-in shader to the Universal Render Pipeline (URP).

Three ways to use URP Renderer Features

A Renderer Feature is a C# script that can be used at any stage in the Render Pipeline to affect the final render. Renderer Features provide a great way of adding custom rendering effects to your scene, often with no code required, making them artist-friendly.

Nik Lever 22 Jan 2023

Categories
Uncategorised

Nik Lever’s New Year Sale

Hope you’re all enjoying the holidays. To celebrate the New Year. All my courses are available at the lowest price Udemy will allow this week with the coupon code NEWYEAR23 . Read through to find two FREE courses

Create WebXR, VR and AR app, using the Wonderland Engine

Wonderland is a high performance engine for WebXR apps. The editor makes creating VR experiences super-easy. In this course I show you how.

https://www.udemy.com/course/webxr-wle/?couponCode=NEWYEAR23

Model viewer: Web 3D made easy

Model-viewer is a web component created by Google. It makes displaying user interact-able 3D models on a web page a walk in the park. In this course I show you how.

https://www.udemy.com/course/model-viewer/?couponCode=NEWYEAR23

The Beginners Guide to 3D Web Game Development with ThreeJS

Learn to write JavaScript code while having fun making 3D web games using the most popular Open Source WebGL library ThreeJS

https://www.udemy.com/course/beginners-3d-web-game-development-with-threejs/?couponCode=NEWYEAR23

Learn to write Unity Compute Shaders

Learn to harness the power of the GPU for processing intensive jobs.

https://www.udemy.com/course/compute-shaders/?couponCode=NEWYEAR23

Learn to Create WebXR, VR and AR, experiences with ThreeJS

Learn how to create VR and AR experiences that work directly from the browser, using the latest API from Google and Amazon and our favourite Open Source WebGL library, ThreeJS

https://www.udemy.com/course/learn-webxr/?couponCode=NEWYEAR23

Learn Unity Shaders from Scratch

Learn the black-art of Unity shaders in this comprehensive course on HLSL. Shaders for both the Built-in Render Pipeline and URP are included.

https://www.udemy.com/course/learn-unity-shaders-from-scratch/?couponCode=NEWYEAR23

Learn GLSL Shaders from Scratch

Learn how to harness the power of the GPU in your web pages by learning to code GLSL shaders.

https://www.udemy.com/course/learn-glsl-shaders-from-scratch/?couponCode=NEWYEAR23

Create a 3D Multi-Player Game using ThreeJS and SocketIO

Learn how to use nodeJS, socketIO and ThreeJS to create a 3d multi-player game

https://www.udemy.com/course/create-a-3d-multi-player-game-using-threejs-and-socketio/?couponCode=NEWYEAR23

Create HTML5 Games using Adobe Animate

Adobe Animate used to be Flash. Learn how you can use your Flash skills to create HTML5 games that use no plugins.

https://www.udemy.com/course/create-html5-games-using-adobe-animate/?couponCode=NEWYEAR23

Create a 3D Car Racing Game with ThreeJS and CannonJS

Learn to combine the physics engine CannonJS and ThreeJS to create a fun car racing game

https://www.udemy.com/course/create-a-3d-car-racing-game-with-threejs-and-cannonjs/?couponCode=NEWYEAR23

Create a 3D RPG Game with ThreeJS

Learn how to harness the ThreeJS library to create a 3D RPG game

https://www.udemy.com/course/create-a-3d-rpg-game-with-threejs/?couponCode=NEWYEAR23

HTML5 Game Development: Beginner to Pro

Learn how to create 2D games that work in the browser. From card games to puzzle games to action games.

https://www.udemy.com/course/html5-game-development-beginner-to-pro/?couponCode=NEWYEAR23

JavaScript in 12 Easy Lessons

New to JavaScript or coding then this FREE course is for you

https://www.udemy.com/course/javascript-in-12-easy-lessons/?referralCode=086EC53154E29AD37EA1

The ThreeJS Primer

New to ThreeJS then this FREE course is for you

https://www.udemy.com/course/the-threejs-primer/?referralCode=ABB270C1AE32EF9E7174

Categories
Uncategorised

My Unity URP e-book is published today!

URP for Advanced Unity Creators

Download this valuable guide to fully leverage the benefits of URP for professional game development. I hope that you find the e-book helpful.

To celebrate the publication of my Unity URP e-book my Udemy Unity courses are available for just $10.99 for the next few days.

Unity Compute Shaders
Learn to Write Unity Compute Shaders

Learn to Write Unity Compute Shaders

Unity Shaders
Learn to Write Unity Shaders from Scratch

Learn to Write Unity Shaders from Scratch

Includes URP shaders and ShaderGraph

Categories
Uncategorised

Three.JS Tips

In July 2022 I posted a Three.JS Tip a day. Here are articles about these tips.

10 Three.JS Tips

1o More Three.JS Tips

Another 1o More Three.JS Tips and a bonus tip

Categories
Uncategorised

Create installable Oculus Quest app using PWAs

I’ve added a new section to my ‘Learn to create WebXR, VR and AR, experiences with Three.JS‘ course. Learn how to make your WebXR website into an installable app, using Progressive Web Apps (PWA) technology. You’ll start with a super simple example. Then learn how to package it using PWABuilder. Then learn how to use Oculus Developer Hub to deploy your app to your headset. Finally you’ll learn to create, package and deploy a WebXR example.

Course is available at the lowest price Udemy will allow until Tuesday 12th June.https://www.udemy.com/course/learn-webxr/?couponCode=OCULUS_PWA

Categories
Uncategorised

Beginners Guide to 3D Web Game Development with Three.JS

My ‘Beginners Guide to 3D Web Game Development with Three.JS’ is just $9.99 for the next few days. It’s a great introduction to an amazing library even if you aren’t interested in the game side.

https://bit.ly/3js-jun-22

The JavaScript programming language is probably the most popular programming language in the world. Companies all around the global require developers who are proficient with this language. In this course I teach you about the language then apply your new skills to create three games.

Before you write your first game you’ll use your new JavaScript skills and the popular Open Source library, ThreeJS to create several simple online 3D apps. Once you know enough about the ThreeJS library it’s time to create your first game. The first game is a simple game. Here you’ll learn about loading assets, moving assets, user input and collision testing.

The course builds on the skills you learn. The next game is a shooter and you learn how to animate a player avatar, how to control NPC characters so they patrol on a random path using navigation meshes and path-finding. You’ll learn how to control the avatar with a keyboard or gamepad and on a mobile using an on-screen controller. You’ll learn how to fire bullets at the enemy and add AI to the NPCs so they fire back. All the key ingredients of a shooter game.

The last game uses the physics engine CannonJS to control the motion of balls in an Eight-ball Pool game.

Along the way you’ll learn to use the 3D application program Blender to prepare your 3D assets for the games you develop.

Once you’ve completed the course you’ll be super ready for any challenges an employer throws your way when writing JavaScript code. But the main thing is you’ll have developed your much in-demand skills while having fun making games.

Categories
Uncategorised

My GLSL course is just $9.99 this week

https://www.udemy.com/course/learn-glsl-shaders-from-scratch/?couponCode=MAY22_BEST

In this course we’re going to look at GLSL ( OpenGL Shading Language) to create amazing effects.

Maybe you are

  • a designer who has seen some terrific, cutting edge websites using cool transitions and wondered how it was done. You may have heard about WebGL and know that you can use some simple THREE.js code to do some remarkable things.
  • a developer trying to visualise some data in a striking way.
  • a game developer wanting to add some custom effects to your 3d objects surfaces.

GLSL is how you can use OpenGL to display a surface. The code syntax is based on the C language, but fear not, we will assume you have literally no knowledge of this language at all and we will, as the course title states, learn this from scratch. GLSL uses the GPU ( the Graphics Processing Unit) to handle multiple programs at the same time, so it is unbelievably fast.

In the course we will be writing code for the browser, because this allows us to focus on GLSL, without needing to worry about installing any additional software. We will be using the THREE.js WebGL library and CodePen so you can instantly edit the source and see the results, needing nothing other than a browser to experiment. Only a small amount of Javascript is used but this will be explained thoroughly as it comes along. But you can also use what you learn about GLSL in a C/C++/C# program or a Python program.

We will start from really simple examples and progress slowly through each stage of developing a custom shader. You will be able to play with the shader code on CodePen, so you can experiment with different values to see the impact it has on the end result.

GLSL shaders are split into vertex shaders and fragment shaders and we will focus initially on the fragment shader, working essentially in a 2d environment. With dozens of shaders in the course resources you will learn the language in gentle stages.

Creating your own shaders means understanding the GLSL language and that is the aim of the course. You could search for a suitable shader on ShaderToy, ShaderFrog or glslViewer and then try to adapt the code. But without knowing the language you’re going to find that difficult to do. To really be effective you need to know about the GLSL language, shaping functions, tiling, polar coordinates and lighting calculations. To do this you will need to follow along with the course and complete the many challenges suggested. At the end you will then be able to create any shader that you can imagine.

As usual there is a 30 day money back guarantee. So you have nothing to lose. Let’s get shading today!

What students say

“I came here interested in making a custom lighting shader on an obj model, and I really found answers to my questions and more. The two faced aspect of the lessons and the CodePen sketches [are] great. I thank you !”

A great course! Methodical, step by step explanations not only of the GLSL but also of the general theory behind shaders, usable with any shader system. Essential if you are into computer graphics or generative art. Thank you!”

“I’ve tried to pick up shaders in the past but found it quite difficult. Unlike other resources I’ve found, this course was the course that finally helped me get a much better grasp of glsl. It is well structured and very informative. I would recommend it to anyone looking to pick up glsl.”

“This is exactly what I needed. I am a web designer/developer with design background and a good a good deal of javascript experience I’m trying to get into 3D visualizations for web. Since GLSL is written in C language it had been a huge barrier. I totally recommend this course to anyone having problems to get a clear understanding of GLSL.

“So far this course has been really amazing. Very few courses on shaders really take the time to explain the math behind what’s happening in a way that let’s “non-math” folk develop an intuition for it. Great job!”

“I was always intimidated by the idea of GLSL, even though I’m an advanced front-end developer. I’ve always been terrible at math; and yet Nik’s style of teaching made me understand everything very intuitively and I’m so comfortable with shaders now. I’ve bought 60+ courses on Udemy; and I quit most of them after a couple videos. This one has me hooked on my chair until I finish everything! Coding along to this course is fun and Nik’s challenges feel very rewarding to either solve or understand through his crystal clear explanation!”

“This is a perfect course for anyone wanting to learn about GLSL in a gradual manner. The instructor makes sure to spend enough time in the basic functions of GLSL, so students can get a proper understanding before moving on to the next concept. I had found GLSL a bit daunting in the past because examples would get out of hand very quickly, so I really appreciate this course’s approach.

Categories
Uncategorised

Two new URP videos for Unity

I’ve been working with the URP team at Unity 3D since September 2021. The initial project was an e-book, a guide for those making the transition from the Built-in render pipeline (BRP) to the newish Universal Render Pipeline (URP) it is due for release around Easter 2022, to link to the launch of Unity 2021.2, LTS. To help launch the e-book I’ve completed two videos. You can see an early version of these by following this link. The GitHub repo is here.

If you want to see more about using URP to create shaders check out my Unity shader course, you’ll find a discount link on this page.