(SSR) Screen-Space Reflections Shader v0.7

Oh, yeah. I’ve been told that render attachments would be useful. I really have to take a look at it and learn how to use those.

Hmm, I changed the FOV value to the mentioned 49.1 and it doesn’t really change the obverved strange effects. So I’ll explain in more detail:

Here, you see the reflection of the texture on the ground:

Once the animation starts and the cam moves/turns towards it, the reflection moves updwards into the floating image itself. This is what looks strange to me.

Second thing is the limited “reflection depth” (not sure how to call it), e.g. here:

Maybe you know a way to influence both effects.

Oh wow. I hadn’t noticed the first thing at all! That’s really weird. I don’t know what causes it, but i’ll check it out,

As for the second one, there are two settings in the shader to correct it. On lines 27 and 28, the numbers you have to change are called stepSize and sampleSteps. These control the maximum distance a ray of light will travel. A larger stepSize will give you longer distances in exchange of less accurate reflections, a larger sampleSteps will give you longer distances in exchange for reduced speed.

Ideally, you want their product to equal one (i.e. stepSize * sampleSteps = 1.0) in order to not get those artifacts. I ended up putting in a bad setting when I was testing some things and didn’t remember to put it back.

Happy new year! :slight_smile:

Any news here?

1 Like

Revive this topic folks,
i am going for it…
i am testing with the variables…

Yes. there is a way to make it work for refractions, make the reflections selective without using extra layers, smooth object edges and control roughness in vanilla bge.

but the below is just the real-time optmized version updated for both bge 2.79 and upbge 0.2.5. with my comentaries.

uniform sampler2D bgl_DepthTexture;
uniform sampler2D bgl_RenderedTexture;

uniform float bgl_RenderedTextureWidth;
uniform float bgl_RenderedTextureHeight;

float width = bgl_RenderedTextureWidth;
float height = bgl_RenderedTextureHeight;

vec2 texCoord = gl_TexCoord[0].st;

//#######################################
//these MUST match your current settings
float znear = 0.1;       //camera clipping start
float zfar = 100.0;       //camera clipping end

//the camera´s fov has to be of 90.0 degrees for this to work
float fov = 90.0 / 90.0; // so keep that equals 1 or help fix this shader

float aspectratio = 16.0/9.0;        //width / height (make sure you put a ".0" after your number)
vec3 skycolor = vec3(0.1,0.3,0.7);   //horizon color from world properties, fallback when reflections fail

//tweak these to your liking
float reflectance = 0.4; //reflectivity of surfaces that you face head-on

// try keep stepSize*samples equals 1.0 or 0.1
float stepSize = 0.01;  //reflection choppiness, the lower the finer & worse the performance 
int samples = 50;        //reflection distance, the higher the more far reaching and slower
float startScale = 4.0; //ray amplitude lod scale, higher for the faster & banded, has to be a power of 2

//#######################################

float getDepth(vec2 coord){
    float zdepth = texture2D(bgl_DepthTexture,coord).x;
    return -zfar * znear / (zdepth * (zfar - znear) - zfar);
}

vec3 getViewPosition(vec2 coord){
    vec3 pos = vec3((coord.s * 2.0 - 1.0) / fov, (coord.t * 2.0 - 1.0) / aspectratio / fov, 1.0);
    return (pos * getDepth(coord));
}

vec3 getViewNormal(vec2 coord){
    
    vec3 p0 = getViewPosition(coord);
    vec3 p1 = getViewPosition(coord + vec2(1.0 / width, 0.0));
    vec3 p2 = getViewPosition(coord + vec2(0.0, 1.0 / height));
  
    vec3 dx = p1 - p0;
    vec3 dy = p2 - p0;
    return normalize(cross( dy , dx ));
}

vec2 getViewCoord(vec3 pos){
    vec3 norm = pos / pos.z;
    vec2 view = vec2((norm.x / fov + 1.0) / 2.0, (norm.y / fov * aspectratio + 1.0) / 2.0);
    return view;
}

