Experimenting with Three.js shaders and the ShaderMaterial

Lately when using Three.js I have needed some very specific material qualities that the built in Three.js materials did not allow for so I have started experimenting with the Three.ShaderMaterial . This material allows you to write you own GLSL shaders for Three.js. My hope is that I can get a good understanding of GLSL and implement some of my own shaders and materials in Three.js even with my limited math skills and no prior experience with GLSL.

On this page I will link to some of my own Three.ShaderMaterial experiments and try to update it as I learn more.

You may also want to take a look at my implementation of a three.js car paint shader (a recreartion of the Radeon 9700 demo).

NOTE: these examples are using R70 of THREE.js and material implementation seems to have changed a bit since the R70 release, so some of these may not work on the current release of THREE.js

Custom Mesh Shader Materials

On most of my experiments there are buttons under "Source" to view both the vertex shader source and the fragment shader source.

  • Basic color

    basic color shader

    This is the most basic of shaders, simple applying a color via the fragment shader.

  • Vertex position color

    Vertex position color shader

    Takes the fragment color from the vertex position. Simple experiment trying to understand how to send varyings from the vertex shader to the fragment shader

  • Uv position color

    Uv position color shader

    Takes the fragment color from the uv position. Again trying to understand how to send varyings from the vertex shader to the fragment shader

  • ...

Gulp imagemin with the pngquant plugin

I found it hard to find an example of how to use gulp-imagemin with a plugin, specifically in my case, the imagemin-pngquant plugin .
The difference seen between using compressing a .png with the default compressor that is included in gulp-imagemin and pngquant was substantial.
I was converting a 100px x 100px 21.3KB .png. The png compressor that comes with gulp-imagemin (optipng) produced a file that was 19KB, but using pngquant produced a file that was 3.63KB. Quite a large difference.
Obviously it is worth using, but examples I found on the interwebs all seems to be wrong. After a bit of trial and error I got it working and though I would post it here for future reference.
Keep in mind, I did not set any of the options for each case.
In the future I will probably look at using gulp-image instead as it seems to also support pngquant and there is actually some decent documentation..

 var imagemin = require('gulp-imagemin'); 
var pngquant = require('imagemin-pngquant');

var inFiles = "src/images/*.png";
var outFiles = "build/images";

