aboutsummaryrefslogtreecommitdiffstatsci
path: root/samples/Model/shaders/model.frag
blob: 59944a4fee6fc558d03e3d572478e4baf4e4e037 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#version 450

#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (set = 1, binding = 0) uniform sampler2D samplerColor;
layout (set = 1, binding = 1) uniform sampler2D samplerNormal;
layout (set = 1, binding = 2) uniform sampler2D samplerOcclusion;
layout (set = 1, binding = 3) uniform sampler2D samplerMetalRoughness;
layout (set = 1, binding = 4) uniform sampler2D samplerEmissive;

layout (location = 0) in vec2 inUV;
layout (location = 1) in vec3 inN;
layout (location = 2) in vec3 inV;//ViewDir

layout (location = 0) out vec4 outFragColor;

layout(push_constant) uniform PushConsts {
    layout(offset = 64)
    vec4 baseColorFactor;
    vec4 emissiveFactor;
    uint availableAttachments;
    uint alphaMode;
    float alphaCutoff;
    float metallicFactor;
    float roughnessFactor;
} pc;

const uint MAP_COLOR = 0x1;
const uint MAP_NORMAL = 0x2;
const uint MAP_AMBIENTOCCLUSION = 0x4;
const uint MAP_METAL = 0x8;
const uint MAP_ROUGHNESS = 0x16;
const uint MAP_METALROUGHNESS = 0x32;
const uint MAP_EMISSIVE = 0x64;
const float M_PI = 3.141592653589793;

vec3 light = vec3(1.0,.0,1.0);

// http://www.thetenthplanet.de/archives/1180
mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv)
{
    // get edge vectors of the pixel triangle
    vec3 dp1 = dFdx( p );
    vec3 dp2 = dFdy( p );
    vec2 duv1 = dFdx( uv );
    vec2 duv2 = dFdy( uv );
 
    // solve the linear system
    vec3 dp2perp = cross( dp2, N );
    vec3 dp1perp = cross( N, dp1 );
    vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
    vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
 
    // construct a scale-invariant frame 
    float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
    return mat3( T * invmax, B * invmax, N );
}

vec3 perturb_normal( vec3 N, vec3 V, vec2 texcoord )
{
    // assume N, the interpolated vertex normal and 
    // V, the view vector (vertex to eye)
    vec3 map = texture(samplerNormal, texcoord).xyz;
    map = map * 255./127. - 128./127.;
    mat3 TBN = cotangent_frame(N, -V, texcoord);
    return normalize(TBN * map);
}
        

void main() 
{
    vec4 base_color = pc.baseColorFactor;
    if ((pc.availableAttachments & MAP_COLOR) == MAP_COLOR)
        base_color *= texture(samplerColor, inUV);    
    float rough = pc.roughnessFactor;
    float metallic = pc.metallicFactor;
    if ((pc.availableAttachments & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) {
        rough *= texture(samplerMetalRoughness, inUV).g;
        metallic *= texture(samplerMetalRoughness, inUV).b;
    }
    
    vec3 emit;
    if ((pc.availableAttachments & MAP_EMISSIVE) == MAP_EMISSIVE)   
        emit = pc.emissiveFactor.rgb * texture(samplerEmissive, inUV).rgb;
    
    vec3 n = normalize(inN);
    vec3 l = normalize(light);
    vec3 pn = perturb_normal(n, inV, inUV);    
    
    float lambert = max(0.0, dot(pn, l));
    
    vec3 f0 = vec3(0.04);
    vec3 diff = base_color.rgb * (vec3(1.0) - f0);
    diff *= 1.0 - metallic;
    diff *= lambert * texture(samplerOcclusion, inUV).r;
    diff += emit;
    
    vec3 spec = mix(f0, base_color.rgb, metallic);
    
    vec3 amb = vec3(0.1);
    if (lambert >= 0.0) {
       vec3 rd = reflect(-l, pn);
       float s = dot(rd, normalize(inV));
       spec = vec3(0.9,0.9,0.9)* //light.specular.xyz * material.specular.xyz *
             pow(max(0.0, s), 10.0); //0.5 = mat shininess
    }

    outFragColor = vec4(diff + amb + spec , base_color.a);  // 
}