float lenCo(vec3 vector){
    return pow(pow(vector.x,2.0) + pow(vector.y,2.0) + pow(vector.z,2.0), 0.5);
}

vec3 rayTrace(vec3 startpos, vec3 dir){
    vec3 pos = startpos;
    float olz = pos.z;      //previous z
    float scl = startScale; //step scale
    vec2 psc;               // Pixel Space Coordinate of the ray's' current viewspace position 
    vec3 ssg;               // Screen Space coordinate of the existing Geometry at that pixel coordinate
    
    for(int i = 0; i < samples; i++){
        olz = pos.z; //previous z
        pos = pos + dir * stepSize * pos.z * scl;
        psc = getViewCoord(pos); 
        ssg = getViewPosition(psc); 
        if(psc.x < 0.0 || psc.x > 1.0 || psc.y < 0.0 || psc.y > 1.0 || pos.z < 0.0 || pos.z >= zfar){
            //out of bounds
            break;
        }
        if(scl == 1 && lenCo(pos) > lenCo(ssg) && lenCo(pos) - lenCo(ssg) < stepSize * 40){
            //collided
            return pos;
        }
        if(scl > 1 && lenCo(pos) - lenCo(ssg) > stepSize * scl * -1){
            //lower step scale
            pos = pos - dir * stepSize * olz * scl;
            scl = scl * 0.5;
        }
    }
    // this will only run if loop ends before return or after break statement
    return vec3(0.0, 0.0, 0.0);
}
float schlick(float r0, vec3 n, vec3 i){
    return r0 + (1.0 - r0) * pow(1.0 - dot(-i,n),5.0);
}

void main(){
    
    //fragment color data
    vec4 direct = texture2D(bgl_RenderedTexture, texCoord);
    vec4 reflection;
    
    //fragment geometry data
    vec3 position = getViewPosition(texCoord);
    vec3 normal   = getViewNormal(texCoord);
    vec3 viewVec  = normalize(position);
    vec3 reflect  = reflect(viewVec,normal);
    float fresnel = 1-schlick(reflectance, normal, viewVec);
   
    
    //raytrace collision
    vec3 collision = rayTrace(position, reflect);
    
    //choose method
    if(collision.z != 0.0){
        vec2 sampler = getViewCoord(collision);
        reflection  = texture2D(bgl_RenderedTexture,sampler,fresnel*4.0);
    }else{
        reflection.rgb = pow(skycolor,vec3(1,1,1)*(0.455));
       // reflection.rgb = skycolor; // Linear or sRGB.
    }
    
    gl_FragColor = mix(direct, reflection, schlick(reflectance, normal/2, viewVec));
}
1 Like

it does not work like that;
here is a rudimentary way to do color based selective reflections in 2.79 and up without extra layers,
replace your fragcolor declaration with this:

// it causes any color with less than 10.0% red to be reflective('selective' reflections)
// comment the line below to disable...
    gl_FragColor = mix(direct, reflection, 1-clamp(direct.r+(fresnel/2),0.0,0.1)*10);

@AeroLynx

  • The filter reconstruct normals from the depth buffer, so , it doesn’t know if an object is smoothed.
    one d have to apply some sort of edge blur to the normals to smooth it out.
    btw: sebastian’s optmized version (up in the thread) have better performance.

  • use the TheLumcoin version as it allows for a FOV other than 90 and lets you choose how to deal with the occluded rays.

  • at this point you may already know but,as implied by the name, the shader will not reflect things outside the camera view, even with high settings.

1 Like

Sorry Murilo, but does this mean you have made a SSR script that works with upbge 0.25? If so, how would we go about testing it? Sorry, not much of a tech guy myself…

1 Like

i didnt made the script. i just ported it to 2,5. yes.

just paste it to a text inside blender and plug it into a custom 2d filter actuator.

