Register
Random numbers Print E-mail
User Rating: / 2
PoorBest 
Written by Stuart   
Sunday, 25 April 2010 07:08

I'm not using pre-generated noise textures or volumes, because there are a lot of ways to tune noise and that's something else I'd rather keep live. But to make noise you need random numbers, which is what this post is about.

I wish there were a (portable) way to do this directly in a shader (under shader model 3), but as far as I know, there isn't. So I've gone the standard route and initialized a texture with random numbers, but instead of using a PRNG to get the values (which would make gaps in the distribution), I generate a smooth gradient between 0 and 1, then randomly permute it:

    1 function CreateRandomTexture( width, height )

    2 

    3     local channels  = 1

    4     local count     = width * height   

    5     local t         = {}

    6 

    7     for i = 1, count do

    8         t[#t + 1] = (i - 1) / (count - 1)

    9     end

   10 

   11     for i = 1, count do

   12         local swap = math.random( count )

   13         t[i], t[swap] = t[swap], t[i]

   14     end

   15 

   16     local tex = CTextureValue:New()

   17     tex:InitImmediate( width, height, channels, t )

   18 

   19     return tex

   20 

   21 end

(Appending to a Lua table using the t[#t + 1] idiom is the fastest way to populate it, because it keeps the array values in contiguous memory. If you poke values in a different order, say by initializing the first column of an image, they end up in the hash table. I learned that the hard way).

Random pixels

This is fine so far, but I'll need a constant stream of random numbers, and generating them every frame on the CPU is too expensive. So I've also got a second texture to do a lossless shuffle of the random numbers:

    1 function CreateRandomShuffleTexture( width, height )

    2 

    3     local channels  = 2

    4     local count     = width * height   

    5     local t         = {}

    6 

    7     for y = 1, height do

    8         local v = (y - 0.5) / height

    9         for x = 1, width do

   10             local u = (x - 0.5) / width

   11             t[#t + 1] = u

   12             t[#t + 1] = v

   13         end

   14     end

   15 

   16     for i = 1, count do

   17         local swap = math.random( count )

   18         t[i*2],   t[swap*2]   = t[swap*2],   t[i*2]

   19         t[i*2-1], t[swap*2-1] = t[swap*2-1], t[i*2-1]

   20     end

   21 

   22     local tex = CTextureValue:New()

   23     tex:InitImmediate( width, height, channels, t )

   24 

   25     return tex

   26 

   27 end

This can be used once per frame (or more) to mix things up.

Noise is much more interesting. I'll share what I'm doing for that soon.

 

Add comment

Security code
Refresh

Licensed developer

Licensed PS3 developer

Subscribe

Follow us on Twitter!

S5 Box

Register

*
*
*
*
*

Fields marked with an asterisk (*) are required.

Copyright © 2011 Pure Energy Games, Inc. All rights reserved.