// Standard imagemin
gulp.task('compressStandard', function(){
return gulp.src(inFiles)

// Standard imagemin with imagemin options
gulp.task('compressStandard', function(){
return gulp.src(inFiles)

// imagemin using pngquant plugin
gulp.task('compressQuant', function(){
return gulp.src(inFiles)

// Using quant plugin and sending options
// Send the pngquant options object directly to the function
// the second argument send to the imagemin function is the imagemin options object
gulp.task('compressQuantOptions', function(){

Three.js easy round / circular particles

Today I came across a question on stackoverflow asking how to make round particles in Three.js ( Three.js - give particles round form ).
I have seen questions like this a few times and the answers always seem to be to load an image and use it as a texture. People seem to forget that you can use a canvas as a texture map and you can draw pretty much what ever you want on a canvas.
I have demonstrated this before when someone asked " Is it possible to use 2 textures (one on top of the other) as a Material without using custom Shaders? ". See the fiddle HERE .

Basically, all you have to do is create a function that draws your canvas and returns a THREE.Texture object, assigning this THREE.Texture object to the map property of the Material.

Here is a function that creates a circle on a canvas:

 function createCircleTexture(color, size) { 
var matCanvas = document.createElement('canvas');
matCanvas.width = matCanvas.height = size;
var matContext = matCanvas.getContext('2d');
// create texture object from canvas.
var texture = new THREE.Texture(matCanvas);
// Draw a circle
var center = size / 2;
matContext.arc(center, center, size/2, 0, 2 * Math.PI, false);
matContext.fillStyle = color;
// need to set needsUpdate
texture.needsUpdate = true;
// return a texture made from the canvas
return texture;

Here is how to use it:

 var pointMaterial = new THREE.PointsMaterial({ 
size: 20,
map: createCircleTexture('#00ff00', 256),
transparent: true,
depthWrite: false

depthWrite must be set to false as per THIS issue on stack.

Tango messenger app: Why you shouldn't use it

The Tango messenger app is probably the worst app for privacy I have ever come across. If you have any concern for your privacy at all, you should not use it. Below I will list just a few of the things that concern me as far as privacy and the Tango app.

  • Tango saves all your contacts to their server

    When you install the app on your phone, it seems to try to sync with all the contacts in your phone. Although there is a setting to stop this called "Save Address Book to Tango" under "App Settings", this setting is on by default and by the time you have installed the app and want to turn this off, it is too late and your contacts have already been saved to their servers.

  • It sometimes allows people to see your phone number

    This one really surprised me and it has happened about 3 times to me. I have opened the app and instead of a contacts name being displayed, tango displayed their phone number. These contacts were only tango contacts who I had never met and who had never given me their phone number. I even checked that is was actually the person's phone number by sending them a regular text and surprisingly, it was their actual phone number. This problem seems to me like it has something to do with the person changing their name in the apps character encoding

  • You can't remove contacts

    For some reason, in the Tango app, contacts are added just by chatting to someone, for most people this probably isn't the behaviour that is expected so if you install the app and go about chatting to many people, your contacts

  • ...

Drupal Migrate: Don't forget to de register your classes

Often times when writing a module to migrate content leveraging the Migrate module you will find yourself disabling and re enabling your module as you add classes to it.
When you do this you might find that you get errors about classes not being found or that your migrations are still being displayed in the interface even though your module is disabled (when using a class from another module such as d2d_migrate).
To get around this, make sure you de register your migration classes in a HOOK_disable() function in your module.

 function MYMODULE_disable() { 

Stopping Drupal spam registrations without an annoying captcha

There are many modules out there to prevent spam registrations in Drupal, but many of them involve some sort of Captcha, which I hate, or a paid for service. Stopping fake site registrations should not make it harder for the legitimate people trying to register on your site, and having to pay to prevent spam does not sit well with me.
While Drupal does have a setting to "Require email validation", I do usually have this enabled, but it does not stop the actual registration process and your user table will increase in size pretty quickly, also, some bots seems to be able to get around this too.
Here is a list of the modules I enabled to stop spam registrations to great effect.

Include a honeypot field

The honeypot module is a great module to implement as your first line of defense. It adds a hidden field to your forms, that when a value is added, the form will not submit.
It also has a "Honeypot time limit" setting that is the "Minimum time required before form should be considered entered by a human instead of a bot.". Not though, that using this setting will disable page cache for whatever page that the form on, As on many of my sites have the registration form on all/most pages I usually set this to 0 effectively disabling it so the pages still cache.

Block certain username or email patterns

Often spam registrations have email addresses at a few common domains and you can stop this by enabling the user restrictions module , but this may not be enough and maybe you want to check the username field for a pattern instead. Enter the Regex Registration Deny module , This is a module...

Fixing drush * needs a higher bootstrap level to run

Today while setting up a Drupal dev environment on a new PC I encountered the drush error "Command * needs a higher bootstrap level to run".
The first thing I did as many probably would is do a quick search on google. This though yields many different results and fixes. The problem though is I didn't know why it was happening so I didn't know which fix would work.
Turns out though it was quite easy to determine the actual problem. Drush has a nice option that will output dubug messages, funny enough, the option is --debug .
So, to get a better understanding of why you might be getting the "Command * needs a higher bootstrap level to run", simple enter this drush command: drush pm-list --debug and run through the output looking for what might be causing the problem.
In my case, I had a line that read "mysql is not recognised as an internal or external command", suggesting to me that my environment variable for mysql was not set up properly.

Using Three.js with jsfiddle

Using Three.js in a fiddle on the site jsfiddle.net is really quite easy but I keep coming across people having trouble with it. So here are a couple of tips when trying to set up a Three.js scene in a fiddle

Including the Three.js source

When creating a fiddle to use Three.js the most important part is including the Three.js library itself. You can select to include Three.js from the "Framework and Extensions" section but this will probably not be the latest version of Three.js. To include the latest version it is best to include it from the github repository itself, so you want to enter the path in the "External resources" section. But directly including the github path will result in an error, even with the github raw path. What you need to do is include the path from rawgit.com/ , which is rawgit.com/mrdoob/three.js/master/build/three.min.js.
Now you have Three.js included in the page correctly, you can start creating your 3D scene. If you prefer to work from a base, I have created on here .

Here is how the base looks.

Using images in materials

When using images in Three.js materials in a fiddle you will probably come across the CORS (Cross-Origin Resource Sharing) problem.
A way to get around this problem is to add the image DataURL as a variable, the same as if you call toDataURL() on a canvas element.
You can get an images DataURL DatURL.net
Here is an example that uses a variable with image data as the source for the THREE.ImageUtils.loadTexture() function.

Here is an example of using image data as a texture in a fiddle.

Instead of using a dataURL...

Drupal 7 Bootstrap image field upload widget

When using the Bootstrap theme in Drupal 7, the image upload widget leaves a lot to be desired. I looks pretty crappy
Below is how I overcame this.
It should probably work with file fields too but instead of overriding THEME_image_widget, you would override THEME_file_widget, though I haven't tried it yet.

First, add this to your css

 .btn-file { 
position: relative;
overflow: hidden;

.btn-file input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 100px;
text-align: right;
filter: alpha(opacity = 0);
opacity: 0;
outline: none;
background: white;
cursor: inherit;
display: block;

Then override the theme_image_widget in your template.php
A note on admin theme
If your upload widget is on a node edit page (or any admin page) the active theme will be your admin theme. This means the code will need to go into your admin themes template.php and the css in your admin themes css.

 function MYTHEME_image_widget($variables) { 
$element = $variables['element'];
$output = '';
$output .= '<div class="image-widget form-managed-file clearfix">';

if (isset($element['preview'])) {
$output .= '<div class="image-preview">';
$output .= drupal_render($element['preview']);
$output .= '</div>';

$output .= '<div class="image-widget-data">';
if ($element['fid']['#value'] != 0) {
$element['filename']['#markup'] = '<div class="form-group">' . $element['filename']['#markup'] . ' <span class="file-size badge">' . format_size($element['#file']->filesize) . '</span></div>';
else {
$element['upload']['#prefix'] = '<div class="input-group"><span class="input-group-btn"><span class="btn

Javascript snippet for "jump to" functionality in Owl Carousel

Putting this here for my own future reference.
It adds an input textfield under an owl carousel (2.0.0-beta.2.4) to jump to a certain item.
Dots must be on to use the "to" method.
It also includes some stuff for lazy loading as it did not seem to work when using the "to" method of the OwlCarousel.

  var container = $('.view-collection-item-viewer-new .view-content', context); 
var carousel = container.owlCarousel({
items: 2,
lazyLoad: true,
loop: false,
nav: true,
//dots: false,
margin: 10,
mouseDrag: false,
responsive : {
200 : {
items: 2,
600 : {
items: 3,
//dots: true,
900 : {
items: 4,
//dots: true,
callbacks: true,
onInitialized: function(){
var carousel = this;
var jumpcon = $('<div class="owl-jump"/>');
var jumpform = $('<form>go to page <input type="text"/></form>').submit(function(e){
var num = e.target[0].value;
if($.isNumeric(num) && num >= 1 && num <= carousel._items.length){
var oneachpage = carousel._items.length / carousel._plugins.navigation._pages.length;
var newpage = Math.ceil(num / Math.ceil(oneachpage));
carousel.to(newpage - 1);
return false;
jumpform.append(' of '+carousel._items.length+' <input type="submit" value="Go">');
onTranslated: function(){
// Lazy loading doesn't work well when using owl carousel 'to' method, so we do it here manually after the transition has ended.
var carousel = this;
$('.owl-item', carousel.$element).each(function(index,