1 Like

dont be sorry, ask as much as you need to know.
By ‘porting’ i mean: debugged the deprecations. XD

But wait. i’ve made mods to some ssr scripts, and i also ‘ported’ the thelumcoin’s version.
and i ve made a version to Upbge render attachments. Is that what you mean?

i am not a tech guy either, more to the artistic side. i just know how to mess with some glsl functions.
i dont feel confident to post them yet. you want to test them? or you just dont know how to use custom 2d filters?

2 Likes

Hey, thanks for taking the time to explain. I did try this out and it works! But I get some issues, like the reflection will move closer or farther to the source object as you look up or down, and also every material in the scene was reflective, but maybe there’s some information about how to set up reflective and non reflective materials in this thread that I havent read yet.

This does have potential, it would be great to have ssr, but it seems there are a few issues still to polish.

And yes, I do know how to use custom filters with logic bricks (and those that need properties, when documented), but I havent really found a lot of information on render attachments.

1 Like

it seems like you have to adjust to the user settings inside the filter (the camera FOV mainly). I mean adjust the camera’s FOV to 90 degrees.

this thread says nothing about selective reflections, except my silly attempt in the post right before your first reply to me. See there.

render attachments are extra layers of information, off-screens blender system writes to.
those are then used inside the filter by declaring:

uniform sampler2D bgl_DataTextures[7];
   // this takes all slots to the shader

Then if your attachment is in the slot number 1, you say:

 vec3 mask = texture(bgl_DataTextures[1], gl_TexCoord[0].st).rgb;

you can use the R channel of the attachment of the type ‘custom’ to determs the reflectance of a material. And the G channel to do roughness.

 reflection  = texture2DLod(bgl_RenderedTexture, sampler, mask.g*10);  

 gl_FragColor = mix(directColor, reflection , mask.r);

if you use render attachments, all your materials have to be node based (to inform the output).
the filter has to support it,otherwise render attachments are useless.

this is all i know for now.

1 Like

There are 3 predefined types I think for the render attachmenta buffers

Normal, custom, and position

Normal and position don’t require user node input

1 Like

thanks Jacob,
i think its

Albedo, Normal, and Custom.

positions cam be recreated from the depth texture.

i mean for this specific shader i have to put a black attachment output for every material that i dont want to be reflective.

1 Like

yeah a metalness buffer if you will

1 Like

here is a test file with the color based reflections:
color_based_selective_reflections.blend
this works in old bge 2.79 and dont use render attachments.

2 Likes

Wow, that was absolutely amazing! Will definitely study this one and try to bring to my project. Thanks a lot for this, Murilo!

1 Like

Im just messing with it and having fun with your showcase map, really cool stuff. But I was looking into the code and I was wondering if its possible to set a sort of bias as you would do to the reflection texture when using the normal cubemap reflections? (For blurred reflections)

Like this example:

No problem :wink:

enable mipmaps in the ssrr 2dfilter logic brick checkbox (if you using Upbge)

line 117
where it says:
reflection = texture2D(bgl_RenderedTexture, sampler, fresnel*4.0);

fresnel*4.0 is the lod factor, you can increase it.

add to it like: … , 2.0 + fresnel*4.0);

but the result will not be great cuz the fallback skycolor is not part of the texture and will not be blured together.

1 Like

Hey there, It looks like you have done some good work bringing this script up to date!

Would you like to post it in the forums as a standalone thread? If not, would you want me to at least link to your file on the OP?

I don’t think I will keep maintaining this, but I did put it up on my Github page here, so it can be worked on collaboratively more easily

  • I only solved the deprecations, no big deal. I didnt used the newest technologies (extra layers)
  • Maybe, when i gain new interest in the subject.
  • Sure. its yours. :slightly_smiling_face:
    the main function has diffuse dependent reflectance which is an experiment. The user have to have precise control of the colors in the scene.