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

  • ...

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() { 
Migration::deregisterMigration('my_role_migration');
Migration::deregisterMigration('my_user_migration');
}

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.

Update:
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){
try{
var oneachpage = carousel._items.length / carousel._plugins.navigation._pages.length;
var newpage = Math.ceil(num / Math.ceil(oneachpage));
carousel.to(newpage - 1);
}catch(e){}
}
return false;
});
jumpform.append(' of '+carousel._items.length+' <input type="submit" value="Go">');
jumpcon.append(jumpform);
carousel.$element.find('.owl-controls').append(jumpcon);
},
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,
...

Useful Drupal Links

I often seem to forget all the good places on the web to find info and things about drupal, So I thought I would start a list, mainly for my own reference.

  • Drupal API Reference Drupal API reference. Every Drupal dev. should be taking advantage of this site.
  • TopDrops Listing of most popular Drupal powered websites.
  • Drupal Jobs A group on Drupal Groups dedicated to job advertisements in the Drupal space.
  • Drupal paid services Another page dedicated to job advertisements.
  • Drupal Project applications A list of Drupal projects that are waiting review and approval to become full Drupal projects.
  • pareview.sh A site to review your Drupal module code. This should be used on all of your Drupal projects.
  • simpletest.me Easily test a drupal theme or module.
  • Drupal 7 Template (Theme Hook) Suggestions
  • Drupal X-Ray Tool to view the modules a Drupal website uses.
  • Create forms in a safe way to avoid cross-site request forgeries (CSRF)
Modules to remember
  • Fields
    • Conditional fields
  • Taxonomy
    • Hierarchical Select
  • Input formats
    • Pathologic
  • Image carousels / sliders
    • Slick Carousel
    • Owl Carousel
  • Development
    • Object Log
    • Security Review
  • Views
    • Foo table - responsive tables
  • Paths
    • Query parameters to url
  • Performance
    • CSS Embedded Images
    • Views Litepager
    • Views content cache
  • Emails
    • Mail logger
    • Reroute email
Useful modules when inheriting a Drupal...

Removing the entity ID from Drupal entity reference fields

On a site I am currently working on I have a content type that includes an entity reference field. When creating a node, the entity reference autocomplete includes the entity id in the field after selecting the entity desired. This can be confusing for the user.
When trying to find a solution to this problem I came across many issues and different proposed solutions including a sandbox module called Entity reference trim .

I tried the entity reference trim module but it has problems when the form was submitted and had errors.
Taking a closer look into this module I could see that it was altering the widget (adding a hidden field) and overriding some of the core Drupal js to do with the autocomplete functionality. While poking around the autocomplete javascript I noticed that the autocomplete fires a 'autocompleteValue' event.
Using this event I could change the entity reference field value and store it, then change it back when the form is submitted.

Below is the code that I am using but be aware that I have not yet tested it extensively and not tested it with multiple entity reference fields. Also, as the event bubbles, a more generic version could probably be coded.

NOTE: you will have to change the jQuery selector.

 (function ($) { 
Drupal.behaviors.damnId = {
attach: function (context, settings){
// Get the entity reference input
$eref = $('#edit-field-postcode-suburb-und-0-target-id', context);
if($eref.val()){
// If field has value on page load, change it.
var val = $eref.val();
var match = val.match(/\((.*?)\)$/);
$eref.data('real-value', val);
$eref.val(val.replace(match[0], ''));
}
// Listen for the
...