Click here to Skip to main content
Licence CPOL
First Posted 4 Jul 2010
Views 15,203
Downloads 787
Bookmarked 13 times

Create a Noise Image with GLSL Shader

By | 6 Jul 2010 | Article
A simple shader program to create noise effect in an image

screenshot.jpg

Screen shot of Noise Application.

Introduction

This is a simple pixel shader program which changes 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 shader will get 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 that of input image. 

Example shader displaying texture image is the same as that of 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 texture coordinate which can be used to get texel (a pixel from texture). After getting texel from ImageTexture, set that coolor as output color, and we will get display of ImageTexture in screen.

What will happen if we change 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 change 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 Image, but that’s not good for creating a noisy image. In order to create a noisy output, we need to randomly change lookup position. That’s why I created a NoiseTexture, which contains random offsets that can be used to change the lookup coordinate of ImageTexture. The size of NoiseTexture is the same as that of ImageTexture to avoid repetition of 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 apply this offset to original texture coordinate. This new texture coordinate is used for lookup of ImageTexture and to get a Noisy output of ImageTexture.

Shader for Creating 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 pixel shader from resource. When I used strlen() to find the length of resource data, some unexpected data is appended at the end of resource. Therefore compilation of shader program failed. Now I used SizeOfResource() for finding the length of 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  

  • 4th July, 2010: Initial version
  • 5th July, 2010: Updated binary, since previous binary had dependency with Visual Studio 2008 runtime

License

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

About the Author

Santhosh_G



India India

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionFillGrad Question PinmemberDavid Mitchell8:17 2 Dec '10  
AnswerRe: FillGrad Question Pinmembersanthosh4gCode16:43 12 Feb '11  
QuestionInclude Cook-Torrance model in Shader PinmemberMember 12234315:07 21 Nov '10  
GeneralPossible to include Cook-Torrance model PinmemberMember 12234315:04 21 Nov '10  
General"Download binary - 898.95 KB" gives source distribution. PinmemberMember 42571214:49 11 Jul '10  
GeneralRe: "Download binary - 898.95 KB" gives source distribution. Pinmembersanthosh4gCode3:08 5 Aug '10  
GeneralMy vote of 5 PinmemberAdrian Pasik2:07 7 Jul '10  
GeneralRe: My vote of 5 Pinmembersanthosh4gCode3:29 7 Jul '10  

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.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 6 Jul 2010
Article Copyright 2010 by Santhosh_G
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid