PBR projected texture shader

Post Reply
admin
Site Admin
Posts: 2
Joined: Wed Jul 26, 2017 6:25 pm

PBR projected texture shader

Post by admin » Fri May 25, 2018 4:40 pm

texture loader...

Code: Select all

    Public Function load_dds_file(ByVal fs As String) As Integer
        Dim image_id As Integer = -1
        Dim texID As UInt32
        
        texID = Ilu.iluGenImage() 
        Il.ilBindImage(texID) 
        Dim success = Il.ilGetError
        Il.ilLoad(Il.IL_DDS, fs)
        success = Il.ilGetError
        If success = Il.IL_NO_ERROR Then
            'Ilu.iluFlipImage()
            ' Ilu.iluMirror()
            Dim width As Integer = Il.ilGetInteger(Il.IL_IMAGE_WIDTH)
            Dim height As Integer = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT)
            'Dim dds_format = Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT)
            'Debug.WriteLine(dds_format.ToString)

            'Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE)

            'success = Il.ilConvertImage(Il.IL_RGBA, Il.IL_UNSIGNED_BYTE)

            Gl.glGenTextures(1, image_id)
            Gl.glEnable(Gl.GL_TEXTURE_2D)
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, image_id)
            If largestAnsio > 0 Then
                Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAX_ANISOTROPY_EXT, largestAnsio)
            End If
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR)
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR_MIPMAP_LINEAR)
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_GENERATE_MIPMAP, Gl.GL_TRUE)

            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT)
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT)

            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, width, height, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE,  Il.ilGetData()) '  Texture specification 


            Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0)
            Il.ilBindImage(0)
            Ilu.iluDeleteImage(texID)
            Gl.glFinish()
            Return image_id
        Else
            log_text.AppendLine("File Missing: " + fs)
        End If
        Return Nothing
    End Function

vertex section...

Code: Select all

//decalCpass_vertex.glsl

#version 330 compatibility 

out mat4 matPrjInv;
out mat4 invDecal_mat;
out mat2 uv_matrix;

out vec4 ShadowCoord;
out vec4 positionSS;
out vec3 v_Position;

uniform mat4 decal_matrix;
uniform float uv_rotate;

void main(void)
{
    gl_Position = decal_matrix * gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Position;
    positionSS =gl_Position;

    v_Position = vec3(gl_ModelViewMatrix * gl_Vertex);

    matPrjInv = inverse(gl_ModelViewProjectionMatrix);

    invDecal_mat = inverse(decal_matrix);
    uv_matrix = mat2 (
        vec2( cos(uv_rotate), -sin(uv_rotate) ), 
        vec2( sin(uv_rotate),  cos(uv_rotate) )
        );                  
}
Fragment section...

Code: Select all

//decalCpass_fragment.glsl

#version 330 compatibility
#extension GL_EXT_gpu_shader4 : enable

layout (location = 0) out vec4 gColor;
//layout (location = 1) out vec4 gNormal;
//layout (location = 2) out vec4 gPosition;
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform sampler2D gmmMap;

uniform sampler2D shadowMap;// produced in depth_fragment

uniform sampler2D depthMap; // copied from depth buffer


uniform sampler2D gNormalMap; // produced in TerrainShader_Fragment
uniform sampler2D fogMap; // produced in TerrainShader_Fragment

uniform samplerCube cubeMap; // loaded resource
uniform sampler2D u_brdfLUT; // loaded resource

uniform int use_shadow; // switch
uniform float alpha_value; // slider value
uniform float color_level; // slider value
uniform vec2 uv_wrap; // wrap
uniform vec3 viewPos; // camera position
uniform vec3 LightPos[3]; // the 3 light positions
uniform mat4 shadowProjection; // light position shadow matrix

uniform vec4 u_ScaleFGDSpec; // display switches
uniform vec4 u_ScaleDiffBaseMR; // display switches

