diff options
Diffstat (limited to 'drivers/gles3')
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 709 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 138 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 226 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 26 | ||||
-rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 81 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.cpp | 1 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.h | 1 | ||||
-rw-r--r-- | drivers/gles3/shaders/cubemap_filter.glsl | 59 | ||||
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 282 |
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 + } |