Click here to Skip to main content
Click here to Skip to main content

Tagged as

Create a Noise Image with GLSL Shader

, 6 Jul 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
A simple shader program to create noise effect in an image

NoiseImage/screenshot.jpg

Screenshot of the Noise application

Introduction

This is a simple pixel shader program which changes the input texture coordinate with a noise value and creates a noisy output image.

Background 

Creating any effect in an image is very simple with a pixel shader. This article demonstrates a simple noise effect in an image.  

Using the Code  

A fragment program will be executed for all pixels of a rendering. When rendering an entire texture fragment, the shader will get the corresponding texture coordinates for each pixel of rendering.

If texture lookup is performed with the provided texture coordinates for display, the rendered image will be the same as the input image.

An example shader displaying a texture image same as the input image:

uniform sampler2D ImageTexture;
// Shader for displaying a texture.
void main()
{
    // Lookup image texture with noise texture coordiante.
    gl_FragColor = texture2D(ImageTexture, gl_TexCoord[0].st );
}

gl_TexCoord[0].st holds the texture coordinate which can be used to get texel (a pixel from texture). After getting the texel from ImageTexture, set that color as output color, and we will get the display of ImageTexture in screen.

What will happen if we change the texture coordinate used for texture lookup?

The display of ImageTexture will be slightly changed.

Given below is an example shader displaying texture image with some changes in display of imageTexture

uniform sampler2D ImageTexture;

// Shader for displaying a texture with some change in texture display.
void main()
{    
     // Lookup image texture with small change in texture coordinate.
          // cos( gl_TexCoord[0].s) is added to texture coordinate.
    gl_FragColor = texture2D(ImageTexture, gl_TexCoord[0].st + 
    vec2(0.0, cos( gl_TexCoord[0].s)));
}

This shader can create a change in display of the image, but that’s not good for creating a noisy image. In order to create a noisy output, we need to randomly change the lookup position. That’s why I created a NoiseTexture which contains random offsets that can be used to change the lookup coordinates of ImageTexture. The size of NoiseTexture is the same as that of ImageTexture to avoid repetition of the Noise offset for nearest pixels.

CreateNoise() creates random offsets for filling NoiseTexture.

// This function create a Noise texture of m_nImageWidth and m_nImageHeight.
bool CNoiseDlg::CreateNoise()
{
    srand(time(NULL));
    if( 0 == m_pnRandomIndexes )
    {
        int maxRandom = max( m_nImageWidth, m_nImageHeight );
        m_pnRandomIndexes = new int[maxRandom];
        for (int nIndex = 0; nIndex < maxRandom; nIndex++)
        {
            m_pnRandomIndexes[nIndex] = max( (int)rand() % 256, (int)1.0);
        }
    }
    FillGrad(1);

    BYTE* pbyData = new BYTE[m_nImageWidth * m_nImageHeight *3];
    float NoiseHeight = m_NoiseValue / 100.0 * 25.0;

    // Creating Noise data of of m_nImageWidth and m_nImageHeight.
    for(int i = 0; i<m_nImageHeight; i++)
        for(int j = 0; j<m_nImageWidth; j++)
        {
            int offset = (i*m_nImageWidth+j)*3;
            char value = m_pnRandomIndexes[(j+m_pnRandomIndexes[i]) & 0xFF];
            pbyData[offset] = m_nRandomValues[value & 0x1F][0] * 
        NoiseHeight + min( NoiseHeight, m_NoiseValue );   // Gradient x
            pbyData[offset+1] = m_nRandomValues[value & 0x1F][1] * 
        NoiseHeight + min( NoiseHeight, m_NoiseValue ); // Gradient y
            pbyData[offset+2] = m_nRandomValues[value & 0x1F][2] * 
        NoiseHeight + min( NoiseHeight, m_NoiseValue ); // Gradient z
        }

        // Create texture with m_nImageWidth and m_nImageHeight.
        if( !m_NoiseTexture.Create( m_nImageWidth, m_nImageHeight, pbyData ))
        {
            AfxMessageBox( L"Texture loading failed" );
            return FALSE;
        }
        delete[] pbyData;
        return true;
}

For each pixel, offset values are retrieved from NoiseTexture, and we apply this offset to the original texture coordinate. This new texture coordinate is used for the lookup of ImageTexture and to get a Noisy output of ImageTexture.

Shader for Creating a Noisy Image

uniform sampler2D ImageTexture;
uniform sampler2D NoiseTexture;

// Shader for creating a noise in ImageTexture.
void main()
{
    // Get NoiseValue from Noisetexture.
    vec4 Noise = texture2D(NoiseTexture, gl_TexCoord[0].st );
    vec2 fLookupCoord = 
    gl_TexCoord[0].st + vec2( Noise.r * 0.065,-Noise.g * 0.025 );
    gl_FragColor = texture2D(ImageTexture,fLookupCoord );
}

Points of Interest

In my previous shader program, the release version creates an error while reading the pixel shader from the resource. When I used strlen() to find the length of the resource data, some unexpected data is appended at the end of the resource. Therefore compilation of the shader program fails. I used SizeOfResource() for finding the length of the Resource data, and fixed that issue.

bool GLSLShader::CreateProgram( const int nProgramID_i, GLenum glSlShaderType_i )
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    HRSRC hrResInfo = FindResource( 0, 
    MAKEINTRESOURCE( nProgramID_i ),TEXT("IDR_DATA"));
    if( 0 == hrResInfo )
    {
        return false;
    }
    HGLOBAL hRcResource =  LoadResource(0, hrResInfo );
    const CHAR* pBufferResData = (CHAR* )LockResource( hRcResource );
    // Get Length of shader program. When I used strlen() to get length of string,
    // I got some unexpected data at the end of progrm
    int nLENGTH = SizeofResource( 0, hrResInfo );

    // Shder creation code 
    // .. ... ....
}

History  

  • 4 July, 2010: Initial version.
  • 5 July, 2010: Updated binary, since previous binary had dependency with the Visual Studio 2008 Runtime.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Santhosh G_

India India
No Biography provided

Comments and Discussions

 
QuestionMemory Leak PinmemberFarhad1139647-Sep-13 9:59 
QuestionFillGrad Question PinmemberDavid Mitchell2-Dec-10 9:17 
AnswerRe: FillGrad Question Pinmembersanthosh4gCode12-Feb-11 17:43 
QuestionInclude Cook-Torrance model in Shader PinmemberMember 12234321-Nov-10 16:07 
GeneralPossible to include Cook-Torrance model PinmemberMember 12234321-Nov-10 16:04 
General"Download binary - 898.95 KB" gives source distribution. PinmemberMember 425712111-Jul-10 5:49 
GeneralRe: "Download binary - 898.95 KB" gives source distribution. Pinmembersanthosh4gCode5-Aug-10 4:08 
GeneralMy vote of 5 PinmemberAdrian Pasik7-Jul-10 3:07 
Nice effect
Nice subject
 

Looking more of this.
 
Please also make some C# version if You would
GeneralRe: My vote of 5 Pinmembersanthosh4gCode7-Jul-10 4:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 6 Jul 2010
Article Copyright 2010 by Santhosh G_
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid