Shader Effects: Refraction

Interactive Shader Effects Series

  • Effects
    • Blending Layers
    • Convolution Filters (Emboss, Edge Detection)
    • Curves and Levels
    • Depth of Field
    • Film Grain
    • Heat Waves
    • Old Film
  • Lighting
  • Materials
    • Skin
    • Snow and Ice
    • Water
  • Miscellaneous
    • Transition Effects
  • Procedural
    • 2D, 3D, 4D Noise
    • Sky / Cloud Generation
    • Terrain

Start WebGL Demo

Sorry, it appears you don't have support for WebGL.


In order to run this demo, you must meet the following requirements.

  • You are running the latest version of Mozilla Firefox, Google Chrome, or Safari.
  • You have a WebGL compatible video card with the latest drivers.
  • Your video card is not blacklisted. You can check the current blacklist on Khronos.

Some browsers may require additional configuration in order to get WebGL to run. If you are having problems running this demo, visit the following sites.

Loading %

Rot. and Zoom

Use mouse.

Amplitude

Frequency

Period

Presets

                            
/// <summary>
/// Basic lighting vertex shader.
/// </summary>


/// <summary>
/// Material source structure.
/// <summary>
struct MaterialSource
{
    vec3 Ambient;
    vec4 Diffuse;
    vec3 Specular;
    float Shininess;
    vec2 TextureOffset;
    vec2 TextureScale;
};


/// <summary>
/// Attributes.
/// <summary>
attribute vec3 Vertex;
attribute vec2 Uv;
attribute vec3 Normal;


/// <summary>
/// Uniform variables.
/// <summary>
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ModelMatrix;
uniform vec3 ModelScale;

uniform MaterialSource Material;


/// <summary>
/// Varying variables.
/// <summary>
varying vec4 vWorldVertex;
varying vec3 vWorldNormal;
varying vec2 vUv;
varying vec3 vViewVec;


/// <summary>
/// Vertex shader entry.
/// <summary>
void main ()
{
    // Transform the vertex
    vWorldVertex = ModelMatrix * vec4(Vertex * ModelScale, 1.0);
    vec4 viewVertex = ViewMatrix * vWorldVertex;
    gl_Position = ProjectionMatrix * viewVertex;
    
    // Setup the UV coordinates
    vUv = Material.TextureOffset + (Uv * Material.TextureScale);
    
    // Rotate normal
    vWorldNormal = normalize(mat3(ModelMatrix) * Normal);
    
    // Calculate view vector (for specular lighting)
    vViewVec = normalize(-viewVertex.xyz);
}
                            
                        
                            
/// <summary>
/// Vertex shader for rendering a 2D plane on the screen. The plane should be sized
/// from -1.0 to 1.0 in the x and y axis. This shader can be shared amongst multiple
/// post-processing fragment shaders.
/// </summary>


/// <summary>
/// Attributes.
/// <summary>
attribute vec3 Vertex;
attribute vec2 Uv;


/// <summary>
/// Uniform variables.
/// <summary>
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ModelMatrix;
uniform vec3 ModelScale;


/// <summary>
/// Varying variables.
/// <summary>
varying vec2 vUv;


/// <summary>
/// Vertex shader entry.
/// <summary>
void main ()
{
    vec4 worldVertex = ModelMatrix * vec4(Vertex * ModelScale, 1.0);
    vec4 viewVertex = ViewMatrix * worldVertex;
    gl_Position = ProjectionMatrix * viewVertex;
    
    vUv = Uv;
}
                            
                        
                            
/// <summary>
/// Vertex shader for rendering a cubemapped skybox.
/// </summary>


/// <summary>
/// Attributes.
/// <summary>
attribute vec3 Vertex;
attribute vec3 Normal;


/// <summary>
/// Uniform variables.
/// <summary>
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ModelMatrix;
uniform vec3 ModelScale;


/// <summary>
/// Varying variables.
/// <summary>
varying vec3 vNormal;


/// <summary>
/// Vertex shader entry.
/// <summary>
void main ()
{
    gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Vertex * ModelScale, 1.0);
    vNormal = Normal;
}
                            
                        
                            
/// <summary>
/// Basic lighting fragment shader.
/// </summary>


#ifdef GL_ES
    precision highp float;
#endif