const vec3 tr = vec3 (0.5 ,0.5 , 0.5);
const vec3 bl = vec3(-0.5, -0.5, -0.5);
in mat4 invDecal_mat; // inverse decal matrix
in mat4 matPrjInv; // inverse projection matrix
in mat2 uv_matrix; // texture rotation matrix. Created in vertex section
//in vec4 ShadowCoord;
in vec3 v_Position; // vertex in model view space
in vec4 positionSS; // vertex in screen space 


void clip(vec3 v){
    if (v.x > tr.x || v.x < bl.x ) {
        discard;
    }
    if (v.y > tr.y || v.y < bl.y ) {
        discard;
    }
    if (v.z > tr.z || v.z < bl.z ) {
        discard;
    }
}

vec3 correction(vec3 color_in){
    const float exposure =2.2;
    vec3 mapped = vec3(1.0) - exp(-color_in * exposure);
    return mapped;
}


vec2 postProjToScreen(vec4 position)
{
    vec2 screenPos = position.xy / position.w;
    return 0.5 * (vec2(screenPos.x, screenPos.y) + 1);
}

vec4 ShadowCoordPostW;
vec2 moments ;
vec4 ShadowCoord;
float alphaGMM;
float chebyshevUpperBound( float distance)
{
    // make sure we are actually on the depth texture!
    if (ShadowCoordPostW.x >1.0) return 1.0;
    if (ShadowCoordPostW.x <0.0) return 1.0;
    if (ShadowCoordPostW.y >0.7) return 1.0;
    if (ShadowCoordPostW.y <0.1) return 1.0;
    moments = texture2D(shadowMap,ShadowCoordPostW.xy).rg;
    // Surface is fully lit. as the current fragment is before the light occluder
    if (distance <= moments.x)
        return 1.0 ;
    // The fragment is either in shadow or penumbra.
    // We now use chebyshev's upperBound to check
    // How likely this pixel is to be lit (p_max)
    float variance = moments.y - (moments.x*moments.x);
    variance = max(variance,0.5);
    float d = distance - moments.x;
    float p_max =  smoothstep(0.1, 0.18, variance / (variance + d*d));
    //float p_max =   variance / (variance + d*d);
    p_max = max(p_max,0.55);
    return p_max ;
}

vec3 getNormal(vec2 iUV,vec2 UVn,vec3 pos)
{
    // compute derivations of the world position
    vec3 p_dx = dFdx(pos);
    vec3 p_dy = dFdy(pos);
    // compute derivations of the texture coordinate
    vec2 tc_dx = dFdx(iUV);
    vec2 tc_dy = dFdy(iUV);
    // compute initial tangent and bi-tangent
    vec3 t = normalize( tc_dy.y * p_dx - tc_dx.y * p_dy );
    vec3 b = normalize( tc_dy.x * p_dx - tc_dx.x * p_dy );
    // sign inversion
    // get new tangent from a given mesh normal
    vec3 ng = normalize(texture2D(gNormalMap, UVn).rgb)*2.0-1.0;
    //ng = normalize(cross(p_dx,p_dy));
    //ng.y *= -1.0;
    t = normalize(t - ng * dot(ng, t));
    //vec3 b = normalize(cross(ng, t));
    mat3 tbn = mat3(t, b, ng);
    //n = texture2D(normalMap, iUV*uv_wrap).rgb*2.0-1.0;
    vec4 tn = texture2D(normalMap, iUV*uv_wrap).rgba*2.0-1.0;
    vec3 co;
    co.xy = tn.ag;
    co.z = sqrt(1.0 - clamp( ((tn.x*tn.x) + (tn.y*tn.y)) ,-1.0,1.0) ); // sqrt was causing a early discard. This fixes it!
    co.y *= -1.0;
    co = tbn * co;
    
    //co.z*=-1.0; // not sure why but it looks better this way!
    //co.y*=-1.0; // not sure why but it looks better this way!
    //return normalize(co.rgb);
    return normalize(co.rgb);
}


