Renderer/shaders/pbr.glsl

206 lines
4.5 KiB
GLSL

precision mediump float;
#define f32 float
#define f64 double
#define u32 uint
#define i32 int
#define b32 bool
#ifdef VERTEX_SHADER
# define varying_param out
layout(location = 0) in vec4 a_color;
layout(location = 1) in vec4 a_tangent;
layout(location = 2) in vec3 a_pos;
layout(location = 3) in vec3 a_normal;
layout(location = 4) in vec2 a_uv0;
layout(location = 5) in vec2 a_uv1;
#else
# define varying_param in
layout(location = 0) out vec4 FragColor;
#define AlbedoTexture u_texture0
#define NormalTexture u_texture1
#define MetallicTexture u_texture2
#define RoughnessTexture u_texture3
#define OcclusionTexture u_texture4
#define EmissionTexture u_texture5
#define HeightTexture u_texture6
#define CubemapTexture u_texture7
#define IrradianceTexture u_texture8
#define PrefilterTexture u_texture9
#define BRDFTexture u_texture10
uniform sampler2D u_texture0;
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
uniform sampler2D u_texture3;
uniform sampler2D u_texture4;
uniform sampler2D u_texture5;
uniform sampler2D u_texture6;
uniform sampler2D u_texture7;
uniform sampler2D u_texture8;
uniform sampler2D u_texture9;
uniform sampler2D u_texture10;
#endif
#define MMI_Albedo 0
#define MMI_Normal 1
#define MMI_Metallic 2
#define MMI_Roughness 3
#define MMI_Occlusion 4
#define MMI_Emission 5
#define MMI_Height 6
#define MMI_Cubemap 7
#define MMI_Irradiance 8
#define MMI_Prefilter 9
#define MMI_BRDF 10
#define MMI_MAX 11
#define AlbedoMaterial material_maps[MMI_Albedo]
#define NormalMaterial material_maps[MMI_Normal]
#define MetallicMaterial material_maps[MMI_Metallic]
#define RoughnessMaterial material_maps[MMI_Roughness]
#define OcclusionMaterial material_maps[MMI_Occlusion]
#define EmissionMaterial material_maps[MMI_Emission]
#define HeightMaterial material_maps[MMI_Height]
#define CubemapMaterial material_maps[MMI_Cubemap]
#define IrradianceMaterial material_maps[MMI_Irradiance]
#define PrefilterMaterial material_maps[MMI_Prefilter]
#define BRDFMaterial material_maps[MMI_BRDF]
#define VertexMain main
#define FragmentMain main
struct MaterialMap
{
vec4 color;
f32 value;
};
layout(location = 0) varying_param vec2 v_uv0;
layout(location = 1) varying_param vec2 v_uv1;
layout(location = 2) varying_param vec3 v_normal;
layout(location = 3) varying_param vec3 v_position;
layout(location = 4) varying_param vec4 v_color;
layout(std140, binding = 0) uniform Globals
{
mat4 projection;
mat4 view;
vec3 camera_position;
vec3 ambient;
};
layout(std140, binding = 1) uniform ModelState
{
bool albedo_texture;
bool normal_texture;
bool metallic_roughness_texture;
bool occlusion_texture;
bool emission_texture;
bool height_texture;
bool cubemap_texture;
bool irradiance_texture;
bool prefilter_texture;
bool brdf_texture;
bool no_material;
};
layout(std140, binding = 2) uniform InstanceState
{
mat4 model_matrix;
};
layout(std140, binding = 3) uniform Materials
{
MaterialMap material_maps[MMI_MAX];
};
f32
InverseLerp(f32 v, f32 min_value, f32 max_value)
{
return (v-min_value) / (max_value-min_value);
}
f32
Remap(f32 v, f32 in_min, f32 in_max, f32 out_min, f32 out_max)
{
f32 t = InverseLerp(v, in_min, in_max);
return mix(out_min, out_max, t);
}
#ifdef VERTEX_SHADER
void
VertexMain()
{
gl_Position = projection * view * model_matrix * vec4(a_pos, 1.0);
v_uv0 = a_uv0;
v_normal = (model_matrix * vec4(a_normal, 0.0f)).xyz;
v_position = (model_matrix * vec4(a_pos, 1.0f)).xyz;
v_color = a_color;
}
#else
void
FragmentMain()
{
vec3 normal = normalize(v_normal);
vec3 view_direction = normalize(camera_position - v_position);
vec4 color;
if(albedo_texture)
{
color = texture(AlbedoTexture, v_uv0);
}
else if(no_material)
{
color = v_color;
}
else
{
color = AlbedoMaterial.color;
}
if(color.a < 0.03f)
{
discard;
}
vec3 light_pos = vec3(0.0f, 100000.0f, 0.0f);
vec3 light_dir = normalize(light_pos-v_position);
vec3 light_color = vec3(1.0, 1.0, 0.9);
// Hemi lighting
vec3 sky_color = vec3(0.0, 0.3, 0.6);
vec3 ground_color = vec3(0.6, 0.3, 0.1);
f32 hemi_mix = Remap(normal.y, -1.0, 1.0, 0.0, 1.0);
vec3 hemi = mix(ground_color, sky_color, hemi_mix);
// Diffuse
f32 dp = max(0.0, dot(light_dir, normal));
vec3 diffuse = dp * light_color;
// Phong
vec3 r = normalize(reflect(-light_dir, normal));
f32 phong_value = max(0.0, dot(view_direction, r));
phong_value = pow(phong_value, 32.0);
vec3 specular = vec3(phong_value);
vec3 lighting = ambient + hemi + diffuse + specular;
lighting = pow(lighting, vec3(1.0/2.2));
FragColor = color * vec4(lighting, 1.0);
}
#endif