summaryrefslogtreecommitdiff
path: root/drivers/gles3
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3')
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp709
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h138
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp226
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h26
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp81
-rw-r--r--drivers/gles3/shader_gles3.cpp1
-rw-r--r--drivers/gles3/shader_gles3.h1
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl59
-rw-r--r--drivers/gles3/shaders/scene.glsl282
9 files changed, 1343 insertions, 180 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 4ce2bd2f37..aadf9e6336 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -75,7 +75,7 @@ void RasterizerSceneGLES3::environment_set_background(RID p_env,VS::EnvironmentB
env->bg_mode=p_bg;
}
-void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p_radiance_size, int p_irradiance_size){
+void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p_radiance_size){
Environment *env=environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
@@ -87,15 +87,12 @@ void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p
storage->free(env->skybox_radiance);
env->skybox_radiance=RID();
}
- if (env->skybox_irradiance.is_valid()) {
- storage->free(env->skybox_irradiance);
- env->skybox_irradiance=RID();
- }
+
if (p_skybox.is_valid()) {
env->skybox_color=p_skybox;
- // env->skybox_radiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_RADIANCE,p_radiance_size);
+ env->skybox_radiance=storage->texture_create_radiance_cubemap(p_skybox,p_radiance_size);
//env->skybox_irradiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_IRRADIANCE,p_irradiance_size);
}
@@ -123,7 +120,7 @@ void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env,float p_energy) {
Environment *env=environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
- env->energy=p_energy;
+ env->bg_energy=p_energy;
}
@@ -135,14 +132,14 @@ void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env,int p_max_
env->canvas_max_layer=p_max_layer;
}
-void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& p_color, float p_energy, float p_skybox_energy){
+void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& p_color, float p_energy, float p_skybox_contribution){
Environment *env=environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->ambient_color=p_color;
- env->ambient_anergy=p_energy;
- env->skybox_ambient=p_skybox_energy;
+ env->ambient_energy=p_energy;
+ env->ambient_skybox_contribution=p_skybox_contribution;
}
@@ -174,13 +171,28 @@ void RasterizerSceneGLES3::environment_set_color_correction(RID p_env,bool p_ena
RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
+ LightInstance *light_instance = memnew( LightInstance );
+
+ light_instance->light=p_light;
+ light_instance->light_ptr=storage->light_owner.getornull(p_light);
+
+ glGenBuffers(1, &light_instance->light_ubo);
+ glBindBuffer(GL_UNIFORM_BUFFER, light_instance->light_ubo);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInstance::LightDataUBO), NULL, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
- return RID();
+ ERR_FAIL_COND_V(!light_instance->light_ptr,RID());
+
+ return light_instance_owner.make_rid(light_instance);
}
void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,const Transform& p_transform){
+ LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+ light_instance->transform=p_transform;
}
@@ -247,11 +259,13 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
//material parameters
+
state.scene_shader.set_custom_shader(p_material->shader->custom_code_id);
bool rebind = state.scene_shader.bind();
if (p_material->ubo_id) {
+
glBindBufferBase(GL_UNIFORM_BUFFER,1,p_material->ubo_id);
}
@@ -267,6 +281,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull( textures[i] );
if (!t) {
//check hints
+
glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex);
continue;
}
@@ -328,7 +343,14 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
}
-void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,bool p_reverse_cull,bool p_alpha_pass) {
+void RasterizerSceneGLES3::_setup_light(LightInstance *p_light) {
+
+
+ glBindBufferBase(GL_UNIFORM_BUFFER,3,p_light->light_ubo); //bind light uniform
+}
+
+
+void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass) {
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) {
//p_reverse_cull=!p_reverse_cull;
@@ -337,8 +359,22 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
glFrontFace(GL_CW);
}
+ bool shadow=false;
+
glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo
+
+ glBindBufferBase(GL_UNIFORM_BUFFER,2,state.env_radiance_ubo); //bind environment radiance info
+ glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-1);
+ glBindTexture(GL_TEXTURE_2D,state.brdf_texture);
+
+ if (p_base_env) {
+ glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2);
+ glBindTexture(p_base_env->target,p_base_env->tex_id);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true);
+ }
+
+
state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false);
state.current_blend_mode=-1;
@@ -349,6 +385,11 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
RasterizerStorageGLES3::Geometry* prev_geometry=NULL;
VS::InstanceType prev_base_type = VS::INSTANCE_MAX;
+ int prev_light_type=-1;
+ int prev_light_index=-1;
+ int prev_blend=-1;
+ int current_blend_mode=-1;
+
for (int i=0;i<p_element_count;i++) {
RenderList::Element *e = p_elements[i];
@@ -356,6 +397,151 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
bool rebind=i==0;
+ int light_type=(e->sort_key>>RenderList::SORT_KEY_LIGHT_TYPE_SHIFT)&0xF;
+ int light_index=(e->sort_key>>RenderList::SORT_KEY_LIGHT_INDEX_SHIFT)&0xFFFF;
+
+ bool additive=false;
+
+ if (!shadow) {
+#if 0
+ if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) {
+ texscreen_copied=true;
+ _copy_to_texscreen();
+
+ //force reset state
+ prev_material=NULL;
+ prev_light=0x777E;
+ prev_geometry_cmp=NULL;
+ prev_light_type=0xEF;
+ prev_skeleton =NULL;
+ prev_sort_flags=0xFF;
+ prev_morph_values=NULL;
+ prev_receive_shadows_state=-1;
+ glEnable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+
+ }
+#endif
+ if (light_type!=prev_light_type /* || receive_shadows_state!=prev_receive_shadows_state*/) {
+
+ if (material->shader->spatial.unshaded/* || current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) {
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true);
+
+ //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true);
+ } else {
+ state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,light_type!=0xF);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,light_type==VS::LIGHT_DIRECTIONAL);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,light_type==VS::LIGHT_OMNI);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,light_type==VS::LIGHT_SPOT);
+ /*
+ if (receive_shadows_state==1) {
+ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,(light_type&0x8));
+ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,(light_type&0x10));
+ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,(light_type&0x20));
+ }
+ else {
+ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false);
+ }
+ state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false);
+ */
+ }
+
+ rebind=true;
+ }
+
+
+ if (!*e->additive_ptr) {
+
+ additive=false;
+ *e->additive_ptr=true;
+ } else {
+ additive=true;
+ }
+
+ bool desired_blend=false;
+ int desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX;
+
+ if (additive) {
+ desired_blend=true;
+ desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD;
+ } else {
+ desired_blend=p_alpha_pass;
+ desired_blend_mode=material->shader->spatial.blend_mode;
+ }
+
+ if (prev_blend!=desired_blend) {
+
+ if (desired_blend) {
+ glEnable(GL_BLEND);
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glColorMask(1,1,1,0);
+ }
+ } else {
+ glDisable(GL_BLEND);
+ glColorMask(1,1,1,1);
+ }
+
+ prev_blend=desired_blend;
+ }
+
+ if (desired_blend && desired_blend_mode!=current_blend_mode) {
+
+
+ switch(desired_blend_mode) {
+
+ case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ } break;
+ case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: {
+
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE);
+
+ } break;
+ case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: {
+
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ } break;
+ case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ } break;
+
+ }
+
+ current_blend_mode=desired_blend_mode;
+ }
+ }
+
+ if (light_index!=prev_light_index) {
+ if (light_index!=0xFFFF) { //not unshaded
+ _setup_light(light_instances[light_index]);
+ }
+ }
+
if (material!=prev_material || rebind) {
rebind = _setup_material(material,p_alpha_pass);
@@ -396,6 +582,7 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
RasterizerStorageGLES3::Material *m=NULL;
RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override :(p_material>=0?p_instance->materials[p_material]:p_geometry->material);
+
/*
#ifdef DEBUG_ENABLED
if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) {
@@ -404,8 +591,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
#endif
*/
+
if (m_src.is_valid()) {
m=storage->material_owner.getornull( m_src );
+
if (!m->shader) {
m=NULL;
}
@@ -419,9 +608,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
- //bool has_base_alpha=(m->shader_cache && m->shader_cache->has_alpha);
- //bool has_blend_alpha=m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || m->flags[VS::MATERIAL_FLAG_ONTOP];
- bool has_alpha = false; //has_base_alpha || has_blend_alpha;
+ bool has_base_alpha=(m->shader->spatial.uses_alpha);
+ bool has_blend_alpha=m->shader->spatial.blend_mode!=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX || m->shader->spatial.ontop;
+ bool has_alpha = has_base_alpha || has_blend_alpha;
+ bool shadow = false;
#if 0
if (shadow) {
@@ -488,12 +678,13 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
e->additive_ptr=&e->additive;
e->sort_key=0;
+
if (e->geometry->last_pass!=render_pass) {
e->geometry->last_pass=render_pass;
e->geometry->index=current_geometry_index++;
}
- e->sort_key|=uint64_t(e->instance->base_type)<<RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
+ e->sort_key|=uint64_t(e->geometry->index)<<RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
e->sort_key|=uint64_t(e->instance->base_type)<<RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
if (e->material->last_pass!=render_pass) {
@@ -502,7 +693,6 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
}
e->sort_key|=uint64_t(e->material->index)<<RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
-
e->sort_key|=uint64_t(e->instance->depth_layer)<<RenderList::SORT_KEY_DEPTH_LAYER_SHIFT;
//if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE)
@@ -510,42 +700,45 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
bool mirror = e->instance->mirror;
-// if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES])
-// e->mirror=!e->mirror;
+ if (m->shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) {
+ mirror=!mirror;
+ }
if (mirror) {
e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG;
}
//e->light_type=0xFF; // no lights!
- e->sort_key|=uint64_t(0xF)<<RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; //light type 0xF is no light?
- e->sort_key|=uint64_t(0xFFFF)<<RenderList::SORT_KEY_LIGHT_INDEX_SHIFT;
-/* prepass
- if (!shadow && !has_blend_alpha && has_alpha && m->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA) {
+
+ if (!shadow && !has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode==RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
//if nothing exists, add this element as opaque too
- RenderList::Element *oe = opaque_render_list.add_element();
+ RenderList::Element *oe = render_list.add_element();
if (!oe)
return;
- memcpy(oe,e,sizeof(RenderList::Element));
+ copymem(oe,e,sizeof(RenderList::Element));
oe->additive_ptr=&oe->additive;
}
-*/
-#if 0
- if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED] || current_debug==VS::SCENARIO_DEBUG_SHADELESS) {
- e->light_type=0x7F; //unshaded is zero
+
+
+ if (shadow || m->shader->spatial.unshaded /*|| current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) {
+
+ e->sort_key=RenderList::SORT_KEY_LIGHT_INDEX_UNSHADED;
+ e->sort_key|=uint64_t(0xF)<<RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; //light type 0xF is no light?
+ e->sort_key|=uint64_t(0xFFFF)<<RenderList::SORT_KEY_LIGHT_INDEX_SHIFT;
} else {
bool duplicate=false;
+ bool lighted=false;
- for(int i=0;i<directional_light_count;i++) {
- uint16_t sort_key = directional_lights[i]->sort_key;
- uint8_t light_type = VS::LIGHT_DIRECTIONAL;
+ for(int i=0;i<directional_light_instance_count;i++) {
+
+/*
if (directional_lights[i]->base->shadow_enabled) {
light_type|=0x8;
if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS)
@@ -554,22 +747,24 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
light_type|=0x30;
}
+*/
RenderList::Element *ec;
if (duplicate) {
-
- ec = render_list->add_element();
- memcpy(ec,e,sizeof(RenderList::Element));
+ ec = render_list.add_element();
+ copymem(ec,e,sizeof(RenderList::Element));
} else {
ec=e;
duplicate=true;
}
- ec->light_type=light_type;
- ec->light=sort_key;
ec->additive_ptr=&e->additive;
+ ec->sort_key|=uint64_t(directional_light_instances[i]->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT;
+ ec->sort_key|=uint64_t(VS::LIGHT_DIRECTIONAL) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT;
+
+ lighted=true;
}
@@ -580,37 +775,45 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
for(int i=0;i<ilc;i++) {
- LightInstance *li=light_instance_owner.get( liptr[i] );
- if (!li || li->last_pass!=scene_pass) //lit by light not in visible scene
+ LightInstance *li=light_instance_owner.getptr( liptr[i] );
+
+ if (!li || li->last_pass!=render_pass) //lit by light not in visible scene
continue;
- uint8_t light_type=li->base->type|0x40; //penalty to ensure directionals always go first
- if (li->base->shadow_enabled) {
- light_type|=0x8;
- }
- uint16_t sort_key =li->sort_key;
+
+
+// if (li->base->shadow_enabled) {
+// light_type|=0x8;
+// }
RenderList::Element *ec;
if (duplicate) {
- ec = render_list->add_element();
- memcpy(ec,e,sizeof(RenderList::Element));
+ ec = render_list.add_element();
+ copymem(ec,e,sizeof(RenderList::Element));
} else {
duplicate=true;
ec=e;
}
- ec->light_type=light_type;
- ec->light=sort_key;
ec->additive_ptr=&e->additive;
+ ec->sort_key|=uint64_t(li->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT;
+ ec->sort_key|=uint64_t(li->light_ptr->type) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT;
+
+ lighted=true;
}
+ if (!lighted) {
+ e->sort_key|=uint64_t(0xE)<<RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; //light type 0xE is no light found
+ e->sort_key|=uint64_t(0xFFFF)<<RenderList::SORT_KEY_LIGHT_INDEX_SHIFT;
+ }
+
}
-#endif
+
}
void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) {
@@ -625,19 +828,20 @@ void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
+ glDepthFunc(GL_LEQUAL);
glColorMask(1,1,1,1);
float flip_sign = p_vflip?-1:1;
Vector3 vertices[8]={
- Vector3(-1,-1*flip_sign,0.1),
+ Vector3(-1,-1*flip_sign,1),
Vector3( 0, 1, 0),
- Vector3( 1,-1*flip_sign,0.1),
+ Vector3( 1,-1*flip_sign,1),
Vector3( 1, 1, 0),
- Vector3( 1, 1*flip_sign,0.1),
+ Vector3( 1, 1*flip_sign,1),
Vector3( 1, 0, 0),
- Vector3(-1, 1*flip_sign,0.1),
- Vector3( 0, 0, 0),
+ Vector3(-1, 1*flip_sign,1),
+ Vector3( 0, 0, 0)
};
@@ -677,27 +881,248 @@ void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,
}
-void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment){
+void RasterizerSceneGLES3::_setup_environment(Environment *env,CameraMatrix& p_cam_projection,const Transform& p_cam_transform) {
- //fill up ubo
+ //store camera into ubo
store_camera(p_cam_projection,state.ubo_data.projection_matrix);
store_transform(p_cam_transform,state.ubo_data.camera_matrix);
store_transform(p_cam_transform.affine_inverse(),state.ubo_data.camera_inverse_matrix);
+
+ //time global variables
for(int i=0;i<4;i++) {
state.ubo_data.time[i]=storage->frame.time[i];
}
+ //bg and ambient
+ if (env) {
+ state.ubo_data.bg_energy=env->bg_energy;
+ state.ubo_data.ambient_energy=env->ambient_energy;
+ Color linear_ambient_color = env->ambient_color.to_linear();
+ state.ubo_data.ambient_light_color[0]=linear_ambient_color.r;
+ state.ubo_data.ambient_light_color[1]=linear_ambient_color.g;
+ state.ubo_data.ambient_light_color[2]=linear_ambient_color.b;
+ state.ubo_data.ambient_light_color[3]=linear_ambient_color.a;
+
+ Color bg_color;
+
+ switch(env->bg_mode) {
+ case VS::ENV_BG_CLEAR_COLOR: {
+ bg_color=storage->frame.clear_request_color.to_linear();
+ } break;
+ case VS::ENV_BG_COLOR: {
+ bg_color=env->bg_color.to_linear();
+ } break;
+ default: {
+ bg_color=Color(0,0,0,1);
+ } break;
+ }
+
+ state.ubo_data.bg_color[0]=bg_color.r;
+ state.ubo_data.bg_color[1]=bg_color.g;
+ state.ubo_data.bg_color[2]=bg_color.b;
+ state.ubo_data.bg_color[3]=bg_color.a;
+
+ state.env_radiance_data.ambient_contribution=env->ambient_skybox_contribution;
+ } else {
+ state.ubo_data.bg_energy=1.0;
+ state.ubo_data.ambient_energy=1.0;
+ //use from clear color instead, since there is no ambient
+ Color linear_ambient_color = storage->frame.clear_request_color.to_linear();
+ state.ubo_data.ambient_light_color[0]=linear_ambient_color.r;
+ state.ubo_data.ambient_light_color[1]=linear_ambient_color.g;
+ state.ubo_data.ambient_light_color[2]=linear_ambient_color.b;
+ state.ubo_data.ambient_light_color[3]=linear_ambient_color.a;
+
+ state.ubo_data.bg_color[0]=linear_ambient_color.r;
+ state.ubo_data.bg_color[1]=linear_ambient_color.g;
+ state.ubo_data.bg_color[2]=linear_ambient_color.b;
+ state.ubo_data.bg_color[3]=linear_ambient_color.a;
+
+ state.env_radiance_data.ambient_contribution=0;
+
+ }
glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(State::SceneDataUBO), &state.ubo_data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ //fill up environment
+
+ store_transform(p_cam_transform,state.env_radiance_data.transform);
+
+
+ glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+}
+
+void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cull_count,const Transform& p_camera_inverse_transform) {
+
+ directional_light_instance_count=0;
+ light_instance_count=0;
+
+ for(int i=0;i<p_light_cull_count;i++) {
+
+ ERR_BREAK( i>=RenderList::MAX_LIGHTS );
+
+ LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]);
+
+ switch(li->light_ptr->type) {
+
+ case VS::LIGHT_DIRECTIONAL: {
+
+ ERR_FAIL_COND( directional_light_instance_count >= RenderList::MAX_LIGHTS);
+ directional_light_instances[directional_light_instance_count++]=li;
+
+ li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r;
+ li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g;
+ li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b;
+ li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
+
+ //omni, keep at 0
+ li->light_ubo_data.light_pos_inv_radius[0]=0.0;
+ li->light_ubo_data.light_pos_inv_radius[1]=0.0;
+ li->light_ubo_data.light_pos_inv_radius[2]=0.0;
+ li->light_ubo_data.light_pos_inv_radius[3]=0.0;
+
+ Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized();
+ li->light_ubo_data.light_direction_attenuation[0]=direction.x;
+ li->light_ubo_data.light_direction_attenuation[1]=direction.y;
+ li->light_ubo_data.light_direction_attenuation[2]=direction.z;
+ li->light_ubo_data.light_direction_attenuation[3]=1.0;
+
+ li->light_ubo_data.light_params[0]=0;
+ li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
+ li->light_ubo_data.light_params[2]=0;
+ li->light_ubo_data.light_params[3]=0;
- render_list.clear();
+
+#if 0
+ if (li->light_ptr->shadow_enabled) {
+ CameraMatrix bias;
+ bias.set_light_bias();
+
+ int passes=light_instance_get_shadow_passes(p_light_instance);
+
+ for(int i=0;i<passes;i++) {
+ Transform modelview=Transform(camera_transform_inverse * li->custom_transform[i]).inverse();
+ li->shadow_projection[i] = bias * li->custom_projection[i] * modelview;
+ }
+ lights_use_shadow=true;
+ }
+#endif
+ } break;
+ case VS::LIGHT_OMNI: {
+
+ li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r;
+ li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g;
+ li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b;
+ li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
+
+ Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin);
+
+ //directional, keep at 0
+ li->light_ubo_data.light_pos_inv_radius[0]=pos.x;
+ li->light_ubo_data.light_pos_inv_radius[1]=pos.y;
+ li->light_ubo_data.light_pos_inv_radius[2]=pos.z;
+ li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]);
+
+ li->light_ubo_data.light_direction_attenuation[0]=0;
+ li->light_ubo_data.light_direction_attenuation[1]=0;
+ li->light_ubo_data.light_direction_attenuation[2]=0;
+ li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
+
+ li->light_ubo_data.light_params[0]=0;
+ li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
+ li->light_ubo_data.light_params[2]=0;
+ li->light_ubo_data.light_params[3]=0;
+
+#if 0
+ if (li->light_ptr->shadow_enabled) {
+ li->shadow_projection[0] = Transform(camera_transform_inverse * li->transform).inverse();
+ lights_use_shadow=true;
+ }
+#endif
+ } break;
+ case VS::LIGHT_SPOT: {
+
+ li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r;
+ li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g;
+ li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b;
+ li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
+
+ Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin);
+
+ //directional, keep at 0
+ li->light_ubo_data.light_pos_inv_radius[0]=pos.x;
+ li->light_ubo_data.light_pos_inv_radius[1]=pos.y;
+ li->light_ubo_data.light_pos_inv_radius[2]=pos.z;
+ li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]);
+
+ Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized();
+ li->light_ubo_data.light_direction_attenuation[0]=direction.x;
+ li->light_ubo_data.light_direction_attenuation[1]=direction.y;
+ li->light_ubo_data.light_direction_attenuation[2]=direction.z;
+ li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
+
+ li->light_ubo_data.light_params[0]=li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION];
+ li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
+ li->light_ubo_data.light_params[2]=0;
+ li->light_ubo_data.light_params[3]=0;
+
+#if 0
+ if (li->light_ptr->shadow_enabled) {
+ CameraMatrix bias;
+ bias.set_light_bias();
+ Transform modelview=Transform(camera_transform_inverse * li->transform).inverse();
+ li->shadow_projection[0] = bias * li->projection * modelview;
+ lights_use_shadow=true;
+ }
+#endif
+ } break;
+
+ }
+
+
+ /* make light hash */
+
+ // actually, not really a hash, but helps to sort the lights
+ // and avoid recompiling redudant shader versions
+
+
+ li->last_pass=render_pass;
+ li->light_index=i;
+
+ //update UBO for forward rendering, blit to texture for clustered
+
+ glBindBuffer(GL_UNIFORM_BUFFER, li->light_ubo);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightInstance::LightDataUBO), &li->light_ubo_data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ light_instances[i]=li;
+ }
+
+}
+
+void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment){
+
+ //first of all, make a new render pass
render_pass++;
+
+ //fill up ubo
+
+ Environment *env = environment_owner.getornull(p_environment);
+
+ _setup_environment(env,p_cam_projection,p_cam_transform);
+
+ _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse());
+
+ render_list.clear();
+
current_material_index=0;
//fill list
@@ -744,8 +1169,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
glClearDepth(1.0);
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
-
- Environment *env = environment_owner.getornull(p_environment);
+ RasterizerStorageGLES3::Texture* env_radiance_tex;
if (!env || env->bg_mode==VS::ENV_BG_CLEAR_COLOR) {
@@ -756,12 +1180,21 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
storage->frame.clear_request=false;
}
+
} else if (env->bg_mode==VS::ENV_BG_COLOR) {
glClearColor( env->bg_color.r, env->bg_color.g, env->bg_color.b, env->bg_color.a );
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
storage->frame.clear_request=false;
+ } else if (env->bg_mode==VS::ENV_BG_SKYBOX) {
+
+ if (env->skybox_radiance.is_valid()) {
+ env_radiance_tex = storage->texture_owner.getornull(env->skybox_radiance);
+ }
+ glClear(GL_DEPTH_BUFFER_BIT);
+ storage->frame.clear_request=false;
+
} else {
glClear(GL_DEPTH_BUFFER_BIT);
storage->frame.clear_request=false;
@@ -810,7 +1243,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
// }
- _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,false,false);
+ _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false);
if (env && env->bg_mode==VS::ENV_BG_SKYBOX) {
@@ -824,6 +1257,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
// state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+ glEnable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
+
+ render_list.sort_by_depth(true);
+
+ _render_list(&render_list.elements[render_list.max_elements-render_list.alpha_element_count],render_list.alpha_element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false);
+
+
#if 0
if (use_fb) {
@@ -972,7 +1416,143 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
bool RasterizerSceneGLES3::free(RID p_rid) {
- return false;
+ if (light_instance_owner.owns(p_rid)) {
+
+ LightInstance *light_instance = light_instance_owner.getptr(p_rid);
+ glDeleteBuffers(1,&light_instance->light_ubo);
+ light_instance_owner.free(p_rid);
+ memdelete(light_instance);
+
+
+ } else {
+ return false;
+ }
+
+
+ return true;
+
+}
+
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+static _FORCE_INLINE_ float radicalInverse_VdC(uint32_t bits) {
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10f; // / 0x100000000
+}
+
+static _FORCE_INLINE_ Vector2 Hammersley(uint32_t i, uint32_t N) {
+ return Vector2(float(i) / float(N), radicalInverse_VdC(i));
+}
+
+static _FORCE_INLINE_ Vector3 ImportanceSampleGGX(Vector2 Xi, float Roughness, Vector3 N) {
+ float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
+
+ // Compute distribution direction
+ float Phi = 2.0f * M_PI * Xi.x;
+ float CosTheta = Math::sqrt((1.0f - Xi.y) / (1.0f + (a*a - 1.0f) * Xi.y));
+ float SinTheta = Math::sqrt((float)Math::abs(1.0f - CosTheta * CosTheta));
+
+ // Convert to spherical direction
+ Vector3 H;
+ H.x = SinTheta * Math::cos(Phi);
+ H.y = SinTheta * Math::sin(Phi);
+ H.z = CosTheta;
+
+ Vector3 UpVector = Math::abs(N.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(1.0, 0.0, 0.0);
+ Vector3 TangentX = UpVector.cross(N);
+ TangentX.normalize();
+ Vector3 TangentY = N.cross(TangentX);
+
+ // Tangent to world space
+ return TangentX * H.x + TangentY * H.y + N * H.z;
+}
+
+static _FORCE_INLINE_ float GGX(float NdotV, float a) {
+ float k = a / 2.0;
+ return NdotV / (NdotV * (1.0 - k) + k);
+}
+
+// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+float _FORCE_INLINE_ G_Smith(float a, float nDotV, float nDotL)
+{
+ return GGX(nDotL, a * a) * GGX(nDotV, a * a);
+}
+
+void RasterizerSceneGLES3::_generate_brdf() {
+
+ int brdf_size=GLOBAL_DEF("rendering/gles3/brdf_texture_size",64);
+
+
+
+ DVector<uint8_t> brdf;
+ brdf.resize(brdf_size*brdf_size*2);
+
+ DVector<uint8_t>::Write w = brdf.write();
+
+
+ for(int i=0;i<brdf_size;i++) {
+ for(int j=0;j<brdf_size;j++) {
+
+ float Roughness = float(j)/(brdf_size-1);
+ float NoV = float(i+1)/(brdf_size); //avoid storing nov0
+
+ Vector3 V;
+ V.x = Math::sqrt( 1.0 - NoV * NoV );
+ V.y = 0.0;
+ V.z = NoV;
+
+ Vector3 N = Vector3(0.0, 0.0, 1.0);
+
+ float A = 0;
+ float B = 0;
+
+ for(int s=0;s<512;s++) {
+
+
+ Vector2 xi = Hammersley(s,512);
+ Vector3 H = ImportanceSampleGGX( xi, Roughness, N );
+ Vector3 L = 2.0 * V.dot(H) * H - V;
+
+ float NoL = CLAMP( L.z, 0.0, 1.0 );
+ float NoH = CLAMP( H.z, 0.0, 1.0 );
+ float VoH = CLAMP( V.dot(H), 0.0, 1.0 );
+
+ if ( NoL > 0.0 ) {
+ float G = G_Smith( Roughness, NoV, NoL );
+ float G_Vis = G * VoH / (NoH * NoV);
+ float Fc = pow(1.0 - VoH, 5.0);
+
+ A += (1.0 - Fc) * G_Vis;
+ B += Fc * G_Vis;
+ }
+ }
+
+ A/=512.0;
+ B/=512.0;
+
+ int tofs = ((brdf_size-j-1)*brdf_size+i)*2;
+ w[tofs+0]=CLAMP(A*255,0,255);
+ w[tofs+1]=CLAMP(B*255,0,255);
+ }
+ }
+
+
+ //set up brdf texture
+
+
+ glGenTextures(1, &state.brdf_texture);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D,state.brdf_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, brdf_size, brdf_size, 0, GL_RG, GL_UNSIGNED_BYTE,w.ptr());
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D,0);
}
@@ -989,6 +1569,12 @@ void RasterizerSceneGLES3::initialize() {
glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ glGenBuffers(1, &state.env_radiance_ubo);
+ glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_ubo, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+
render_list.max_elements=GLOBAL_DEF("rendering/gles3/max_renderable_elements",(int)RenderList::DEFAULT_MAX_ELEMENTS);
if (render_list.max_elements>1000000)
render_list.max_elements=1000000;
@@ -1017,6 +1603,7 @@ void RasterizerSceneGLES3::initialize() {
glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
}
render_list.init();
+ _generate_brdf();
}
void RasterizerSceneGLES3::finalize(){
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 53088deb0d..4b1b77f13c 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -32,12 +32,28 @@ public:
float camera_inverse_matrix[16];
float camera_matrix[16];
float time[4];
- float ambient_light[4];
+ float ambient_light_color[4];
+ float bg_color[4];
+ float ambient_energy;
+ float bg_energy;
} ubo_data;
GLuint scene_ubo;
+ struct EnvironmentRadianceUBO {
+
+ float transform[16];
+ float box_min[4]; //unused for now
+ float box_max[4];
+ float ambient_contribution;
+
+ } env_radiance_data;
+
+ GLuint env_radiance_ubo;
+
+ GLuint brdf_texture;
+
GLuint skybox_verts;
GLuint skybox_array;
@@ -54,16 +70,15 @@ public:
RID skybox_color;
RID skybox_radiance;
- RID skybox_irradiance;
float skybox_scale;
Color bg_color;
- float energy;
+ float bg_energy;
float skybox_ambient;
Color ambient_color;
- float ambient_anergy;
- float ambient_skybox_energy;
+ float ambient_energy;
+ float ambient_skybox_contribution;
int canvas_max_layer;
@@ -71,10 +86,10 @@ public:
Environment() {
bg_mode=VS::ENV_BG_CLEAR_COLOR;
skybox_scale=1.0;
- energy=1.0;
+ bg_energy=1.0;
skybox_ambient=0;
- ambient_anergy=1.0;
- ambient_skybox_energy=0.0;
+ ambient_energy=1.0;
+ ambient_skybox_contribution=0.0;
canvas_max_layer=0;
}
};
@@ -84,12 +99,12 @@ public:
virtual RID environment_create();
virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg);
- virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size,int p_irradiance_size);
+ virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size);
virtual void environment_set_skybox_scale(RID p_env,float p_scale);
virtual void environment_set_bg_color(RID p_env,const Color& p_color);
virtual void environment_set_bg_energy(RID p_env,float p_energy);
virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer);
- virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_energy=0.0);
+ virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0);
virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode);
virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture);
@@ -100,19 +115,81 @@ public:
virtual void environment_set_saturation(RID p_env,bool p_enable,float p_saturation);
virtual void environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp);
+
+ /* LIGHT INSTANCE */
+
+ struct LightInstance : public RID_Data {
+
+ struct SplitInfo {
+
+ CameraMatrix camera;
+ Transform transform;
+ float near;
+ float far;
+ };
+
+ struct LightDataUBO {
+
+ float light_pos_inv_radius[4];
+ float light_direction_attenuation[4];
+ float light_color_energy[4];
+ float light_params[4]; //cone attenuation, specular, shadow darkening,
+ float shadow_split_offsets[4];
+ float shadow_matrix1[16];
+ float shadow_matrix2[16];
+ float shadow_matrix3[16];
+ float shadow_matrix4[16];
+
+ } light_ubo_data;
+
+
+ SplitInfo split_info[4];
+
+ RID light;
+ RasterizerStorageGLES3::Light *light_ptr;
+
+ CameraMatrix shadow_matrix[4];
+
+ Transform transform;
+
+ Vector3 light_vector;
+ Vector3 spot_vector;
+ float linear_att;
+
+ GLuint light_ubo;
+
+ uint64_t shadow_pass;
+ uint64_t last_pass;
+ uint16_t light_index;
+
+ Vector2 dp;
+
+ CameraMatrix shadow_projection[4];
+
+
+ LightInstance() { }
+
+ };
+
+ mutable RID_Owner<LightInstance> light_instance_owner;
+
+ virtual RID light_instance_create(RID p_light);
+ virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform);
+
/* RENDER LIST */
struct RenderList {
enum {
DEFAULT_MAX_ELEMENTS=65536,
- MAX_LIGHTS=4,
SORT_FLAG_SKELETON=1,
SORT_FLAG_INSTANCING=2,
-
+ MAX_DIRECTIONAL_LIGHTS=16,
+ MAX_LIGHTS=4096,
SORT_KEY_DEPTH_LAYER_SHIFT=58,
SORT_KEY_LIGHT_TYPE_SHIFT=54, //type is most important
SORT_KEY_LIGHT_INDEX_SHIFT=38, //type is most important
+ SORT_KEY_LIGHT_INDEX_UNSHADED=uint64_t(0xF) << SORT_KEY_LIGHT_TYPE_SHIFT, //type is most important
SORT_KEY_MATERIAL_INDEX_SHIFT=22,
SORT_KEY_GEOMETRY_INDEX_SHIFT=6,
SORT_KEY_GEOMETRY_TYPE_SHIFT=2,
@@ -161,7 +238,24 @@ public:
SortArray<Element*,SortByKey> sorter;
if (p_alpha) {
- sorter.sort(&elements[max_elements-alpha_element_count-1],alpha_element_count);
+ sorter.sort(&elements[max_elements-alpha_element_count],alpha_element_count);
+ } else {
+ sorter.sort(elements,element_count);
+ }
+ }
+
+ struct SortByDepth {
+
+ _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const {
+ return A->instance->depth > B->instance->depth;
+ }
+ };
+
+ void sort_by_depth(bool p_alpha) {
+
+ SortArray<Element*,SortByDepth> sorter;
+ if (p_alpha) {
+ sorter.sort(&elements[max_elements-alpha_element_count],alpha_element_count);
} else {
sorter.sort(elements,element_count);
}
@@ -197,6 +291,7 @@ public:
}
+
RenderList() {
max_elements=DEFAULT_MAX_ELEMENTS;
@@ -210,26 +305,35 @@ public:
+ LightInstance *directional_light_instances[RenderList::MAX_DIRECTIONAL_LIGHTS];
+ int directional_light_instance_count;
+
+ LightInstance *light_instances[RenderList::MAX_LIGHTS];
+ int light_instance_count;
+
RenderList render_list;
_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass);
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
+ _FORCE_INLINE_ void _setup_light(LightInstance *p_light);
+ void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass);
- void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, bool p_reverse_cull, bool p_alpha_pass);
-
- virtual RID light_instance_create(RID p_light);
- virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform);
_FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material);
void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale);
+ void _setup_environment(Environment *env,CameraMatrix& p_cam_projection, const Transform& p_cam_transform);
+ void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform);
+
virtual void render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment);
virtual bool free(RID p_rid);
+ void _generate_brdf();
+
void initialize();
void finalize();
RasterizerSceneGLES3();
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 94ad2afabe..1141a605c5 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -587,6 +587,7 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture,int p_width, int p_h
texture->height=p_height;
texture->format=p_format;
texture->flags=p_flags;
+ texture->stored_cube_sides=0;
texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
_get_gl_image_and_format(Image(),texture->format,texture->flags,format,internal_format,type,compressed,srgb);
@@ -759,8 +760,9 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image
//printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem);
+ texture->stored_cube_sides|=(1<<p_cube_side);
- if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && mipmaps==1 && !texture->ignore_mipmaps) {
+ if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && mipmaps==1 && !texture->ignore_mipmaps && (!(texture->flags&VS::TEXTURE_FLAG_CUBEMAP) || texture->stored_cube_sides==(1<<6)-1)) {
//generate mipmaps if they were requested and the image does not contain them
glGenerateMipmap(texture->target);
}
@@ -995,7 +997,7 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable
config.shrink_textures_x2=p_enable;
}
-RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution) const {
+RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_resolution) const {
Texture * texture = texture_owner.get(p_source);
ERR_FAIL_COND_V(!texture,RID());
@@ -1019,12 +1021,13 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM
glDisable(GL_BLEND);
- glActiveTexture(GL_TEXTURE1);
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
- glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
GLuint new_cubemap;
glGenTextures(1, &new_cubemap);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, new_cubemap);
GLuint tmp_fb;
@@ -1033,8 +1036,7 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM
glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
- int w = texture->width;
- int h = texture->height;
+ int size = p_resolution;
int lod=0;
@@ -1044,19 +1046,42 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM
int mm_level=mipmaps;
+ GLenum internal_format = use_float?GL_RGBA16F:GL_RGB10_A2;
+ GLenum format = GL_RGBA;
+ GLenum type = use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV;
+
+
+ while(mm_level) {
+
+ for(int i=0;i<6;i++) {
+ glTexImage2D(_cube_side_enum[i], lod, internal_format, size, size, 0, format, type, NULL);
+ }
+
+ lod++;
+ mm_level--;
+
+ if (size>1)
+ size>>=1;
+ }
+
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod-1);
+
+ lod=0;
+ mm_level=mipmaps;
+
+ size = p_resolution;
+
while(mm_level) {
for(int i=0;i<6;i++) {
- glTexImage2D(_cube_side_enum[i], lod, use_float?GL_RGBA16F:GL_RGB10_A2, w, h, 0, GL_RGBA, use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV, NULL);
- glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, lod);
- glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, lod);
- glViewport(0,0,w,h);
+ glViewport(0,0,size,size);
glBindVertexArray(resources.quadie_array);
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::FACE_ID,i);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,lod/float(mipmaps));
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,lod/float(mipmaps-1));
glDrawArrays(GL_TRIANGLE_FAN,0,4);
@@ -1069,29 +1094,51 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM
- if (w>1)
- w>>=1;
- if (h>1)
- h>>=1;
-
+ if (size>1)
+ size>>=1;
lod++;
mm_level--;
}
- for(int i=0;i<6;i++) {
- //restore ranges
- glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod);
+ //restore ranges
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod-1);
- }
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
glDeleteFramebuffers(1, &tmp_fb);
-
- return RID();
+ Texture * ctex = memnew( Texture );
+
+ ctex->flags=VS::TEXTURE_FLAG_CUBEMAP|VS::TEXTURE_FLAG_MIPMAPS|VS::TEXTURE_FLAG_FILTER;
+ ctex->width=p_resolution;
+ ctex->height=p_resolution;
+ ctex->alloc_width=p_resolution;
+ ctex->alloc_height=p_resolution;
+ ctex->format=use_float?Image::FORMAT_RGBAH:Image::FORMAT_RGBA8;
+ ctex->target=GL_TEXTURE_CUBE_MAP;
+ ctex->gl_format_cache=format;
+ ctex->gl_internal_format_cache=internal_format;
+ ctex->gl_type_cache=type;
+ ctex->data_size=0;
+ ctex->compressed=false;
+ ctex->srgb=false;
+ ctex->total_data_size=0;
+ ctex->ignore_mipmaps=false;
+ ctex->mipmaps=mipmaps;
+ ctex->active=true;
+ ctex->tex_id=new_cubemap;
+ ctex->stored_cube_sides=(1<<6)-1;
+ ctex->render_target=NULL;
+
+ return texture_owner.make_rid(ctex);
}
@@ -1137,9 +1184,9 @@ void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode)
shader->mode=p_mode;
ShaderGLES3* shaders[VS::SHADER_MAX]={
- &canvas->state.canvas_shader,
&scene->state.scene_shader,
&canvas->state.canvas_shader,
+ &canvas->state.canvas_shader,
};
@@ -1231,10 +1278,14 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
shaders.actions_scene.render_mode_values["cull_back"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_BACK);
shaders.actions_scene.render_mode_values["cull_disable"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED);
- shaders.actions_canvas.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded;
- shaders.actions_canvas.render_mode_flags["ontop"]=&p_shader->spatial.ontop;
+ shaders.actions_scene.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded;
+ shaders.actions_scene.render_mode_flags["ontop"]=&p_shader->spatial.ontop;
+
+ shaders.actions_scene.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha;
+
+ actions=&shaders.actions_scene;
+ actions->uniforms=&p_shader->uniforms;
- shaders.actions_canvas.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha;
}
@@ -1243,6 +1294,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
Error err = shaders.compiler.compile(p_shader->mode,p_shader->code,actions,p_shader->path,gen_code);
+
ERR_FAIL_COND(err!=OK);
p_shader->shader->set_custom_shader_code(p_shader->custom_code_id,gen_code.vertex,gen_code.vertex_global,gen_code.fragment,gen_code.light,gen_code.fragment_global,gen_code.uniforms,gen_code.texture_uniforms,gen_code.defines);
@@ -1633,29 +1685,29 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[0]=v.r;
gui[1]=v.g;
- gui[3]=v.b;
- gui[4]=v.a;
+ gui[2]=v.b;
+ gui[3]=v.a;
} else if (value.get_type()==Variant::RECT2) {
Rect2 v=value;
gui[0]=v.pos.x;
gui[1]=v.pos.y;
- gui[3]=v.size.x;
- gui[4]=v.size.y;
+ gui[2]=v.size.x;
+ gui[3]=v.size.y;
} else if (value.get_type()==Variant::QUAT) {
Quat v=value;
gui[0]=v.x;
gui[1]=v.y;
- gui[3]=v.z;
- gui[4]=v.w;
+ gui[2]=v.z;
+ gui[3]=v.w;
} else {
Plane v=value;
gui[0]=v.normal.x;
gui[1]=v.normal.y;
- gui[3]=v.normal.x;
- gui[4]=v.d;
+ gui[2]=v.normal.x;
+ gui[3]=v.d;
}
} break;
@@ -2307,8 +2359,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
if (p_format&VS::ARRAY_FORMAT_INDEX) {
index_array_size=attribs[VS::ARRAY_INDEX].stride*p_index_count;
-
- print_line("index count: "+itos(p_index_count)+" stride: "+itos(attribs[VS::ARRAY_INDEX].stride) );
}
@@ -2882,55 +2932,134 @@ Matrix32 RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton,i
RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
- return RID();
+ Light *light = memnew( Light );
+ 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_RANGE]=1.0;
+ light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45;
+ light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0;
+ light->param[VS::LIGHT_PARAM_SHADOW_DARKNESS]=0;
+ light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET]=0.1;
+ light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET]=0.3;
+ light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET]=0.6;
+ light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_4_OFFSET]=1.0;
+ light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]=0.1;
+ light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]=0.1;
+
+
+ light->color=Color(1,1,1,1);
+ light->shadow=false;
+ light->negative=false;
+ light->cull_mask=0xFFFFFFFF;
+ light->directional_shadow_mode=VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+
+ return light_owner.make_rid(light);
}
void RasterizerStorageGLES3::light_set_color(RID p_light,const Color& p_color){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ light->color=p_color;
}
void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param,float p_value){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ ERR_FAIL_INDEX(p_param,VS::LIGHT_PARAM_MAX);
+ if (p_param==VS::LIGHT_PARAM_RANGE || p_param==VS::LIGHT_PARAM_SPOT_ANGLE) {
+ light->instance_change_notify();
+ }
+ light->param[p_param]=p_value;
}
void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ light->shadow=p_enabled;
}
void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
}
void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_texture){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
}
void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ light->negative=p_enable;
}
void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ light->cull_mask=p_mask;
}
void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
}
void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode){
+ Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
}
VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
+ const Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL);
+
return VS::LIGHT_DIRECTIONAL;
}
AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
+ const Light * light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light,AABB());
+
+ switch( light->type ) {
+
+ case VS::LIGHT_SPOT: {
+
+ float len=light->param[VS::LIGHT_PARAM_RANGE];
+ float size=Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE]))*len;
+ return AABB( Vector3( -size,-size,-len ), Vector3( size*2, size*2, len ) );
+ } break;
+ case VS::LIGHT_OMNI: {
+
+ float r = light->param[VS::LIGHT_PARAM_RANGE];
+ return AABB( -Vector3(r,r,r), Vector3(r,r,r)*2 );
+ } break;
+ case VS::LIGHT_DIRECTIONAL: {
+
+ return AABB();
+ } break;
+ default: {}
+ }
+
+ ERR_FAIL_V( AABB() );
return AABB();
}
@@ -3028,6 +3157,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene:
inst = mesh_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
+ case VS::INSTANCE_LIGHT: {
+ inst = light_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
default: {
ERR_FAIL();
}
@@ -3046,6 +3179,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce
ERR_FAIL_COND(!inst);
} break;
+ case VS::INSTANCE_LIGHT: {
+ inst = light_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
default: {
ERR_FAIL();
}
@@ -3542,6 +3679,9 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return VS::INSTANCE_MESH;
}
+ if (light_owner.owns(p_rid)) {
+ return VS::INSTANCE_LIGHT;
+ }
return VS::INSTANCE_NONE;
}
@@ -3617,6 +3757,14 @@ bool RasterizerStorageGLES3::free(RID p_rid){
mesh_owner.free(p_rid);
memdelete(mesh);
+ } else if (light_owner.owns(p_rid)) {
+
+ // delete the texture
+ Light *light = light_owner.get(p_rid);
+
+ light_owner.free(p_rid);
+ memdelete(light);
+
} else if (canvas_occluder_owner.owns(p_rid)) {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index c3022b3ac0..f052aa8019 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -135,10 +135,13 @@ public:
bool active;
GLuint tex_id;
+ uint16_t stored_cube_sides;
+
RenderTarget *render_target;
Texture() {
+ stored_cube_sides=0;
ignore_mipmaps=false;
render_target=NULL;
flags=width=height=0;
@@ -184,7 +187,7 @@ public:
virtual void texture_debug_usage(List<VS::TextureInfo> *r_info);
- virtual RID texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution=-1) const;
+ virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const;
/* SHADER API */
@@ -351,13 +354,6 @@ public:
struct Instantiable : public RID_Data {
- enum Type {
- GEOMETRY_INVALID,
- GEOMETRY_SURFACE,
- GEOMETRY_IMMEDIATE,
- GEOMETRY_MULTISURFACE,
- };
-
SelfList<RasterizerScene::InstanceBase>::List instance_list;
_FORCE_INLINE_ void instance_change_notify() {
@@ -582,6 +578,20 @@ public:
/* Light API */
+
+ struct Light : Instantiable {
+
+ VS::LightType type;
+ float param[VS::LIGHT_PARAM_MAX];
+ Color color;
+ bool shadow;
+ bool negative;
+ uint32_t cull_mask;
+ VS::LightDirectionalShadowMode directional_shadow_mode;
+ };
+
+ mutable RID_Owner<Light> light_owner;
+
virtual RID light_create(VS::LightType p_type);
virtual void light_set_color(RID p_light,const Color& p_color);
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 49707400ca..da8f6689d0 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -48,7 +48,7 @@ static int _get_datatype_size(SL::DataType p_type) {
case SL::TYPE_SAMPLERCUBE: return 16;
}
-
+ ERR_FAIL_V(0);
}
@@ -195,7 +195,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
- String ucode="uniform ";
+ String ucode;
+
+ if (SL::is_sampler_type(E->get().type)) {
+ ucode="uniform ";
+ }
+
ucode+=_prestr(E->get().precission);
ucode+=_typestr(E->get().type);
ucode+=" "+_mkid(E->key());
@@ -228,7 +233,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
for(int i=0;i<uniform_sizes.size();i++) {
if (i>0)
- r_gen_code.uniform_offsets[i]=uniform_sizes[i]-1;
+ r_gen_code.uniform_offsets[i]=uniform_sizes[i-1];
else
r_gen_code.uniform_offsets[i]=0;
}
@@ -320,7 +325,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
SL::VariableNode *vnode=(SL::VariableNode*)p_node;
if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) {
- r_gen_code.defines.push_back(p_default_actions.usage_defines[vnode->name].utf8());
+ String define = p_default_actions.usage_defines[vnode->name];
+ if (define.begins_with("@")) {
+ define = p_default_actions.usage_defines[define.substr(1,define.length())];
+ }
+ r_gen_code.defines.push_back(define.utf8());
used_name_defines.insert(vnode->name);
}
@@ -451,6 +460,14 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code,
Error err = parser.compile(p_code,ShaderTypes::get_singleton()->get_functions(p_mode),ShaderTypes::get_singleton()->get_modes(p_mode));
if (err!=OK) {
+#if 1
+
+ Vector<String> shader = p_code.split("\n");
+ for(int i=0;i<shader.size();i++) {
+ print_line(itos(i)+" "+shader[i]);
+ }
+#endif
+
_err_print_error(NULL,p_path.utf8().get_data(),parser.get_error_line(),parser.get_error_text().utf8().get_data(),ERR_HANDLER_SHADER);
return err;
}
@@ -469,6 +486,7 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code,
_dump_node_code(parser.get_shader(),1,r_gen_code,*p_actions,actions[p_mode]);
+
return OK;
}
@@ -518,6 +536,61 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n";
+ /** SPATIAL SHADER **/
+
+
+ actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"]="world_transform";
+ actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"]="camera_inverse_matrix";
+ actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"]="projection_matrix";
+
+
+ actions[VS::SHADER_SPATIAL].renames["VERTEX"]="vertex.xyz";
+ actions[VS::SHADER_SPATIAL].renames["NORMAL"]="normal";
+ actions[VS::SHADER_SPATIAL].renames["TANGENT"]="tangent";
+ actions[VS::SHADER_SPATIAL].renames["BINORMAL"]="binormal";
+ actions[VS::SHADER_SPATIAL].renames["UV"]="uv_interp";
+ actions[VS::SHADER_SPATIAL].renames["UV2"]="uv2_interp";
+ actions[VS::SHADER_SPATIAL].renames["COLOR"]="color_interp";
+ actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"]="gl_PointSize";
+ //actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"]=ShaderLanguage::TYPE_INT;
+
+ //builtins
+
+ actions[VS::SHADER_SPATIAL].renames["TIME"]="time";
+ //actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2;
+
+ actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"]="gl_FragCoord";
+ actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"]="gl_FrotFacing";
+ actions[VS::SHADER_SPATIAL].renames["NORMALMAP"]="normalmap";
+ actions[VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"]="normaldepth";
+ actions[VS::SHADER_SPATIAL].renames["ALBEDO"]="albedo";
+ 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["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";
+
+
+ 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["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";
+ actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"]="@NORMALMAP";
+ actions[VS::SHADER_SPATIAL].usage_defines["COLOR"]="#define ENABLE_COLOR_INTERP\n";
+
+ actions[VS::SHADER_SPATIAL].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n";
+
+
+
+
+
+
+
+
List<String> func_list;
ShaderLanguage::get_builtin_funcs(&func_list);
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index ebdf60cf42..052c915241 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -751,6 +751,7 @@ void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_ver
ERR_FAIL_COND(!custom_code_map.has(p_code_id));
CustomCode *cc=&custom_code_map[p_code_id];
+
cc->vertex=p_vertex;
cc->vertex_globals=p_vertex_globals;
cc->fragment=p_fragment;
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 176a2282fd..4c7f682dff 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -29,6 +29,7 @@
#ifndef SHADER_GLES3_H
#define SHADER_GLES3_H
+#include <stdio.h>
#include "platform_config.h"
#ifndef GLES3_INCLUDE_H
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
index f450f34113..d3d4cbd435 100644
--- a/drivers/gles3/shaders/cubemap_filter.glsl
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -16,19 +16,26 @@ void main() {
[fragment]
-uniform samplerCube source_cube; //texunit:1
+precision highp float;
+precision highp int;
+
+
+uniform samplerCube source_cube; //texunit:0
uniform int face_id;
uniform float roughness;
in highp vec2 uv_interp;
-layout(location = 0) vec4 frag_color;
+layout(location = 0) out vec4 frag_color;
+
+
+#define M_PI 3.14159265359
vec3 texelCoordToVec(vec2 uv, int faceID)
{
mat3 faceUvVectors[6];
-
+/*
// -x
faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
@@ -58,6 +65,37 @@ vec3 texelCoordToVec(vec2 uv, int faceID)
faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
+*/
+
+ // -x
+ faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z
+ faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face
+
+ // +x
+ faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z
+ faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face
+
+ // -y
+ faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z
+ faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face
+
+ // +y
+ faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z
+ faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face
+
+ // -z
+ faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
+ faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face
+
+ // +z
+ faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
@@ -113,7 +151,7 @@ vec2 Hammersley(uint i, uint N) {
return vec2(float(i)/float(N), radicalInverse_VdC(i));
}
-#define SAMPLE_COUNT 1024
+#define SAMPLE_COUNT 1024u
void main() {
@@ -123,20 +161,21 @@ void main() {
//vec4 color = color_interp;
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
- for(int sampleNum = 0; sampleNum < SAMPLE_COUNT; sampleNum++) {
+ for(uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) {
vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT);
- vec2 xi = texture2DLod(Texture0, vec2(float(sampleNum) / float(SAMPLE_COUNT), 0.5), 0.0).xy;
vec3 H = ImportanceSampleGGX( xi, roughness, N );
vec3 V = N;
vec3 L = normalize(2.0 * dot( V, H ) * H - V);
- float ndotl = max(0.0, dot(N, L));
- vec3 s = textureCubeLod(u_skyCube, H, 0.0).rgb * ndotl;
+ float ndotl = clamp(dot(N, L),0.0,1.0);
- sum += vec4(s, 1.0);
+ if (ndotl>0.0) {
+ sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl;
+ sum.a += ndotl;
+ }
}
- sum /= sum.w;
+ sum /= sum.a;
frag_color = vec4(sum.rgb, 1.0);
}
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 4183e828f5..3f94252606 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1,7 +1,7 @@
[vertex]
-
+#define ENABLE_UV_INTERP
/*
from VisualServer:
@@ -52,14 +52,47 @@ layout(std140) uniform SceneData { //ubo:0
highp mat4 camera_matrix;
highp vec4 time;
- highp vec4 ambient_light;
+ highp vec4 ambient_light_color;
+ highp vec4 bg_color;
+ float ambient_energy;
+ float bg_energy;
};
uniform highp mat4 world_transform;
+#ifdef USE_FORWARD_LIGHTING
+
+layout(std140) uniform LightData { //ubo:3
+
+ highp vec4 light_pos_inv_radius;
+ mediump vec4 light_direction_attenuation;
+ mediump vec4 light_color_energy;
+ mediump vec4 light_params; //cone attenuation, specular, shadow darkening,
+ mediump vec4 shadow_split_offsets;
+ highp mat4 shadow_matrix1;
+ highp mat4 shadow_matrix2;
+ highp mat4 shadow_matrix3;
+ highp mat4 shadow_matrix4;
+};
+
+#ifdef USE_FORWARD_1_SHADOW_MAP
+out mediump vec4 forward_shadow_pos1;
+#endif
+
+#ifdef USE_FORWARD_2_SHADOW_MAP
+out mediump vec4 forward_shadow_pos2;
+#endif
+
+#ifdef USE_FORWARD_4_SHADOW_MAP
+out mediump vec4 forward_shadow_pos3;
+out mediump vec4 forward_shadow_pos4;
+#endif
+
+#endif
+
/* Varyings */
-out vec3 vertex_interp;
+out highp vec3 vertex_interp;
out vec3 normal_interp;
#if defined(ENABLE_COLOR_INTERP)
@@ -74,13 +107,6 @@ out vec2 uv_interp;
out vec2 uv2_interp;
#endif
-#if defined(ENABLE_VAR1_INTERP)
-out vec4 var1_interp;
-#endif
-
-#if defined(ENABLE_VAR2_INTERP)
-out vec4 var2_interp;
-#endif
#if defined(ENABLE_TANGENT_INTERP)
out vec3 tangent_interp;
@@ -118,13 +144,13 @@ MATERIAL_UNIFORMS
void main() {
- highp vec4 vertex_in = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0);
+ highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0);
highp mat4 modelview = camera_inverse_matrix * world_transform;
- vec3 normal_in = normal_attrib;
- normal_in*=normal_mult;
+ vec3 normal = normal_attrib * normal_mult;
+
#if defined(ENABLE_TANGENT_INTERP)
- vec3 tangent_in = tangent_attrib.xyz;
- tangent_in*=normal_mult;
+ vec3 tangent = tangent_attrib.xyz;
+ tangent*=normal_mult;
float binormalf = tangent_attrib.a;
#endif
@@ -137,23 +163,31 @@ void main() {
m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.z;
m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.w;
- vertex_in = vertex_in * m;
- normal_in = (vec4(normal_in,0.0) * m).xyz;
+ vertex = vertex_in * m;
+ normal = (vec4(normal,0.0) * m).xyz;
#if defined(ENABLE_TANGENT_INTERP)
- tangent_in = (vec4(tangent_in,0.0) * m).xyz;
+ tangent = (vec4(tangent,0.0) * m).xyz;
#endif
}
#endif
- vertex_interp = (modelview * vertex_in).xyz;
- normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz);
+#if !defined(SKIP_TRANSFORM_USED)
+
+ vertex = modelview * vertex;
+ normal = normalize((modelview * vec4(normal,0.0)).xyz);
+#endif
#if defined(ENABLE_TANGENT_INTERP)
- tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz);
- binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf );
+# if !defined(SKIP_TRANSFORM_USED)
+
+ tangent=normalize((modelview * vec4(tangent,0.0)).xyz);
+# endif
+ vec3 binormal = normalize( cross(normal,tangent) * binormalf );
#endif
+
+
#if defined(ENABLE_COLOR_INTERP)
color_interp = color_attrib;
#endif
@@ -161,13 +195,17 @@ void main() {
#if defined(ENABLE_UV_INTERP)
uv_interp = uv_attrib;
#endif
+
#if defined(ENABLE_UV2_INTERP)
uv2_interp = uv2_attrib;
#endif
+{
VERTEX_SHADER_CODE
+}
+
#ifdef USE_SHADOW_PASS
@@ -177,26 +215,32 @@ VERTEX_SHADER_CODE
#endif
-#ifdef USE_FOG
+ vertex_interp = vertex.xyz;
+ normal_interp = normal;
- fog_interp.a = pow( clamp( (length(vertex_interp)-fog_params.x)/(fog_params.y-fog_params.x), 0.0, 1.0 ), fog_params.z );
- fog_interp.rgb = mix( fog_color_begin, fog_color_end, fog_interp.a );
+#if defined(ENABLE_TANGENT_INTERP)
+ tangent_interp = tangent;
+ binormal_interp = binormal;
#endif
-#ifndef VERTEX_SHADER_WRITE_POSITION
-//vertex shader might write a position
+#if !defined(SKIP_TRANSFORM_USED)
gl_Position = projection_matrix * vec4(vertex_interp,1.0);
+#else
+ gl_Position = vertex;
#endif
-
-
}
[fragment]
+
+#define M_PI 3.14159265359
+
+
+#define ENABLE_UV_INTERP
//hack to use uv if no uv present so it works with lightmap
@@ -219,17 +263,27 @@ in vec3 tangent_interp;
in vec3 binormal_interp;
#endif
-#if defined(ENABLE_VAR1_INTERP)
-in vec4 var1_interp;
-#endif
+in highp vec3 vertex_interp;
+in vec3 normal_interp;
-#if defined(ENABLE_VAR2_INTERP)
-in vec4 var2_interp;
-#endif
-in vec3 vertex_interp;
-in vec3 normal_interp;
+/* PBR CHANNELS */
+
+#ifdef USE_RADIANCE_CUBEMAP
+
+uniform sampler2D brdf_texture; //texunit:-1
+uniform samplerCube radiance_cube; //texunit:-2
+
+layout(std140) uniform Radiance { //ubo:2
+
+ mat4 radiance_inverse_xform;
+ vec3 radiance_box_min;
+ vec3 radiance_box_max;
+ float radiance_ambient_contribution;
+
+};
+#endif
/* Material Uniforms */
@@ -255,18 +309,97 @@ layout(std140) uniform SceneData {
highp mat4 camera_matrix;
highp vec4 time;
- highp vec4 ambient_light;
+ highp vec4 ambient_light_color;
+ highp vec4 bg_color;
+ float ambient_energy;
+ float bg_energy;
};
+
+#ifdef USE_FORWARD_LIGHTING
+
+layout(std140) uniform LightData {
+
+ highp vec4 light_pos_inv_radius;
+ mediump vec4 light_direction_attenuation;
+ mediump vec4 light_color_energy;
+ mediump vec4 light_params; //cone attenuation, specular, shadow darkening,
+ mediump vec4 shadow_split_offsets;
+ highp mat4 shadow_matrix1;
+ highp mat4 shadow_matrix2;
+ highp mat4 shadow_matrix3;
+ highp mat4 shadow_matrix4;
+};
+
+#ifdef USE_FORWARD_1_SHADOW_MAP
+in mediump vec4 forward_shadow_pos1;
+#endif
+
+#ifdef USE_FORWARD_2_SHADOW_MAP
+in mediump vec4 forward_shadow_pos2;
+#endif
+
+#ifdef USE_FORWARD_4_SHADOW_MAP
+in mediump vec4 forward_shadow_pos3;
+in mediump vec4 forward_shadow_pos4;
+#endif
+
+#endif
+
layout(location=0) out vec4 frag_color;
+
+// GGX Specular
+// Source: http://www.filmicworlds.com/images/ggx-opt/optimized-ggx.hlsl
+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 alpha = roughness * roughness;
+
+ vec3 H = normalize(V + L);
+
+ 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 );
+
+ // D
+ float alphaSqr = alpha * alpha;
+ float pi = M_PI;
+ float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
+ float D = alphaSqr / (pi * denom * denom);
+
+ // F
+ float dotLH5 = pow(1.0 - dotLH, 5.0);
+ float F = F0 + (1.0 - F0) * (dotLH5);
+
+ // V
+ float k = alpha / 2.0f;
+ float vis = G1V(dotNL, k) * G1V(dotNV, k);
+
+ return dotNL * D * F * vis;
+}
+
+void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color, vec3 specular_color, float roughness, float attenuation, inout vec3 diffuse, inout vec3 specular) {
+
+ diffuse += max(0.0,dot(normal,light_vec)) * diffuse_color * attenuation;
+ //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 * specular_color * attenuation;
+}
+
+
void main() {
//lay out everything, whathever is unused is optimized away anyway
vec3 vertex = vertex_interp;
- vec3 albedo = vec3(0.9,0.9,0.9);
- vec3 metal = vec3(0.0,0.0,0.0);
- float rough = 0.0;
+ vec3 albedo = vec3(0.8,0.8,0.8);
+ vec3 specular = vec3(0.2,0.2,0.2);
+ float roughness = 1.0;
float alpha = 1.0;
#ifdef METERIAL_DOUBLESIDED
@@ -334,6 +467,66 @@ FRAGMENT_SHADER_CODE
}
#endif
+/////////////////////// LIGHTING //////////////////////////////
+
+ vec3 specular_light = vec3(0.0,0.0,0.0);
+ vec3 ambient_light = ambient_light_color.rgb;
+ vec3 diffuse_light = vec3(0.0,0.0,0.0);
+
+ vec3 eye_vec = -normalize( vertex_interp );
+
+#ifdef USE_RADIANCE_CUBEMAP
+
+ {
+
+ float ndotv = clamp(dot(normal,eye_vec),0.0,1.0);
+ vec2 brdf = texture(brdf_texture, vec2(roughness, ndotv)).xy;
+
+ float lod = roughness * 5.0;
+ vec3 r = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n);
+ r=normalize((radiance_inverse_xform * vec4(r,0.0)).xyz);
+ vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y);
+
+ specular_light=mix(albedo,radiance,specular);
+
+ }
+
+ {
+
+ vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz);
+ vec3 env_ambient=textureLod(radiance_cube, ambient_dir, 5.0).xyz;
+
+ ambient_light=mix(ambient_light,env_ambient,radiance_ambient_contribution);
+ }
+
+
+#else
+
+ ambient_light=albedo;
+#endif
+
+
+#ifdef USE_FORWARD_LIGHTING
+
+#ifdef USE_FORWARD_DIRECTIONAL
+
+ light_compute(normal,light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,1.0,diffuse_light,specular_light);
+#endif
+
+#ifdef USE_FORWARD_OMNI
+
+ vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex;
+ float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w;
+ float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w );
+ light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
+
+#endif
+
+#ifdef USE_FORWARD_SPOT
+
+#endif
+
+#endif
#if defined(USE_LIGHT_SHADER_CODE)
@@ -345,7 +538,14 @@ LIGHT_SHADER_CODE
}
#endif
+#ifdef SHADELESS
+
frag_color=vec4(albedo,alpha);
+#else
+ frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha);
+
+#endif
+
}