// PBR Functions ======================================================
// Encapsulate the various inputs used by the various functions in the shading equation
// We store values in this struct to simplify the integration of alternative implementations
// of the shading terms, outlined in the Readme.MD Appendix.
struct PBRInfo
{
    float NdotL;
    // cos angle between normal and light direction
    float NdotV;
    // cos angle between normal and view direction
    float NdotH;
    // cos angle between normal and half vector
    float LdotH;
    // cos angle between light direction and half vector
    float VdotH;
    // cos angle between view direction and half vector
    float perceptualRoughness;
    // roughness value, as authored by the model creator (input to shader)
    float metalness;
    // metallic value at the surface
    vec3 reflectance0;
    // full reflectance color (normal incidence angle)
    vec3 reflectance90;
    // reflectance color at grazing angle
    float alphaRoughness;
    // roughness mapped to a more linear change in the roughness (proposed by [2])
    vec3 diffuseColor;
    // color contribution from diffuse lighting
    vec3 specularColor;
    // color contribution from specular lighting
};
const float M_PI = 3.141592653589793;
const float c_MinRoughness = 0.1;
// used for debug.. shows different parts of the lighting

#define MANUAL_SRGB;
vec4 SRGBtoLINEAR(vec4 srgbIn)
{
    #ifdef MANUAL_SRGB
    #ifdef SRGB_FAST_APPROXIMATION
    vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
    #else //SRGB_FAST_APPROXIMATION
    vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
    vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
    #endif //SRGB_FAST_APPROXIMATION
    return vec4(linOut,srgbIn.w);
    ;
    #else //MANUAL_SRGB
    return srgbIn;
    #endif //MANUAL_SRGB
}



vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection)
{
    float mipCount = 9.0;
    // resolution of 512x512
    float lod = ((1.0-pbrInputs.perceptualRoughness) * mipCount);
    // retrieve a scale and bias to F0. See [1], Figure 3
    vec3 brdf = SRGBtoLINEAR(texture2D(u_brdfLUT, vec2(pbrInputs.NdotV*0.1, (1.0 - pbrInputs.perceptualRoughness)*0.1))).rgb;
    vec3 diffuseLight = SRGBtoLINEAR(textureCubeLod(cubeMap, n, 7)).rgb;
    reflection.yz *= -1.0;
    // like so many other things, DirectX to OpenDL causes axis issues.
    vec3 specularLight = SRGBtoLINEAR(textureCubeLod(cubeMap, reflection, lod)).rgb;
    vec3 diffuse = diffuseLight * pbrInputs.diffuseColor;
    vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y);
    // For presentation, this allows us to disable IBL terms
    return diffuse + specular;
}


vec3 diffuse(PBRInfo pbrInputs)
{
    return pbrInputs.diffuseColor /M_PI;
}


vec3 specularReflection(PBRInfo pbrInputs)
{
    return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 1.5);
}


float geometricOcclusion(PBRInfo pbrInputs)
{
    float NdotL = pbrInputs.NdotL;
    float NdotV = pbrInputs.NdotV;
    float r = 0.3;
    //pbrInputs.alphaRoughness;

    float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
    float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
    return attenuationL * attenuationV;
}


float microfacetDistribution(PBRInfo pbrInputs)
{
    float roughnessSq = 0.05;
    //pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
    float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
    return roughnessSq / (M_PI * f * f);
}


// end PBR functions ===============================================================

