Creating a small noise texture

I am trying to implement SSAO with the help of the tutorial by John Chapman and I need to create a 4x4 random noise texture that will later be tiled across the screen and used in the algorithm itself. I am not sure what the simplest way to create it is.

If I create all the 16 samples on the CPU should I send the samples as vertices or uniform? If as uniforms then what should the vertices be?

Alternatively, can I generate the random samples on the GPU - in that case is this approach correct?

  1. Send a (-1, 1) rectangle as vertices.
  2. Use the fragment shader to calculate and output the random samples. I have to do it in the fragment shader since only that way will the value in the resulting texture have a randomly calculated value in each sample. If I calculated it in the vertex shader, there would be only 4 random values in the corners of the texture(because the rectangle is specified by its corners) and the other values would be interpolated, right? Just checking whether I understand what’s going on here.

In any case do I have to to make a single dedicated render pass just for this purpose or can it somehow be made a part of the geometry pass?
Thanks.

If I create all the 16 samples on the CPU should I send the samples as vertices or uniform? If as uniforms then what should the vertices be?

You’re doing SSAO. And SSAO is a full-screen effect; it uses the value of the depth in screen-space (ie: the depth buffer values) to compute/modify the ambient lighting at a particular location of the final image.

Your vertices for this process are nothing more than a full-screen quad.

If all you need to do is access a 4x4 set of values from the fragment shader, that ought to be a uniform (buffer). Don’t try to over-complicate things.

The reason why I wanted to use a texture (and why the author of the tutorial used it) is that in the SSAO shader that random vec3 value is used to rotate the kernel which samples the area around a fragment. This rotation is used to effectively increase the number of samples which removes the banding artifacts and since the the texture size is small and tiled across the entire screen it introduces a high frequency regularity to the resulting image which can then be removed by blurring.

So I am supposed to have a repeating texture pattern like this available in the SSAO fragment shader:

A B C D
E F G H
I J K L
M N O P

At fragment (0, 0) located in the top left corner of the screen I should sample random value A, and at fragment (3, 0) I should sample A again, and at (0, 1) I should sample E, at (3, 1) E again etc., so that the regularity is preserved. That is why I thought that sampling a repeating texture is the easiest / fastest way to do it.

I guess that I could map the current texture coordinate in the fragment shader to one of the 16 values using some kind of modulo operation. Do you think that would be a better approach? Thanks again for your help.

That is why I thought that sampling a repeating texture is the easiest / fastest way to do it.

Texture accesses are not fast. Oh sure, a 4x4 texture will probably be cached pretty quickly. But that still leaves plenty of overhead for the access, since it is a global memory fetch. Uniforms are local, constant memory.

And quite frankly, the only advantage of using a texture is that you get repeat filtering.

It is far easier and faster to simply access a 4x4 uniform array:


uniform vec3 Table[4][4];

...

vec2 clamped = mod(gl_FragCoord.xy, 4);
doStuffWithTableEntry(Table[clamped.x][clamped.y]);

See? You don’t even need to pass “texture coordinates”.

In fact… why use a uniform at all? Unless this table will change, just use a const array, declared entirely in the shader.

That is why I thought that sampling a repeating texture is the easiest / fastest way to do it.

Texture accesses are not fast. Oh sure, a 4x4 texture will probably be cached pretty quickly. But that still leaves plenty of overhead for the access, since it is a global memory fetch. Uniforms are local, constant memory.

And quite frankly, the only advantage of using a texture is that you get repeat filtering.

It is far easier and faster to simply access a 4x4 uniform array:


uniform vec3 Table[4][4];

...

vec2 clamped = mod(gl_FragCoord.xy, 4);
doStuffWithTableEntry(Table[clamped.x][clamped.y]);

See? You don’t even need to pass “texture coordinates”.

In fact… why use a uniform at all? Unless this table will change, just use a const array, declared entirely in the shader.

Thanks a lot Alfonse, a const array seems like the best way to do it.