/// <summary>
/// Light source structure.
/// <summary>
struct LightSource
{
    vec3 Position;
    vec3 Attenuation;
    vec3 Direction;
    vec3 Colour;
    float OuterCutoff;
    float InnerCutoff;
    float Exponent;
};


/// <summary>
/// Material source structure.
/// <summary>
struct MaterialSource
{
    vec3 Ambient;
    vec4 Diffuse;
    vec3 Specular;
    float Shininess;
    vec2 TextureOffset;
    vec2 TextureScale;
};


/// <summary>
/// Uniform variables.
/// <summary>
uniform int NumLight;
uniform LightSource Light[4];
uniform MaterialSource Material;
uniform sampler2D Sample0;


/// <summary>
/// Varying variables.
/// <summary>
varying vec4 vWorldVertex;
varying vec3 vWorldNormal;
varying vec2 vUv;
varying vec3 vViewVec;


/// <summary>
/// Fragment shader entry.
/// <summary>
void main ()
{
    // vWorldNormal is interpolated when passed into the fragment shader.
    // We need to renormalize the vector so that it stays at unit length.
    vec3 normal = normalize(vWorldNormal);

    vec3 colour = Material.Ambient;
    for (int i = 0; i < 4; ++i)
    {
        if ( i >= NumLight )
            break;
        
        // Calculate diffuse term
        vec3 lightVec = normalize(Light[i].Position - vWorldVertex.xyz);
        float l = dot(normal, lightVec);
        if ( l > 0.0 )
        {
            // Calculate spotlight effect
            float spotlight = 1.0;
            if ( (Light[i].Direction.x != 0.0) || (Light[i].Direction.y != 0.0) || (Light[i].Direction.z != 0.0) )
            {
                spotlight = max(-dot(lightVec, Light[i].Direction), 0.0);
                float spotlightFade = clamp((Light[i].OuterCutoff - spotlight) / (Light[i].OuterCutoff - Light[i].InnerCutoff), 0.0, 1.0);
                spotlight = pow(spotlight * spotlightFade, Light[i].Exponent);
            }
            
            // Calculate specular term
            vec3 r = -normalize(reflect(lightVec, normal));
            float s = pow(max(dot(r, vViewVec), 0.0), Material.Shininess);
            
            // Calculate attenuation factor
            float d = distance(vWorldVertex.xyz, Light[i].Position);
            float a = 1.0 / (Light[i].Attenuation.x + (Light[i].Attenuation.y * d) + (Light[i].Attenuation.z * d * d));
            
            // Add to colour
            colour += ((Material.Diffuse.xyz * l) + (Material.Specular * s)) * Light[i].Colour * a * spotlight;
        }
    }
    
    gl_FragColor = clamp(vec4(colour, Material.Diffuse.w), 0.0, 1.0) * texture2D(Sample0, vUv);
}
                            
                        
                            
/// <summary>
/// Fragment shader for rendering a cubemapped skybox.
/// </summary>


#ifdef GL_ES
    precision highp float;
#endif


/// <summary>
/// Uniform variables.
/// <summary>
uniform samplerCube Sample0;


/// <summary>
/// Varying variables.
/// <summary>
varying vec3 vNormal;


/// <summary>
/// Fragment shader entry.
/// <summary>
void main ()
{
    gl_FragColor = textureCube(Sample0, vNormal);
}
                            
                        
                            
/// <summary>
/// Shader for tagging pixels that will be affected by the refraction shader.
/// </summary>


#ifdef GL_ES
    precision highp float;
#endif


/// <summary>
/// Fragment shader entry.
/// <summary>
void main ()
{
    // Simply set the alpha value
    gl_FragColor.w = 0.0;
}
                            
                        
                            
/// <summary>
/// Shader to refract all pixels with their alpha channel set to 0.
/// </summary>


#ifdef GL_ES
    precision highp float;
#endif


/// <summary>
/// Uniform variables.
/// <summary>
uniform vec2 ImageSize;
uniform vec2 TexelSize;
uniform sampler2D Sample0;

/// <summary>
/// Size of the refraction.
/// <summary>
uniform float Amplitude;

/// <summary>
/// Frequency of the refraction.
/// <summary>
uniform float Frequency;

/// <summary>
/// Relative speed (period) of the refraction.
/// <summary>
uniform float Period;

/// <summary>
/// Random number to animate or mix up the refracted results.
/// <summary>
uniform float RandomNumber;


