summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2016-11-20 22:49:53 -0300
committerJuan Linietsky <reduzio@gmail.com>2016-11-20 22:49:53 -0300
commita2505542ffeea705208f72459152c5b86779e327 (patch)
tree22d8ef0237410683d102b2b002bd5f2f33dcb1e3 /drivers
parentc39d2b3f429639803f4f4fe80eda6935659e9c51 (diff)
Huge amount of improvement in the material system. Materials should be
a lot more complete and usable now.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp4
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp7
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp20
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h1
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp51
-rw-r--r--drivers/gles3/shaders/scene.glsl195
6 files changed, 219 insertions, 59 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 4573f94d22..10a8912561 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -934,9 +934,13 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
if (!t) {
switch(texture_hints[i]) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex);
} break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
+ glBindTexture(GL_TEXTURE_2D,storage->resources.aniso_tex);
+ } break;
case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex);
} break;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index e04908ea67..3ead218226 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1035,9 +1035,13 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
if (!t) {
//check hints
switch(texture_hints[i]) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex);
} break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
+ glBindTexture(GL_TEXTURE_2D,storage->resources.aniso_tex);
+ } break;
case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex);
} break;
@@ -1046,7 +1050,6 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
} break;
}
- glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex);
continue;
}
@@ -1054,7 +1057,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
//if SRGB decode extension is present, simply switch the texture to whathever is needed
bool must_srgb=false;
- if (t->srgb && texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO) {
+ if (t->srgb && (texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) {
must_srgb=true;
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 8188fe3adb..669ab96036 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -2285,6 +2285,7 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
if (V) {
//user provided
_fill_std140_variant_ubo_value(E->get().type,V->get(),data,material->shader->mode==VS::SHADER_SPATIAL);
+
} else if (E->get().default_value.size()){
//default value
_fill_std140_ubo_value(E->get().type,E->get().default_value,data);
@@ -3304,7 +3305,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
light->type=p_type;
light->param[VS::LIGHT_PARAM_ENERGY]=1.0;
- light->param[VS::LIGHT_PARAM_SPECULAR]=1.0;
+ light->param[VS::LIGHT_PARAM_SPECULAR]=0.5;
light->param[VS::LIGHT_PARAM_RANGE]=1.0;
light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45;
light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0;
@@ -4491,7 +4492,7 @@ void RasterizerStorageGLES3::initialize() {
glGenTextures(1, &resources.black_tex);
unsigned char blacktexdata[8*8*3];
- for(int i=0;i<8*8;i++) {
+ for(int i=0;i<8*8*3;i++) {
blacktexdata[i]=0;
}
@@ -4515,6 +4516,21 @@ void RasterizerStorageGLES3::initialize() {
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
+
+ glGenTextures(1, &resources.aniso_tex);
+ unsigned char anisotexdata[8*8*3];
+ for(int i=0;i<8*8*3;i+=3) {
+ anisotexdata[i+0]=255;
+ anisotexdata[i+1]=128;
+ anisotexdata[i+2]=0;
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D,resources.aniso_tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,anisotexdata);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D,0);
+
}
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&config.max_texture_image_units);
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 5f07efeb0a..b433bcd517 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -74,6 +74,7 @@ public:
GLuint white_tex;
GLuint black_tex;
GLuint normal_tex;
+ GLuint aniso_tex;
GLuint quadie;
GLuint quadie_array;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index dce52ecd93..c54fc011e9 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -52,6 +52,7 @@ static int _get_datatype_size(SL::DataType p_type) {
}
+
static String _prestr(SL::DataPrecision p_pres) {
@@ -248,7 +249,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
r_gen_code.texture_hints.resize(max_texture_uniforms);
Vector<int> uniform_sizes;
+ Vector<int> uniform_alignments;
+ Vector<StringName> uniform_defines;
uniform_sizes.resize(max_uniforms);
+ uniform_alignments.resize(max_uniforms);
+ uniform_defines.resize(max_uniforms);
for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
@@ -272,19 +277,31 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii());
}
- r_gen_code.uniforms+=ucode;
+ uniform_defines[E->get().order]=ucode;
uniform_sizes[E->get().order]=_get_datatype_size(E->get().type);
+ uniform_alignments[E->get().order]=MIN(16,_get_datatype_size(E->get().type));
}
p_actions.uniforms->insert(E->key(),E->get());
}
+ for(int i=0;i<max_uniforms;i++) {
+ r_gen_code.uniforms+=uniform_defines[i];
+ }
// add up
for(int i=0;i<uniform_sizes.size();i++) {
- if (i>0)
+ if (i>0) {
+
+ int align = uniform_sizes[i-1] % uniform_alignments[i];
+ if (align!=0) {
+ uniform_sizes[i-1]+=uniform_alignments[i]-align;
+ }
+
uniform_sizes[i]=uniform_sizes[i]+uniform_sizes[i-1];
+
+ }
}
//offset
r_gen_code.uniform_offsets.resize(uniform_sizes.size());
@@ -294,8 +311,21 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
r_gen_code.uniform_offsets[i]=uniform_sizes[i-1];
else
r_gen_code.uniform_offsets[i]=0;
+
+
}
+/*
+ for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
+
+ if (SL::is_sampler_type(E->get().type)) {
+ continue;
+ }
+
+ print_line("u - "+String(E->key())+" offset: "+itos(r_gen_code.uniform_offsets[E->get().order]));
+ }
+
+*/
if (uniform_sizes.size()) {
r_gen_code.uniform_total_size=uniform_sizes[ uniform_sizes.size() -1 ];
} else {
@@ -549,13 +579,11 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code,
r_gen_code.uses_vertex_time=false;
-
used_name_defines.clear();
used_rmode_defines.clear();
_dump_node_code(parser.get_shader(),1,r_gen_code,*p_actions,actions[p_mode]);
-
return OK;
}
@@ -636,8 +664,14 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["ALPHA"]="alpha";
actions[VS::SHADER_SPATIAL].renames["SPECULAR"]="specular";
actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"]="roughness";
+ actions[VS::SHADER_SPATIAL].renames["RIM"]="rim";
+ actions[VS::SHADER_SPATIAL].renames["RIM_TINT"]="rim_tint";
+ actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"]="clearcoat";
+ actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"]="clearcoat_gloss";
+ actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"]="anisotropy";
+ actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"]="anisotropy_flow";
+ actions[VS::SHADER_SPATIAL].renames["AO"]="ao";
actions[VS::SHADER_SPATIAL].renames["EMISSION"]="emission";
- actions[VS::SHADER_SPATIAL].renames["SPECIAL"]="special";
actions[VS::SHADER_SPATIAL].renames["DISCARD"]="_discard";
// actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
actions[VS::SHADER_SPATIAL].renames["POINT_COORD"]="gl_PointCoord";
@@ -645,6 +679,13 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"]="#define ENABLE_TANGENT_INTERP\n";
actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"]="@TANGENT";
+ actions[VS::SHADER_SPATIAL].usage_defines["RIM"]="#define LIGHT_USE_RIM\n";
+ actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"]="@RIM";
+ actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"]="#define LIGHT_USE_CLEARCOAT\n";
+ actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"]="@CLEARCOAT";
+ actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"]="#define LIGHT_USE_ANISOTROPY\n";
+ actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"]="@ANISOTROPY";
+ actions[VS::SHADER_SPATIAL].usage_defines["AO"]="#define ENABLE_AO\n";
actions[VS::SHADER_SPATIAL].usage_defines["UV"]="#define ENABLE_UV_INTERP\n";
actions[VS::SHADER_SPATIAL].usage_defines["UV2"]="#define ENABLE_UV2_INTERP\n";
actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"]="#define ENABLE_NORMALMAP\n";
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index a923c130dc..aa8b3cacdc 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -108,7 +108,7 @@ out vec2 uv2_interp;
#endif
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
out vec3 tangent_interp;
out vec3 binormal_interp;
#endif
@@ -146,7 +146,7 @@ void main() {
highp mat4 modelview = camera_inverse_matrix * world_transform;
vec3 normal = normal_attrib * normal_mult;
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
vec3 tangent = tangent_attrib.xyz;
tangent*=normal_mult;
float binormalf = tangent_attrib.a;
@@ -163,7 +163,7 @@ void main() {
vertex = vertex_in * m;
normal = (vec4(normal,0.0) * m).xyz;
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
tangent = (vec4(tangent,0.0) * m).xyz;
#endif
}
@@ -176,7 +176,7 @@ void main() {
normal = normalize((modelview * vec4(normal,0.0)).xyz);
#endif
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
# if !defined(SKIP_TRANSFORM_USED)
tangent=normalize((modelview * vec4(tangent,0.0)).xyz);
@@ -207,7 +207,7 @@ VERTEX_SHADER_CODE
vertex_interp = vertex.xyz;
normal_interp = normal;
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
tangent_interp = tangent;
binormal_interp = binormal;
#endif
@@ -276,7 +276,7 @@ in vec2 uv_interp;
in vec2 uv2_interp;
#endif
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
in vec3 tangent_interp;
in vec3 binormal_interp;
#endif
@@ -455,40 +455,86 @@ float G1V(float dotNV, float k)
return 1.0 / (dotNV * (1.0 - k) + k);
}
-float specularGGX(vec3 N, vec3 V, vec3 L, float roughness, float F0)
+
+float SchlickFresnel(float u)
{
- float alpha = roughness * roughness;
+ float m = 1.0-u;
+ float m2 = m*m;
+ return m2*m2*m; // pow(m,5)
+}
+
+float GTR1(float NdotH, float a)
+{
+ if (a >= 1.0) return 1.0/M_PI;
+ float a2 = a*a;
+ float t = 1.0 + (a2-1.0)*NdotH*NdotH;
+ return (a2-1.0) / (M_PI*log(a2)*t);
+}
- vec3 H = normalize(V + L);
+void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) {
- float dotNL = max(dot(N,L), 0.0 );
- float dotNV = max(dot(N,V), 0.0 );
- float dotNH = max(dot(N,H), 0.0 );
- float dotLH = max(dot(L,H), 0.0 );
+ float dotNL = max(dot(N,L), 0.0 );
+ float dotNV = max(dot(N,V), 0.0 );
- // D
- float alphaSqr = alpha * alpha;
- float pi = M_PI;
- float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
- float D = alphaSqr / (pi * denom * denom);
+#if defined(LIGHT_USE_RIM)
+ float rim_light = pow(1.0-dotNV,(1.0-roughness)*16.0);
+ diffuse += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color;
+#endif
- // F
- float dotLH5 = pow(1.0 - dotLH, 5.0);
- float F = F0 + (1.0 - F0) * (dotLH5);
+ diffuse += dotNL * light_color * diffuse_color;
- // V
- float k = alpha / 2.0f;
- float vis = G1V(dotNL, k) * G1V(dotNV, k);
+ if (roughness > 0.0) {
- return dotNL * D * F * vis;
-}
+ float alpha = roughness * roughness;
+
+ vec3 H = normalize(V + L);
+
+ float dotNH = max(dot(N,H), 0.0 );
+ float dotLH = max(dot(L,H), 0.0 );
+
+ // D
+#if defined(LIGHT_USE_ANISOTROPY)
+
+ float aspect = sqrt(1.0-anisotropy*0.9);
+ float rx = roughness/aspect;
+ float ry = roughness*aspect;
+ float ax = rx*rx;
+ float ay = ry*ry;
+ float dotXH = dot( T, H );
+ float dotYH = dot( B, H );
+ float pi = M_PI;
+ float denom = dotXH*dotXH / (ax*ax) + dotYH*dotYH / (ay*ay) + dotNH*dotNH;
+ float D = 1.0 / ( pi * ax*ay * denom*denom );
+
+#else
+ float alphaSqr = alpha * alpha;
+ float pi = M_PI;
+ float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
+ float D = alphaSqr / (pi * denom * denom);
+#endif
+ // F
+ float F0 = 1.0;
+ float dotLH5 = SchlickFresnel( dotLH );
+ float F = F0 + (1.0 - F0) * (dotLH5);
+
+ // V
+ float k = alpha / 2.0f;
+ float vis = G1V(dotNL, k) * G1V(dotNV, k);
+
+ float speci = dotNL * D * F * vis;
+
+ specular += speci * light_color * specular_color * specular_blob_intensity;
+
+#if defined(LIGHT_USE_CLEARCOAT)
+ float Dr = GTR1(dotNH, mix(.1,.001,clearcoat_gloss));
+ float Fr = mix(.04, 1.0, dotLH5);
+ float Gr = G1V(dotNL, .25) * G1V(dotNV, .25);
+
+ specular += .25*clearcoat*Gr*Fr*Dr;
+#endif
+ }
-void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float roughness, inout vec3 diffuse, inout vec3 specular) {
- diffuse += max(0.0,dot(normal,light_vec)) * light_color * diffuse_color;
- //specular += specular_ggx( roughness, max(0.0,dot(normal,eye_vec)) ) * specular_color * attenuation;
- float s = roughness > 0.0 ? specularGGX(normal,eye_vec,light_vec,roughness,1.0) : 0.0;
- specular += s * light_color * specular_color;
}
@@ -536,7 +582,7 @@ in highp float dp_clip;
#endif
-void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 specular, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex;
float normalized_distance = length( light_rel_vec )*omni_lights[idx].light_pos_inv_radius.w;
@@ -577,11 +623,11 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albe
light_attenuation*=mix(omni_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect));
}
- light_compute(normal,normalize(light_rel_vec),eye_vec,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light);
+ light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,omni_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
-void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, vec3 specular, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex;
float normalized_distance = length( light_rel_vec )*spot_lights[idx].light_pos_inv_radius.w;
@@ -589,8 +635,8 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 al
vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz;
float spot_cutoff=spot_lights[idx].light_params.y;
float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff);
- float rim = (1.0 - scos) / (1.0 - spot_cutoff);
- light_attenuation *= 1.0 - pow( rim, spot_lights[idx].light_params.x);
+ float spot_rim = (1.0 - scos) / (1.0 - spot_cutoff);
+ light_attenuation *= 1.0 - pow( spot_rim, spot_lights[idx].light_params.x);
if (spot_lights[idx].light_params.w>0.5) {
//there is a shadowmap
@@ -599,11 +645,11 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 al
light_attenuation*=mix(spot_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp));
}
- light_compute(normal,normalize(light_rel_vec),eye_vec,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light);
+ light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,spot_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
-void reflection_process(int idx, vec3 vertex, vec3 normal,float roughness,vec3 ambient,vec3 skybox,vec2 brdf, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) {
+void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 tangent,float roughness,float anisotropy,vec3 ambient,vec3 skybox,vec2 brdf, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) {
vec3 ref_vec = normalize(reflect(vertex,normal));
vec3 local_pos = (reflections[idx].local_matrix * vec4(vertex,1.0)).xyz;
@@ -729,7 +775,19 @@ void main() {
highp vec3 vertex = vertex_interp;
vec3 albedo = vec3(0.8,0.8,0.8);
vec3 specular = vec3(0.2,0.2,0.2);
+ vec3 emission = vec3(0.0,0.0,0.0);
float roughness = 1.0;
+ float rim = 0.0;
+ float rim_tint = 0.0;
+ float clearcoat=0.0;
+ float clearcoat_gloss=0.0;
+ float anisotropy = 1.0;
+ vec2 anisotropy_flow = vec2(1.0,0.0);
+
+#if defined(ENABLE_AO)
+ float ao=1.0;
+#endif
+
float alpha = 1.0;
#ifdef METERIAL_DOUBLESIDED
@@ -739,9 +797,12 @@ void main() {
#endif
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
vec3 binormal = normalize(binormal_interp)*side;
vec3 tangent = normalize(tangent_interp)*side;
+#else
+ vec3 binormal = vec3(0.0);
+ vec3 tangent = vec3(0.0);
#endif
vec3 normal = normalize(normal_interp)*side;
@@ -777,9 +838,26 @@ FRAGMENT_SHADER_CODE
}
+
+
#if defined(ENABLE_NORMALMAP)
- normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side;
+ normalmap.xy=normalmap.xy*2.0-1.0;
+ normalmap.z=sqrt(1.0-dot(normalmap.xy,normalmap.xy)); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
+
+ normal = normalize( mix(normal_interp,tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z,normaldepth) ) * side;
+
+#endif
+
+#if defined(LIGHT_USE_ANISOTROPY)
+
+ if (anisotropy>0.01) {
+ //rotation matrix
+ mat3 rot = mat3( tangent, binormal, normal );
+ //make local to space
+ tangent = normalize(rot * vec3(anisotropy_flow.x,anisotropy_flow.y,0.0));
+ binormal = normalize(rot * vec3(-anisotropy_flow.y,anisotropy_flow.x,0.0));
+ }
#endif
@@ -799,6 +877,10 @@ FRAGMENT_SHADER_CODE
/////////////////////// LIGHTING //////////////////////////////
+ //apply energy conservation
+ vec3 diffuse=mix(albedo,vec3(0.0),specular);
+ specular = max(vec3(0.04),specular);
+
vec3 specular_light = vec3(0.0,0.0,0.0);
vec3 ambient_light;
vec3 diffuse_light = vec3(0.0,0.0,0.0);
@@ -839,8 +921,7 @@ FRAGMENT_SHADER_CODE
norm.xy/=norm.z;
norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25+y_ofs);
- vec3 radiance = textureLod(radiance_map, norm.xy, lod).xyz * ( brdf.x + brdf.y);
- specular_light=mix(albedo,radiance,specular);
+ specular_light = textureLod(radiance_map, norm.xy, lod).xyz * ( brdf.x + brdf.y);
}
//no longer a cubemap
@@ -996,7 +1077,7 @@ FRAGMENT_SHADER_CODE
#endif //LIGHT_DIRECTIONAL_SHADOW
- light_compute(normal,-light_direction_attenuation.xyz,eye_vec,light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light);
+ light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb*light_attenuation,diffuse,specular,light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
#endif //#USE_LIGHT_DIRECTIONAL
@@ -1008,23 +1089,22 @@ FRAGMENT_SHADER_CODE
highp vec4 ambient_accum = vec4(0.0,0.0,0.0,0.0);
for(int i=0;i<reflection_count;i++) {
- reflection_process(reflection_indices[i],vertex,normal,roughness,ambient_light,specular_light,brdf,reflection_accum,ambient_accum);
+ reflection_process(reflection_indices[i],vertex,normal,binormal,tangent,roughness,anisotropy,ambient_light,specular_light,brdf,reflection_accum,ambient_accum);
}
if (reflection_accum.a>0.0) {
specular_light=reflection_accum.rgb/reflection_accum.a;
- specular_light*=specular;
}
if (ambient_accum.a>0.0) {
ambient_light=ambient_accum.rgb/ambient_accum.a;
}
for(int i=0;i<omni_light_count;i++) {
- light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,albedo,specular,roughness,diffuse_light,specular_light);
+ light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,binormal,tangent,diffuse,specular,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
for(int i=0;i<spot_light_count;i++) {
- light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,albedo,specular,roughness,diffuse_light,specular_light);
+ light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,binormal,tangent,diffuse,specular,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
@@ -1048,16 +1128,28 @@ LIGHT_SHADER_CODE
#else
specular_light*=reflection_multiplier;
+ specular_light*=specular;
+ ambient_light*=albedo; //ambient must be multiplied by albedo at the end
+
+#if defined(ENABLE_AO)
+ ambient_light*=ao;
+#endif
#ifdef USE_MULTIPLE_RENDER_TARGETS
+#if defined(ENABLE_AO)
+
+ float ambient_scale=0.0; // AO is supplied by material
+#else
//approximate ambient scale for SSAO, since we will lack full ambient
+ float max_emission=max(emission.r,max(emission.g,emission.b));
float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b));
float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b));
- float total_ambient = max_ambient+max_diffuse;
+ float total_ambient = max_ambient+max_diffuse+max_emission;
float ambient_scale = (total_ambient>0.0) ? max_ambient/total_ambient : 0.0;
+#endif //ENABLE_AO
- diffuse_buffer=vec4(diffuse_light+ambient_light,ambient_scale);
+ diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale);
specular_buffer=vec4(specular_light,0.0);
normal_mr_buffer=vec4(normal.x,normal.y,max(specular.r,max(specular.g,specular.b)),roughness);
@@ -1067,11 +1159,14 @@ LIGHT_SHADER_CODE
#ifdef SHADELESS
frag_color=vec4(albedo,alpha);
#else
- frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha);
+ frag_color=vec4(emission+ambient_light+diffuse_light+specular_light,alpha);
#endif //SHADELESS
+
#endif //USE_MULTIPLE_RENDER_TARGETS
+
+
#endif //RENDER_SHADOW