mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-27 01:20:28 +03:00
It has the same effect as the (sprite) material attribute. Also, now sprite objects are rendered in the DRAW_OPAQUE phase.
163 lines
4.4 KiB
GLSL
163 lines
4.4 KiB
GLSL
/* Copyright (C) 2022 kichikuou <KichikuouChrome@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://gnu.org/licenses/>.
|
|
*/
|
|
|
|
#define NR_DIR_LIGHTS 3
|
|
|
|
#define DIFFUSE_EMISSIVE 0
|
|
#define DIFFUSE_NORMAL 1
|
|
#define DIFFUSE_LIGHT_MAP 2
|
|
#define DIFFUSE_ENV_MAP 3
|
|
|
|
#define FOG_LINEAR 1
|
|
#define FOG_LIGHT_SCATTERING 2
|
|
|
|
#define ALPHA_BLEND 0
|
|
#define ALPHA_TEST 1
|
|
#define ALPHA_MAP_BLEND 2
|
|
|
|
struct dir_light {
|
|
vec3 dir;
|
|
vec3 diffuse;
|
|
vec3 globe_diffuse;
|
|
};
|
|
|
|
uniform sampler2D tex;
|
|
uniform sampler2D specular_texture;
|
|
uniform sampler2D alpha_texture;
|
|
uniform sampler2D light_texture;
|
|
uniform sampler2D shadow_texture;
|
|
uniform float alpha_mod;
|
|
|
|
uniform bool use_normal_map;
|
|
uniform sampler2D normal_texture;
|
|
|
|
uniform vec3 ambient;
|
|
uniform dir_light dir_lights[NR_DIR_LIGHTS];
|
|
uniform float specular_strength;
|
|
uniform float specular_shininess;
|
|
uniform bool use_specular_map;
|
|
uniform float rim_exponent;
|
|
uniform vec3 rim_color;
|
|
uniform int diffuse_type;
|
|
uniform float shadow_darkness;
|
|
uniform float shadow_bias;
|
|
uniform int fog_type;
|
|
uniform float fog_near;
|
|
uniform float fog_far;
|
|
uniform vec3 fog_color;
|
|
uniform int alpha_mode;
|
|
|
|
in vec2 tex_coord;
|
|
in vec2 light_tex_coord;
|
|
in vec3 frag_pos;
|
|
in vec4 shadow_frag_pos;
|
|
in float dist;
|
|
in vec3 eye;
|
|
in vec3 normal;
|
|
in vec3 light_dir[NR_DIR_LIGHTS];
|
|
in vec3 specular_dir;
|
|
in vec3 ls_ex;
|
|
in vec3 ls_in;
|
|
out vec4 frag_color;
|
|
|
|
void main() {
|
|
vec3 norm;
|
|
if (use_normal_map) {
|
|
// NOTE: TT3's shader doesn't normalize this vector.
|
|
norm = texture(normal_texture, tex_coord).rgb * 2.0 - 1.0;
|
|
} else {
|
|
norm = normalize(normal);
|
|
}
|
|
|
|
vec3 view_dir = normalize(eye - frag_pos);
|
|
vec3 frag_rgb = ambient;
|
|
|
|
// Diffuse lighting
|
|
vec4 texel;
|
|
if (diffuse_type == DIFFUSE_ENV_MAP) {
|
|
texel = texture(tex, (vec2(normal.x, -normal.y) + 1.0) / 2.0);
|
|
frag_rgb = texel.rgb;
|
|
} else {
|
|
texel = texture(tex, tex_coord);
|
|
if (diffuse_type == DIFFUSE_EMISSIVE) {
|
|
frag_rgb = texel.rgb;
|
|
} else {
|
|
vec3 diffuse = vec3(0.0);
|
|
for (int i = 0; i < NR_DIR_LIGHTS; i++) {
|
|
float half_lambert = dot(norm, -light_dir[i]) * 0.5 + 0.5;
|
|
diffuse += mix(dir_lights[i].globe_diffuse, dir_lights[i].diffuse, half_lambert);
|
|
}
|
|
if (diffuse_type == DIFFUSE_LIGHT_MAP) {
|
|
diffuse *= texture(light_texture, light_tex_coord).rgb;
|
|
}
|
|
frag_rgb += texel.rgb * diffuse;
|
|
}
|
|
}
|
|
|
|
// Specular lighting
|
|
if (specular_strength > 0.0) {
|
|
vec3 reflect_dir = reflect(specular_dir, norm);
|
|
float specular = pow(max(dot(view_dir, reflect_dir), 0.0), specular_shininess) * specular_strength;
|
|
if (use_specular_map) {
|
|
specular *= texture(specular_texture, tex_coord).r;
|
|
}
|
|
frag_rgb += vec3(specular);
|
|
}
|
|
|
|
// Rim lighting
|
|
if (rim_exponent > 0.0) {
|
|
// Normal map is not used here.
|
|
vec3 n = use_normal_map ? vec3(0.0, 0.0, 1.0) : normalize(normal);
|
|
frag_rgb += pow(1.0 - max(dot(n, view_dir), 0.0), rim_exponent) * rim_color;
|
|
}
|
|
|
|
// Fog
|
|
if (fog_type == FOG_LINEAR) {
|
|
float fog_factor = clamp((dist - fog_near) / (fog_far - fog_near), 0.0, 1.0);
|
|
frag_rgb = mix(frag_rgb, fog_color, fog_factor);
|
|
} else if (fog_type == FOG_LIGHT_SCATTERING) {
|
|
frag_rgb = frag_rgb * ls_ex + ls_in;
|
|
}
|
|
|
|
// Shadow mapping
|
|
if (shadow_darkness > 0.0) {
|
|
vec3 shadow_coords = shadow_frag_pos.xyz / shadow_frag_pos.w * 0.5 + 0.5;
|
|
shadow_coords.z = min(1.0, shadow_coords.z - shadow_bias);
|
|
// PCF with 9 samples.
|
|
float brightness = 1.0;
|
|
vec2 texel_size = 1.0 / vec2(textureSize(shadow_texture, 0));
|
|
for (int x = -1; x <= 1; ++x) {
|
|
for (int y = -1; y <= 1; ++y) {
|
|
float depth = texture(shadow_texture, shadow_coords.xy + vec2(x, y) * texel_size).r;
|
|
if (depth < shadow_coords.z)
|
|
brightness -= 0.05 * shadow_darkness;
|
|
}
|
|
}
|
|
frag_rgb *= brightness;
|
|
}
|
|
|
|
// Alpha mapping
|
|
float alpha = texel.a * alpha_mod;
|
|
if (alpha_mode == ALPHA_TEST) {
|
|
if (alpha < 0.8)
|
|
discard;
|
|
} else if (alpha_mode == ALPHA_MAP_BLEND) {
|
|
alpha *= texture(alpha_texture, tex_coord).r;
|
|
}
|
|
|
|
frag_color = vec4(frag_rgb, alpha);
|
|
}
|