/// <summary>
/// Varying variables.
/// <summary>
varying vec2 vUv;


// Description : Array and textureless GLSL 3D simplex noise function.
//      Author : Ian McEwan, Ashima Arts.
//  Maintainer : ijm
//     Lastmod : 20110822 (ijm)
//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//               Distributed under the MIT License. See LICENSE file.
//               https://github.com/ashima/webgl-noise
vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
vec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
vec4 permute(vec4 x) { return mod289(((x*34.0)+1.0)*x); }
vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }
float snoise(vec3 v)
{ 
  const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
  const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);

  // First corner
  vec3 i  = floor(v + dot(v, C.yyy) );
  vec3 x0 =   v - i + dot(i, C.xxx) ;

  // Other corners
  vec3 g = step(x0.yzx, x0.xyz);
  vec3 l = 1.0 - g;
  vec3 i1 = min( g.xyz, l.zxy );
  vec3 i2 = max( g.xyz, l.zxy );

  //   x0 = x0 - 0.0 + 0.0 * C.xxx;
  //   x1 = x0 - i1  + 1.0 * C.xxx;
  //   x2 = x0 - i2  + 2.0 * C.xxx;
  //   x3 = x0 - 1.0 + 3.0 * C.xxx;
  vec3 x1 = x0 - i1 + C.xxx;
  vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
  vec3 x3 = x0 - D.yyy;      // -1.0+3.0*C.x = -0.5 = -D.y

  // Permutations
  i = mod289(i); 
  vec4 p = permute( permute( permute( 
             i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
           + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 
           + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));

  // Gradients: 7x7 points over a square, mapped onto an octahedron.
  // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
  float n_ = 0.142857142857; // 1.0/7.0
  vec3  ns = n_ * D.wyz - D.xzx;

  vec4 j = p - 49.0 * floor(p * ns.z * ns.z);  //  mod(p,7*7)

  vec4 x_ = floor(j * ns.z);
  vec4 y_ = floor(j - 7.0 * x_ );    // mod(j,N)

  vec4 x = x_ *ns.x + ns.yyyy;
  vec4 y = y_ *ns.x + ns.yyyy;
  vec4 h = 1.0 - abs(x) - abs(y);

  vec4 b0 = vec4( x.xy, y.xy );
  vec4 b1 = vec4( x.zw, y.zw );

  //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
  //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
  vec4 s0 = floor(b0)*2.0 + 1.0;
  vec4 s1 = floor(b1)*2.0 + 1.0;
  vec4 sh = -step(h, vec4(0.0));

  vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
  vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;

  vec3 p0 = vec3(a0.xy,h.x);
  vec3 p1 = vec3(a0.zw,h.y);
  vec3 p2 = vec3(a1.xy,h.z);
  vec3 p3 = vec3(a1.zw,h.w);

  //Normalise gradients
  vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;

  // Mix final noise value
  vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
  m = m * m;
  return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 
                                dot(p2,x2), dot(p3,x3) ) );
}


/// <summary>
/// Compute the normal using a sobel filter on the adjacent noise pixels.
///
/// Normally you would output the noise to a texture first and then calculate
/// the normals on that texture to improve performance; however everthing is
/// kept in this shader as a single process to help illustrate what's going on.
/// <summary>
/// <returns>A normal vector.</returns>
vec3 GetNormal ()
{
    // Get Sobel values
    vec2 uv = vUv * Frequency;
    float z = RandomNumber * Period;
    
    float tl = snoise(vec3(uv.x - TexelSize.x, uv.y - TexelSize.y, z));
    float t = snoise(vec3(uv.x, uv.y - TexelSize.y, z));
    float tr = snoise(vec3(uv.x + TexelSize.x, uv.y - TexelSize.y, z));
    float l = snoise(vec3(uv.x - TexelSize.x, uv.y, z));
    float r = snoise(vec3(uv.x + TexelSize.x, uv.y, z));
    float bl = snoise(vec3(uv.x - TexelSize.x, uv.y + TexelSize.y, z));
    float b = snoise(vec3(uv.x, uv.y + TexelSize.y, z));
    float br = snoise(vec3(uv.x + TexelSize.x, uv.y + TexelSize.y, z));

    // Sobel filter
    vec3 normal = vec3((-tl - l * 2.0 - bl) + (tr + r * 2.0 + br),
                (-tl - t * 2.0 - tr) + (bl + b * 2.0 + br),
                1.0 / Amplitude);
                        
    // Return normalized vector
    return normalize(normal);
}