void main(){
    float shadow = 1.0;
    float falloff = 1.0;
vec3 lightColor[3];
    lightColor[0] = vec3 (0.6,0.0,0.0);
    lightColor[1] = vec3 (0.0,0.6,0.0);
    lightColor[2] = vec3 (0.0,0.0,0.8);
    lightColor[0] = vec3 (0.5);
    lightColor[1] = vec3 (0.5);
    lightColor[2] = vec3 (0.5);

 //=========================================================
    // Calculate UVs
    vec2 UV = postProjToScreen(positionSS);
    // sample the Depth from the Depthsampler
    float Depth = texture2D(depthMap, UV).x * 2.0 - 1.0;
    // Calculate Worldposition by recreating it out of the coordinates and depth-sample
    vec4 ScreenPosition;
    ScreenPosition.xy = UV * 2.0 - 1.0;
    ScreenPosition.z = (Depth);
    ScreenPosition.w = 1.0f;
    // Transform position from screen space to world space
    vec4 WorldPosition = matPrjInv * ScreenPosition ;
    WorldPosition.xyz /= WorldPosition.w;
    WorldPosition.w = 1.0f;
    // trasform to decal original and size.
    ShadowCoord = shadowProjection * WorldPosition;
    vec3 world = vec3(WorldPosition);
    // this is world space!
    WorldPosition = invDecal_mat * WorldPosition;
    clip (WorldPosition.xyz);
    /*==================================================*/
    //Get texture UVs
    WorldPosition.xy += 0.5;
    WorldPosition.y *= -1.0;
    vec2 UV_ = uv_matrix * WorldPosition.xy;
    UV_.x *=-1.0;// better ot flip it than mirror the images at load.
    //=========================================================
    if (use_shadow == 1){
        ShadowCoordPostW = ShadowCoord / ShadowCoord.w;
        // Depth was scaled up in the depth writer so we scale it up here too.
        // This fixes precision issues.
        shadow = chebyshevUpperBound(ShadowCoordPostW.z*5000.0);
    }

    //=========================================================
    vec4 color = texture2D(colorMap,  UV_.st*uv_wrap);
    color.rgb *= color_level;
    vec3 GMM   = texture2D(gmmMap,    UV_.st*uv_wrap).rgb;
    alphaGMM = texture2D(gmmMap,    UV_.st*uv_wrap).a;
    vec2 AO = vec2(0.75);

    //=========================================================
    float perceptualRoughness = 0.3;
    float metallic = 0.2;
    // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
    // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
    //vec4 mrSample = vec4(1.0 , 1.0-GMM.r, GMM.g ,1.0);
    vec4 mrSample = vec4(1.0 , GMM.g* alphaGMM, 1.0-GMM.r ,1.0);
    // setup correct loctaions
    //mrSample = vec4(AO.r , pow(GMM.r/1.0,2.0), pow(GMM.g/1.0,1.0) ,1.0);
    // setup correct loctaions
    perceptualRoughness = mrSample.g;
    metallic = max(mrSample.b,0.1) * metallic;


    perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
    metallic = clamp(metallic, 0.0, 1.0);
    // Roughness is authored as perceptual roughness; as is convention,
    // convert to material roughness by squaring the perceptual roughness [2].
    float alphaRoughness = perceptualRoughness * perceptualRoughness;
    // The albedo may be defined from a base texture or a flat color
    vec4 baseColor = color;

    vec3 f0 = vec3(0.04);
    vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
    diffuseColor *= 1.0 - metallic;
    vec3 specularColor = mix(f0, baseColor.rgb, metallic);
    // Compute reflectance.
    float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
    // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
    // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
    float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
    vec3 specularEnvironmentR0 = specularColor.rgb;
    vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;

vec4 sum = vec4(0.0);

for (int i = 0; i < 3; i++){

      
        //lp = invd_mat * lp;
        vec3 ll = LightPos[i].xyz;
        vec3 n = getNormal(UV_, UV, world);// normal at surface point
        vec3 v = normalize(viewPos - world);// Vector from surface point to camera
        vec3 l = normalize(ll - world);// Vector from surface point to light
        vec3 h = normalize(l+v);// Half vector between both l and v
        vec3 reflection = normalize(reflect(-v, n));
        vec3 R = normalize(reflect(-v,n));
        float NdotL = clamp(dot(n, l), 0.001, 1.0);
        float NdotV = abs(dot(n, v)) + 0.001;
        float NdotH = clamp(dot(n, h), 0.0, 1.0);
        float LdotH = clamp(dot(l, h), 0.0, 1.0);
        float VdotH = clamp(dot(v, h), 0.0, 1.0);

        PBRInfo pbrInputs = PBRInfo(
            NdotL,
            NdotV,
            NdotH,
            LdotH,
            VdotH,
            perceptualRoughness,
            metallic,
            specularEnvironmentR0,
            specularEnvironmentR90,
            alphaRoughness,
            diffuseColor,
            specularColor
        );
        // Calculate the shading terms for the microfacet specular shading model
        vec3 F = specularReflection(pbrInputs);
        float G = geometricOcclusion(pbrInputs);
        float D = microfacetDistribution(pbrInputs)* GMM.r;
        vec3 u_LightColor = vec3(0.5,0.5,0.5);
        // Calculation of analytical lighting contribution
    vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);
    vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV);
    vec3 sSpec = vec3(1.0) * pow(max(dot(R,l),0.0),10.0) * 0.00;
        // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
    vec3 colorMix =  NdotL * u_LightColor * ((sSpec + diffuseContrib) + (specContrib * mrSample.g*1.0))*6.0;
    colorMix += NdotV * getIBLContribution(pbrInputs, n, R)
                *perceptualRoughness ;
    vec3 ambient = diffuseContrib.rgb *0.25;
    colorMix += (ambient + (ambient*NdotL));
    colorMix *= vec3(shadow);
       // Calculate lighting contribution from image based lighting source (IBL)
    #define USE_IBL;
    #ifdef USE_IBL
    #endif

    // This section uses mix to override final color for reference app visualization
    // of various parameters in the lighting equation. Great for Debuging!
    colorMix = mix(colorMix, F, u_ScaleFGDSpec.x);
    colorMix = mix(colorMix, vec3(G), u_ScaleFGDSpec.y);
    colorMix = mix(colorMix, vec3(D), u_ScaleFGDSpec.z);
    colorMix = mix(colorMix, specContrib, u_ScaleFGDSpec.w);

    colorMix = mix(colorMix, diffuseContrib, u_ScaleDiffBaseMR.x);
    colorMix = mix(colorMix, baseColor.rgb, u_ScaleDiffBaseMR.y);
    colorMix = mix(colorMix, vec3(metallic), u_ScaleDiffBaseMR.z);
    colorMix = mix(colorMix, vec3(perceptualRoughness), u_ScaleDiffBaseMR.w);

    sum.rgb += colorMix.rgb *0.5 ;
    //sum.rgb += vec3(sSpec) * lightColor[i] + colorMix.rgb *0.0001;
    //gColor.rgb = (gColor.rgb*vec3(0.001)) + vec3(shadow) * T_level * 2.0;
    
}// i loop

    //=========================================================
    vec4 groundFog = texture2D(fogMap,vec2(UV.x,UV.y));
    float z = length(world);
    float height = sin(1.0-( (world.y+3.0)/50.0)*(3.1415/2.0));
    const float LOG2 = 1.442695;
    vec4 fog_color = vec4(vec3(0.35),1.0);

    //the moving ground fog
    float density = (gl_Fog.density * height) * 0.03;
    float fogFactor = exp2(-density * density * z * z * LOG2);
    fogFactor = clamp(fogFactor, 0.0, 1.0);
    gColor.rgb = sum.rgb+groundFog.xyz;
    gColor.rgb = mix(fog_color.rgb, gColor.rgb, fogFactor );
    gColor.a = color.a * alpha_value;
    //gColor.rgb = gColor.rgb * vec3(0.0001) + vec3(getNormal(UV_, UV, world));
    //gColor.rgb = gColor.rgb * vec3(0.0001) + vec3(texture2D(normalMap,  UV_.st*uv_wrap).g);
    }


Post Reply