Source

dark-hammer / data / shaders / hlsl / df-light.ps.hlsl

The branch 'v0.4' does not exist.
/***********************************************************************************
 * Copyright (c) 2012, Sepehr Taghdisian
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, 
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution.
 *
 ***********************************************************************************/

struct vso
{
    float4 pos : SV_Position;
    float2 coord : TEXCOORD0;
    float3 viewray : TEXCOORD1;
#if defined(_LOCAL_LIGHTING_)
    nointerpolation uint tile_id : TEXCOORD2;
#endif
};

/* global constants */
float4 c_projparams;

#if defined(_SUN_LIGHTING_)
float4 c_ambient_sky;
float4 c_ambient_ground;
float c_ambient_intensity;
float3 c_skydir_vs;     /* direction of the sky (view-space) */

float3 c_lightdirinv_vs;   /* direction (view-space) */
float4 c_lightcolor;    /* linear space color (premultiplied) */
#endif

/* material */
struct mtl
{
    float4 ambient_clr;
    float4 diff_clr;
    float4 spec_clr;
    float4 emissive_clr;
    float4 props;       /* extra props */
};

#if defined(_LOCAL_LIGHTING_)

#define LIGHT_TYPE_POINT 2.0f
#define LIGHT_TYPE_SPOT 3.0f

/* light */
struct local_light
{
    float4 type;   /* type.x: point=2, spot=3 */
    float4 pos_vs; /* position (view-space) */
    float4 atten;  /* attenuations (x=near, y=far, z=cos(narrow), w=cos(wide) */
    float3 dir_vs; /* direction (view-space) */
    float4 color;  /* linear space color (pre-multiplied) */
};

struct local_light_tile
{
    uint4 lightcnt;  /* x = cnt */
    uint4 lightidxs[_MAX_LIGHT_INDEXES_/4];
};

cbuffer cb_light
{
    local_light_tile c_tiles[_MAX_TILES_];
};

tbuffer tb_lights
{
    local_light c_lights[_MAX_LIGHTS_];
};
#endif

tbuffer tb_mtls
{
    mtl c_mtls[_MAX_MTLS_];
};

/* textures */
Texture2D<float> s_depth;
Texture2D<float2> s_norm;
Texture2D<float4> s_albedo;
Texture2D<uint2> s_mtl;
#if defined(_SUN_LIGHTING_)
Texture2D<float4> s_shadows;
Texture2D<float4> s_ssao;
#endif

/* functions */
float3 calc_lit(float3 diff_clr_over_pi, float3 spec_clr, float3 lv, float3 vv, 
    float3 norm, float gloss, float4 light_clr, float a_t)
{
    /* Microfacet BRDF Torrance-Sparrow (Lazarov11)
     * f(l, v) = c_diff/PI + f(v, h)*G(l, v, h)*D(h)/4(n.l)(n.v)
     */
    /* calculate base values (light-vector, half-vector, n_dot_l) */
    float3 hv = normalize(vv + lv);
    float n_dot_l = max(0, dot(norm, lv));

    /* reflectance (specular) */
    float3 fresnel = calc_fresnel_schlick(hv, vv, spec_clr);
    float vis_t = calc_vis_term(n_dot_l, norm, vv, gloss, a_t);
    float blinnphong_t = calc_blinnphong_norm_term(hv, norm, gloss);
    float3 spec_refl = fresnel*(vis_t*blinnphong_t);

    return (diff_clr_over_pi + spec_refl)*light_clr.rgb*n_dot_l;
}

#if defined(_LOCAL_LIGHTING_)
float calc_dist_atten(float3 lv, float anear, float afar, out float lv_len)
{
    lv_len = length(lv);
    return 1.0f - smoothstep(anear, afar, lv_len);
}

float calc_angle_atten(float3 ldir, float3 lv, float anarrow, float awide)
{
    return smoothstep(awide, anarrow, dot(ldir, -lv));
}
#endif

float4 main(vso input) : SV_Target0
{
    int3 coord2d = int3(input.pos.xy, 0);

    /* reconstruct position */
    float depth = s_depth.Load(coord2d);
    clip(0.999999f - depth);

    float depth_vs = c_projparams.w / (depth - c_projparams.z);    /* view depth */
    float3 pos_vs = depth_vs * input.viewray;

    /* material/gloss/a-term */
    uint2 mtl_enc = s_mtl.Load(coord2d);
    uint mtl_idx;
    float gloss;
    mtl_decode(mtl_enc, mtl_idx, gloss);
    mtl m = c_mtls[mtl_idx];
    float a_t = 1.0f / sqrt(PI_OVER_4*gloss + PI_OVER_2);

    /* reconstruct normal */
    float2 norm = s_norm.Load(coord2d);
    float3 norm_vs = normal_decode_spheremap(norm);

    /* albedo/diffuse color */
    float4 g1 = s_albedo.Load(coord2d);
    float3 diff_albedo = g1.rgb * m.diff_clr.rgb;
    float3 diff_over_pi = diff_albedo/PI;

    /* specular intensity */
    float3 spec_clr = g1.a * m.spec_clr.rgb;

    /* view-vector */
    float3 vv = -normalize(pos_vs);

#if defined(_SUN_LIGHTING_)
    /* light-vector */
    float3 lv = c_lightdirinv_vs;

    float3 lit_clr = calc_lit(
        diff_over_pi,
        spec_clr,
        lv, vv, norm_vs,
        gloss,
        c_lightcolor,
        a_t);

    /* shadows/ssao */
    float4 shadow = s_shadows.Load(coord2d);
    float4 ssao = s_ssao.Load(coord2d);

    /* ambient */
    float3 ambient = calc_ambient_spherical(norm_vs, c_skydir_vs, c_ambient_sky.xyz, 
        c_ambient_ground.xyz) * diff_albedo;
    ambient *= c_ambient_intensity;
    ambient *= ssao.xyz;
    
    /* final lit (considering shadows and ambient) */
    lit_clr *= shadow.xyz;
    lit_clr += ambient;
#elif defined(_LOCAL_LIGHTING_)
    float3 lit_clr = float3(0, 0, 0);

    local_light_tile tile = c_tiles[input.tile_id];
    for (uint i = 0; i < tile.lightcnt.x; i++)    {
        uint vidx = i/4;
        uint subidx = i % 4;
        uint lightidx = tile.lightidxs[vidx][subidx];
        local_light light = c_lights[lightidx];

        /* light-vector */
        float3 lv = light.pos_vs.xyz - pos_vs;

        /* attenuation */
        float lv_len;
        float atten = calc_dist_atten(lv, light.atten.x, light.atten.y, lv_len);

        [flatten]
        if (light.type.x == LIGHT_TYPE_SPOT)
            atten *= calc_angle_atten(light.dir_vs, lv, light.atten.z, light.atten.w);

        /* lit calc */
        lv /= lv_len;   /* normalize light-vect for light calc */
        lit_clr += atten * calc_lit(diff_over_pi,
            spec_clr,
            lv, vv, norm_vs,
            gloss, 
            light.color,
            a_t);
    }
#endif

    return float4(lit_clr, 1);    
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.