/// <summary>
/// Fragment shader entry.
/// <summary>
void main ()
{
    // Refract only tagged pixels (that is, the alpha channel has been set)
    vec2 offset;
    if ( texture2D(Sample0, vUv).w == 0.0 )
    {
        // Method 1: Use noise as the refraction angle.
        // Fast and good results for some scenarios.
        //const float pi = 3.141592;
        //float noise = snoise(vec3((vUv * Frequency), RandomNumber * Period)) * pi;
        //offset = vec2(cos(noise), sin(noise)) * Amplitude * TexelSize;
        
        // Method 2: Get the normal from an animating normalmap to use as the refracted vector.
        // Slower, but better results.
        vec3 normal = GetNormal();
        offset = normal.xy;
    }
    
    // Use the colour at the specified offset into the texture
    gl_FragColor.xyz = texture2D(Sample0, vUv + offset).xyz;
    gl_FragColor.w = 1.0;
}
                            
                        
                            
/// <summary>
/// Fragment shader to modify brightness, contrast, and gamma of an image.
/// </summary>


#ifdef GL_ES
    precision highp float;
#endif


/// <summary>
/// Uniform variables.
/// <summary>
uniform float Brightness;   // 0 is the centre. < 0 = darken, > 1 = brighten
uniform float Contrast;     // 1 is the centre. < 1 = lower contrast, > 1 is raise contrast
uniform float InvGamma;     // Inverse gamma correction applied to the pixel

uniform sampler2D Sample0;  // Colour texture to modify


/// <summary>
/// Varying variables.
/// <summary>
varying vec2 vUv;


/// <summary>
/// Fragment shader entry.
/// <summary>
void main ()
{
    // Get the sample
    vec4 colour = texture2D(Sample0, vUv);
    
    // Adjust the brightness
    colour.xyz = colour.xyz + Brightness;
    
    // Adjust the contrast
    colour.xyz = (colour.xyz - vec3(0.5)) * Contrast + vec3(0.5);
    
    // Clamp result
    colour.xyz = clamp(colour.xyz, 0.0, 1.0);
    
    // Apply gamma correction, except for the alpha channel
    colour.xyz = pow(colour.xyz, vec3(InvGamma));
    
    // Set fragment
    gl_FragColor = colour;
}
                            
                        

Refraction

Heat haze from an F-111. Photo by Nic MacBean, ABC News

Introduction

Refraction is the bending of light when passing from one medium into another. When light reaches your eyes, the objects appear bent or distorted in some way. You see this type of physical property whenever you stare at objects within water or when you look off to the horizon on a hot day and see heat haze rising from the ground. This article will cover a refraction technique used to produce these types of effects.

Refraction

Unlike reflection where a vector bounces off the surface with the same angle, vectors that penetrate transparent objects refract at a different angle, depending on the differences between the two mediums.

Reflection vs Refraction


In the case with heat haze, hot air is less dense then colder air. When light passes through the hot air, it refracts from its trajectory. When it returns to the cooler region, it refracts back to its original angle, but by now the light will have been shifted. To the observer, this makes the object in the distance appear distorted. The hotter the air, the stronger the refractive angle. This is why on a hot summer day the horizon appears to wave in and out smoothly, but when you look at the heat generated from a turbofan on a jet aircraft the distortion is very strong.

Implementation

The technique demonstrated in the WebGL demo is not physically based. In an ideal implementation, you would cast a ray from the view camera toward the environment and refract the ray as necessary to find an intersection point on an object and colour the pixel. This can be an expensive process. Instead, we will use a rasterization technique. The process is as follows.


1. Create an RGBA framebuffer object.


2. Render the scene to the FBO.


3. Render all heat-casting entities to the alpha channel in the FBO. These entities are not actually visible, but by altering the alpha channel the refraction shader will know which pixels to modify. For illustration purposes, the screenshot below displays the refracted area.


4. In the refraction shader, refract the pixels that had their alpha channel modified in step 3. One way to refract the pixels is to use an animating normal map. The demo uses animating 3D simplex noise and a sobel filter to calculate the normalmap. The (X,Y) vector returned by the normal map will point in the direction to acquire the refracted pixel data. The amount you shift is called the amplitude. Small amplitudes represent small changes, like heat haze. Large amplitudes emulate more like water.


