1
\$\begingroup\$

I'm currently experimenting a little bit on level design. Let's say that I've a room composed of walls and a floor tiles. I'd like to apply to all these elements a sort of "grain" effect, similar to concrete. I wonder which is the better way to go... the only think I can immagine is working with texture directly, so for each element create the texture that already contains the "grain" effect.

I've also tried to apply a generic screen shader but the result is not good because the grain is fixed to the screen, I wanted it to be fixed to walls/floor. Obviously creating all the textures is a long process and I have to keep UV absolutelly proportional for each element.

I'm ok with that solution actually but I wonder if there is anyother way to apply this effect all in once in a simpler and "safer" way, soemthing like a decal that maybe adds also some imperfections.

\$\endgroup\$
  • \$\begingroup\$ You want the grain effect to move or just be static? Otherwise just render the walls with a second texure wich is just a noise map and sample from it. \$\endgroup\$ – Sidar Jul 29 '17 at 10:48
  • \$\begingroup\$ Use a grainy normal map for the models you want to have the grainy texture. \$\endgroup\$ – Andrew Wilson Jul 29 '17 at 11:10
  • \$\begingroup\$ If UV mapping your environment is too arduous, or you just need something quick, you can also map a tiling grain texture in worldspace. For flat/faceted surfaces, this can be done quite efficiently. For arbitrarily curved surfaces you need tri-planar mapping, which gets substantially more expensive. \$\endgroup\$ – DMGregory Jul 29 '17 at 12:19
  • \$\begingroup\$ The object are statics @Sidar \$\endgroup\$ – MatterGoal Jul 29 '17 at 13:33
  • 1
    \$\begingroup\$ So why not pass a second texture unit ( a noise map) or use a perlin noise function in your shader and mix it with the final result? Maybe I'm not getting it though. \$\endgroup\$ – Sidar Jul 30 '17 at 16:22
1
\$\begingroup\$

If you are talking about just adding noise there are simple options and a combination of the two.

Either case are simply achieved by multiplying the output color with a grey scale value.

How to get this greyscale value?

A: Noise functions

B: Texture sampling

How you sample from either is up to you. You can project from screen space, world space, object position what have you. If you just want it static simply use the uv mapping of your object.

Here is an example : AWSD to move, mouse to look around. Check the simple.frag.glsl tab/file.

You can also combine option A and B and do all sorts of trickery to your liking but the most basic look is done by simply sampling and multiplying. subtracting, adding, didiving whatever suites you.

Snippet for Noise function

#version 450

// Uv coordinates
in vec2 vUV;

// In your case the brick texture
uniform sampler2D myTextureSampler;

// our final color data
out vec4 fragColor;

// Noise resolution
float noiseScale = 1000.0;

//-----------------------------
// Noise function
float rand(vec2 n) { 
    return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}

float noise(vec2 p){
    vec2 ip = floor(p);
    vec2 u = fract(p);
    u = u*u*(3.0-2.0*u);

    float res = mix(
        mix(rand(ip),rand(ip+vec2(1.0,0.0)),u.x),
        mix(rand(ip+vec2(0.0,1.0)),rand(ip+vec2(1.0,1.0)),u.x),u.y);
    return res*res;
}
//------------------------------------------

void main() {

     //Get noise value
    float n = noise(vUV*noiseScale);

    // Get brick texture sample - 
    //that is if your texture is a brick texture of course
    vec4 color = texture(myTextureSampler, vUV);

    // Multiply the RGB color of your main texture with the noise
    // Add 0.5 so we at least retain more bright colors
    color.rgb *=n+0.5;

    // Tell OpenGL color is our final result
    fragColor = color;
}

Snippet for Texture sampling

#version 450

// Uv coordinates
in vec2 vUV;

// In your case the brick texture
uniform sampler2D myTextureSampler;
uniform sampler2D myNoiseSampler;

// our final color data
out vec4 fragColor;

void main() {



    // Get brick texture sample - 
    //that is if your texture is a brick texture of course
    // Then get noise sample, just taking green, red and blue would work too.
    vec4 color = texture(myTextureSampler, vUV);
    float n = texture(myNoiseSampler, vUV).g;

    // Multiply the RGB color of your main texture with the noise
    // Add 0.5 so we at least retain more bright colors
    color.rgb *=n+0.5;

    // Tell OpenGL color is our final result
    fragColor = color;
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.