Animating normalmap


One last step remains, but is not handled in the demo. Foreground objects will be picked up and incorrectly refracted in the refraction shader. To eliminate this issue, you should render only the objects beyond the refracted surface, pass the texture to the refraction shader, and finally render all foreground objects. This however may not be a trivial solution, especially if you have multiple refracted areas with intersecting polygons. If your amplitudes are within a small range, the rendering defects are not as noticeable and may not even prove to be a quality issue for your game, but it's something to think about.

The source code for this project is made freely available for download. The ZIP package below contains both the HTML and JavaScript files to replicate this WebGL demo.


The source code utilizes the Nutty Open WebGL Framework, which is an open sourced, simplified version of the closed source Nutty WebGL Framework. It is released under a modified MIT license, so you are free to use if for personal and commercial purposes.


Download Source

Tagged: webgl shaders refraction

Comments

enaena10 | about 6 hours ago

cheap tiffany and co jewelry
| stores sell tiffany jewelry
| sell tiffany and co jewelry
| tiffany silver jewelry
| cheap tiffany and co jewelry

Tiffany & Co Elsa Peretti Triple Open Heart Necklace - $87.00 : cheap tiffany Jewelry, goodstiffany.com










#sddm { margin: 0 auto; padding: 0; z-index: 30; background-color:#F4F4F4; width: 80px; height:23px; float: right; margin-right: 70px;} #sddm li { margin: 0; padding: 0; list-style: none; float: left; font: bold 12px arial} #sddm li a { display: block; margin: 0 1px 0 0; padding: 4px 10px; width: 60px; background: #EAEAE8; color: #666; text-align: center; text-decoration: none} #sddm li a:hover { background: #49A3FF} #sddm div { position: absolute; visibility: hidden; margin: 0; padding: 0; background: #EAEBD8; border: 1px solid #5970B2} #sddm div a { position: relative; display: block; margin: 0; padding: 5px 10px; width: auto; white-space: nowrap; text-align: left; text-decoration: none; background: #EAEBD8; color: #2875DE; font: 12px arial} #sddm div a:hover { background: #49A3FF; color: #FFF} Payment |  Shipping & Returns  |  Wholesale |  Contact Us Welcome! Sign In or Register Your cart is empty
  • Home
  • New Arrivals
  • Tiffany Bangles
  • Tiffany Earrings
  • Tiffany Necklaces
  • Contact Us
  • Currencies US DollarCNYEuroGB PoundCanadian DollarAustralian DollarJappen YenNorske KroneSwedish KroneDanish Krone Categories New Arrivals Tiffany Bangles Tiffany Bracelets Tiffany Cuff Link Tiffany Earrings Tiffany Key Rings Tiffany Money Clips Tiffany Necklaces Tiffany Pendants Tiffany Rings Tiffany Sets Featured -   [more] Tiffany & Co Padlock Cuff $225.00  $67.00
    Save: 70% off Tiffany & Co Square Stacking Ring $250.00  $77.00
    Save: 69% off Return to Tiffany & Co Round Tag Toggle Bracelet $295.00  $77.00
    Save: 74% off Tiffany & Co Atlas Silver Ring $235.00  $67.00
    Save: 71% off Home ::  New Arrivals ::  Tiffany & Co Elsa Peretti Triple Open Heart Necklace .jqzoom{ float:left; position:relative; padding:0px; cursor:pointer; width:301px; height:300px; } $(document).ready(function(){ $(".jqzoom").jqueryzoom({ xzoom: 282, //zooming div default width(default width value is 200) yzoom: 282, //zooming div default width(default height value is 200) offset: 5, //zooming div default offset(default offset value is 10) position: "right", //zooming div position(default position value is "right") preload:1, lens:1 }); $("#jqzoomimages").jqzoomimages({ sImgList: ["images//tiffany01_/New-Arrivals/Tiffany-Co-Elsa-Peretti-Triple-Open-Heart-Necklace.jpg"], lImgList: ["images//tiffany01_/New-Arrivals/Tiffany-Co-Elsa-Peretti-Triple-Open-Heart-Necklace.jpg"], vImgList: ["images//tiffany01_/New-Arrivals/Tiffany-Co-Elsa-Peretti-Triple-Open-Heart-Necklace.jpg"], pageNo: 1, pagesize: 4, imgWidth: 55, imgHeight: 55, bigImageId: "jqzoomimg" }); });
    larger image



    Tiffany & Co Elsa Peretti Triple Open Heart Necklace


    $325.00  $87.00
    Save: 73% off

                  <div id="cartAdd">
    Add to Cart: <input type="text" name="cart_quantity" value="1" maxlength="6" size="4" /><br /><br /><input type="hidden" name="products_id" value="30" /><input type="image" src="http://www.goodstiffany.com/includes/templates/polo/buttons/english/button_in_cart.gif" alt="Add to Cart" title=" Add to Cart " />          </div>
    




    Tiffany & Co Elsa Peretti Triple Open Heart Necklace Sale Description

    You'll do a triple take when you see this unique triple open heart necklace. Crafted of sterling silver,the necklace with triple-heart design provides romantic elegance and lasting shine. This simple necklace from Tiffany and co outlet will easily capture your heart.

    Brand story:
    'Tiffany Breakfast' is a famous Hollywood actress Audrey HePburm starred in 1960 named by tiffany uk.There are mang different kinds of jewellery on Tiffany uk, for example,tiffany accessory, bracelet ,chain, charm and so on.

    Product Features:
    Elsa Peretti Open Heart Necklace
    Sterling Silver
    Manufacturer: Tiffany & Co. jewelry

    Recommend this:
    Tiffany & Co 1837 Cuff Bangles Set of Tiffany jewelry outlet is an timeless style to take you elegantly through this season and beyond.


    Related Products Tiffany & Co Engraved Oval Tag Ring Tiffany & Co Multi-heart Drop Earrings Tiffany & Co Elsa Peretti Open Heart Ring Tiffany & Co Atlas Cube Drop Earrings



    TIFFANY JEWELRY    TIFFANY IMITATE    TIFFANY DISCOUNT RING    TIFFANY CHEAP STOER    TIFFANY HIGH IMITATE   Copyright © 2012 All Rights Reserved.

    tiffany jewelry outlet


    tiffany and co outlet


    tiffany outlet online


    tiffany outlet store


    tiffany outlet locations


    .Initially, the payment cigarettes like Marlboro, Camel, Winston, Va Slims, plus Salem can be manufactured and shipped right from duty zero cost zones throughout Eastern The uk.As they are really tax totally free they turn out to be really affordable even bearing in mind shipping price involved.There's a simple small find though, a person's country may possibly levy an individual import responsibility.

    However, evaluate these minimal points.First off, one who smokes Cigarette regularly might discover imported affordable Marlboro using tobacco tasting in a different way.This is an issue that the usual smokers dont want to agree.This will not truly as the case mainly because same makes are manufactured in similar style everywhere barring a few exceptions where by regulations are usually slack as well as the franchisee brand names themselves circumnavigate your regulations

    enaena10 | about 6 hours ago

    [b][url=http://www.goodstiffany.com/]tiffany jewelry outlet[/url][/b]
    [b]tiffany and co outlet[/b]
    [b][url=http://www.goodstiffany.com/]tiffany outlet online[/url][/b]
    [b][url=http://www.goodstiffany.com/]tiffany outlet store[/url][/b]
    [b]tiffany outlet locations[/b]
    .Initially, the payment cigarettes like Marlboro, Cametiffany jewelry outlet


    tiffany and co outlet


    tiffany outlet online


    tiffany outlet store


    tiffany outlet locations


    .Initially, the payment cigarettes like Marlboro, Camel, Winston, Va Slims, plus Salem can be manufactured and shipped right from duty zero cost zones throughout Eastern The uk.As they are really tax totally free they turn out to be really affordable even bearing in mind shipping price involved.There's a simple small find though, a person's country may possibly levy an individual import responsibility.

    However, evaluate these minimal points.First off, one who smokes Cigarette regularly might discover imported affordable Marlboro using tobacco tasting in a different way.This is an issue that the usual smokers dont want to agree.This will not truly as the case mainly because same makes are manufactured in similar style everywhere barring a few exceptions where by regulations are usually slack as well as the franchisee brand names themselves circumnavigate your regulations

    Add New Comment

    Please Log in or register now to post a comment.
    Copyright 2011 DevMaster. All rights reserved. (rev: 994f941)