diff options
Diffstat (limited to 'drivers/gles2')
| -rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 526 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_gles2.h | 86 | ||||
| -rw-r--r-- | drivers/gles2/shader_compiler_gles2.cpp | 7 | ||||
| -rw-r--r-- | drivers/gles2/shader_compiler_gles2.h | 1 | ||||
| -rw-r--r-- | drivers/gles2/shader_gles2.cpp | 8 | ||||
| -rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 3 | ||||
| -rw-r--r-- | drivers/gles2/shaders/copy.glsl | 113 | ||||
| -rw-r--r-- | drivers/gles2/shaders/material.glsl | 125 |
8 files changed, 787 insertions, 82 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 58abb71a12..74a82e1a5c 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -952,7 +952,11 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { Texture *texture = texture_owner.get( p_texture ); ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->render_target); + if (texture->render_target) { + + p_flags&=VS::TEXTURE_FLAG_FILTER;//can change only filter + } + glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); @@ -2241,6 +2245,9 @@ AABB RasterizerGLES2::mesh_get_aabb(RID p_mesh) const { Mesh *mesh = mesh_owner.get( p_mesh ); ERR_FAIL_COND_V(!mesh,AABB()); + if (mesh->custom_aabb!=AABB()) + return mesh->custom_aabb; + AABB aabb; for (int i=0;i<mesh->surfaces.size();i++) { @@ -2253,6 +2260,24 @@ AABB RasterizerGLES2::mesh_get_aabb(RID p_mesh) const { return aabb; } + + +void RasterizerGLES2::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb) { + + Mesh *mesh = mesh_owner.get( p_mesh ); + ERR_FAIL_COND(!mesh); + + mesh->custom_aabb=p_aabb; + +} + +AABB RasterizerGLES2::mesh_get_custom_aabb(RID p_mesh) const { + + const Mesh *mesh = mesh_owner.get( p_mesh ); + ERR_FAIL_COND_V(!mesh,AABB()); + + return mesh->custom_aabb; +} /* MULTIMESH API */ RID RasterizerGLES2::multimesh_create() { @@ -2464,6 +2489,156 @@ int RasterizerGLES2::multimesh_get_visible_instances(RID p_multimesh) const { } +/* IMMEDIATE API */ + + +RID RasterizerGLES2::immediate_create() { + + Immediate *im = memnew( Immediate ); + return immediate_owner.make_rid(im); + +} + +void RasterizerGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(im->building); + + Immediate::Chunk ic; + ic.texture=p_texture; + ic.primitive=p_rimitive; + im->chunks.push_back(ic); + im->mask=0; + im->building=true; + + +} +void RasterizerGLES2::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + Immediate::Chunk *c = &im->chunks.back()->get(); + + + if (c->vertices.empty() && im->chunks.size()==1) { + + im->aabb.pos=p_vertex; + im->aabb.size=Vector3(); + } else { + im->aabb.expand_to(p_vertex); + } + + if (im->mask&VS::ARRAY_FORMAT_NORMAL) + c->normals.push_back(chunk_normal); + if (im->mask&VS::ARRAY_FORMAT_TANGENT) + c->tangents.push_back(chunk_tangent); + if (im->mask&VS::ARRAY_FORMAT_COLOR) + c->colors.push_back(chunk_color); + if (im->mask&VS::ARRAY_FORMAT_TEX_UV) + c->uvs.push_back(chunk_uv); + if (im->mask&VS::ARRAY_FORMAT_TEX_UV2) + c->uvs2.push_back(chunk_uv2); + im->mask|=VS::ARRAY_FORMAT_VERTEX; + c->vertices.push_back(p_vertex); + +} + + +void RasterizerGLES2::immediate_normal(RID p_immediate,const Vector3& p_normal){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_NORMAL; + chunk_normal=p_normal; + +} +void RasterizerGLES2::immediate_tangent(RID p_immediate,const Plane& p_tangent){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TANGENT; + chunk_tangent=p_tangent; + +} +void RasterizerGLES2::immediate_color(RID p_immediate,const Color& p_color){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_COLOR; + chunk_color=p_color; + +} +void RasterizerGLES2::immediate_uv(RID p_immediate,const Vector2& tex_uv){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TEX_UV; + chunk_uv=tex_uv; + +} +void RasterizerGLES2::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TEX_UV2; + chunk_uv2=tex_uv; + +} + +void RasterizerGLES2::immediate_end(RID p_immediate){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->building=false; + +} +void RasterizerGLES2::immediate_clear(RID p_immediate) { + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(im->building); + + im->chunks.clear(); +} + +AABB RasterizerGLES2::immediate_get_aabb(RID p_immediate) const { + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND_V(!im,AABB()); + return im->aabb; +} + +void RasterizerGLES2::immediate_set_material(RID p_immediate,RID p_material) { + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + im->material=p_material; + +} + +RID RasterizerGLES2::immediate_get_material(RID p_immediate) const { + + const Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND_V(!im,RID()); + return im->material; + +} + /* PARTICLES API */ @@ -3114,7 +3289,8 @@ Rasterizer::ShadowType RasterizerGLES2::light_instance_get_shadow_type(RID p_lig case VS::LIGHT_DIRECTIONAL_SHADOW_PERSPECTIVE:{ return SHADOW_PSM; } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_SPLIT:{ + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:{ return SHADOW_PSSM; } break; } @@ -3131,9 +3307,13 @@ int RasterizerGLES2::light_instance_get_shadow_passes(RID p_light_instance) cons LightInstance *lighti = light_instance_owner.get( p_light_instance ); ERR_FAIL_COND_V(!lighti,0); - if (lighti->base->type==VS::LIGHT_OMNI || (lighti->base->type==VS::LIGHT_DIRECTIONAL && lighti->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_SPLIT)) + + if (lighti->base->type==VS::LIGHT_DIRECTIONAL && lighti->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + + return 4; // dp4 + } else if (lighti->base->type==VS::LIGHT_OMNI || (lighti->base->type==VS::LIGHT_DIRECTIONAL && lighti->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS)) { return 2; // dp - else + } else return 1; } @@ -3145,6 +3325,10 @@ void RasterizerGLES2::light_instance_set_shadow_transform(RID p_light_instance, ERR_FAIL_COND(lighti->base->type!=VS::LIGHT_DIRECTIONAL); // ERR_FAIL_INDEX(p_index,1); + lighti->custom_projection[p_index]=p_camera; + lighti->custom_transform[p_index]=p_transform; + lighti->shadow_split[p_index]=1.0/p_split_far; +#if 0 if (p_index==0) { lighti->custom_projection=p_camera; lighti->custom_transform=p_transform; @@ -3161,7 +3345,7 @@ void RasterizerGLES2::light_instance_set_shadow_transform(RID p_light_instance, lighti->shadow_split2=p_split_far; } - +#endif } int RasterizerGLES2::light_instance_get_shadow_size(RID p_light_instance, int p_index) const{ @@ -3407,6 +3591,7 @@ void RasterizerGLES2::begin_frame() { //fragment_lighting=Globals::get_singleton()->get("rasterizer/use_fragment_lighting"); canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false)); + shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter"))); window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height ); @@ -3675,18 +3860,21 @@ void RasterizerGLES2::add_light( RID p_light_instance ) { if (li->base->shadow_enabled) { CameraMatrix bias; bias.set_light_bias(); - Transform modelview=Transform(camera_transform_inverse * li->custom_transform).inverse(); - li->shadow_projection = bias * li->custom_projection * modelview; - Transform modelview2=Transform(camera_transform_inverse * li->custom_transform2).inverse(); - li->shadow_projection2 = bias * li->custom_projection2 * modelview2; + 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; } } break; case VS::LIGHT_OMNI: { if (li->base->shadow_enabled) { - li->shadow_projection = Transform(camera_transform_inverse * li->transform).inverse(); + li->shadow_projection[0] = Transform(camera_transform_inverse * li->transform).inverse(); lights_use_shadow=true; } } break; @@ -3696,7 +3884,7 @@ void RasterizerGLES2::add_light( RID p_light_instance ) { CameraMatrix bias; bias.set_light_bias(); Transform modelview=Transform(camera_transform_inverse * li->transform).inverse(); - li->shadow_projection = bias * li->projection * modelview; + li->shadow_projection[0] = bias * li->projection * modelview; lights_use_shadow=true; } } break; @@ -3755,9 +3943,16 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { //print_line("UCF: "+itos(p_shader->uniforms.size())); + int first_tex_index=0xFFFFF; + p_shader->first_texture=StringName(); + for(Map<StringName,ShaderLanguage::Uniform>::Element *E=p_shader->uniforms.front();E;E=E->next()) { uniform_names.push_back("_"+String(E->key())); + if (E->get().type==ShaderLanguage::TYPE_TEXTURE && E->get().order<first_tex_index) { + p_shader->first_texture=E->key(); + first_tex_index=E->get().order; + } } if (p_shader->mode==VS::SHADER_MATERIAL) { @@ -3781,6 +3976,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (flags.uses_screen_uv) { enablers.push_back("#define ENABLE_SCREEN_UV\n"); } + if (flags.uses_discard) { + enablers.push_back("#define ENABLE_DISCARD\n"); + } material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names,enablers); } else { @@ -3789,6 +3987,8 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { p_shader->valid=true; p_shader->has_alpha=flags.uses_alpha || flags.uses_texscreen; + p_shader->writes_vertex=flags.vertex_code_writes_vertex; + p_shader->uses_discard=flags.uses_discard; p_shader->has_texscreen=flags.uses_texscreen; p_shader->has_screen_uv=flags.uses_screen_uv; p_shader->can_zpass=!flags.uses_discard && !flags.vertex_code_writes_vertex; @@ -3849,16 +4049,19 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD RenderList *render_list=NULL; - bool has_alpha = m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || (m->shader_cache && m->shader_cache->has_alpha) || m->flags[VS::MATERIAL_FLAG_ONTOP]; + 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 = has_base_alpha || has_blend_alpha; if (shadow) { - if (has_alpha) + if (has_blend_alpha || (has_base_alpha && !m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS])) return; //bye - if (true) { - m = shadow_mat_ptr; //for now do this always + if (m->shader_cache && !m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && !m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]) { + //shader does not use discard and does not write a vertex position, use generic material + m = shadow_mat_ptr; if (m->last_pass!=frame) { if (m->shader.is_valid()) { @@ -3901,6 +4104,9 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD RenderList::Element *e = render_list->add_element(); + if (!e) + return; + e->geometry=p_geometry; e->geometry_cmp=p_geometry_cmp; e->material=m; @@ -3936,6 +4142,18 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD e->light_type=0xFF; // no lights! e->light=0xFFFF; + if (!shadow && !has_blend_alpha && has_alpha && m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]) { + + //if nothing exists, add this element as opaque too + RenderList::Element *oe = opaque_render_list.add_element(); + + if (!oe) + return; + + memcpy(oe,e,sizeof(RenderList::Element)); + oe->additive_ptr=&oe->additive; + } + if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED]) { e->light_type=0x7F; //unshaded is zero @@ -3954,8 +4172,10 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD light_types[i]=VS::LIGHT_DIRECTIONAL; if (directional_lights[i]->base->shadow_enabled) { light_types[i]|=0x8; - if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_SPLIT) + if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) light_types[i]|=0x10; + else if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) + light_types[i]|=0x30; } @@ -4058,6 +4278,17 @@ void RasterizerGLES2::add_multimesh( const RID& p_multimesh, const InstanceData } +void RasterizerGLES2::add_immediate( const RID& p_immediate, const InstanceData *p_data) { + + + Immediate *immediate = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!immediate); + + _add_geometry(immediate,p_data,immediate,NULL); + +} + + void RasterizerGLES2::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ //print_line("adding particles"); @@ -4129,7 +4360,7 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ } -bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light) { +bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light,bool p_opaque_pass) { if (p_material->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED]) { glDisable(GL_CULL_FACE); @@ -4152,14 +4383,23 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material //all goes to false by default material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PASS,shadow!=NULL); - material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,use_shadow_pcf); + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,shadow_filter!=SHADOW_FILTER_NONE); + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter>SHADOW_FILTER_PCF5); //material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,true); + if (p_opaque_pass && p_material->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS] && p_material->shader_cache && p_material->shader_cache->has_alpha) { + + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,true); + } else { + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,false); + + } + if (!shadow) { bool depth_test=!p_material->flags[VS::MATERIAL_FLAG_ONTOP]; - bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW]; + bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW] && (p_opaque_pass || !p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]); if (current_depth_mask!=depth_write) { current_depth_mask=depth_write; @@ -4235,6 +4475,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material if (t) { if (t->render_target) t->render_target->last_pass=frame; + if (E->key()==p_material->shader_cache->first_texture) { + tc0_idx=texcoord; + tc0_id_cache=t->tex_id; + } glBindTexture(t->target,t->tex_id); } else glBindTexture(GL_TEXTURE_2D,white_tex); //no texture @@ -4379,16 +4623,27 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { //} - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,7); - if (li->base->type==VS::LIGHT_DIRECTIONAL && li->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_SPLIT) { + if (li->base->type==VS::LIGHT_DIRECTIONAL) { + + if (li->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX2,li->shadow_projection[1]); + material_shader.set_uniform(MaterialShaderGLES2::LIGHT_PSSM_SPLIT,Vector3(li->shadow_split[0],li->shadow_split[1],li->shadow_split[2])); + } else if (li->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX2,li->shadow_projection2); - material_shader.set_uniform(MaterialShaderGLES2::LIGHT_PSSM_SPLIT,li->shadow_split); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX2,li->shadow_projection[1]); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX3,li->shadow_projection[2]); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX4,li->shadow_projection[3]); + material_shader.set_uniform(MaterialShaderGLES2::LIGHT_PSSM_SPLIT,Vector3(li->shadow_split[0],li->shadow_split[1],li->shadow_split[2])); + + } //print_line("shadow split: "+rtos(li->shadow_split)); - } + } else material_shader.set_uniform(MaterialShaderGLES2::SHADOW_DARKENING,li->base->vars[VS::LIGHT_PARAM_SHADOW_DARKENING]); //matrix @@ -4967,6 +5222,109 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater }; } } break; + case Geometry::GEOMETRY_IMMEDIATE: { + + bool restore_tex=false; + const Immediate *im = static_cast<const Immediate*>( p_geometry ); + if (im->building) { + return; + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + for(const List<Immediate::Chunk>::Element *E=im->chunks.front();E;E=E->next()) { + + const Immediate::Chunk &c=E->get(); + if (c.vertices.empty()) { + continue; + } + for(int i=0;i<c.vertices.size();i++) + + if (c.texture.is_valid() && texture_owner.owns(c.texture)) { + + const Texture *t = texture_owner.get(c.texture); + glActiveTexture(GL_TEXTURE0+tc0_idx); + glBindTexture(t->target,t->tex_id); + restore_tex=true; + + + } else if (restore_tex) { + + glActiveTexture(GL_TEXTURE0+tc0_idx); + glBindTexture(GL_TEXTURE_2D,tc0_id_cache); + restore_tex=false; + } + + if (!c.normals.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_NORMAL); + glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false,sizeof(Vector3),c.normals.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_NORMAL); + } + + if (!c.tangents.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TANGENT); + glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false,sizeof(Plane),c.tangents.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TANGENT); + } + + if (!c.colors.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false,sizeof(Color),c.colors.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_COLOR); + _set_color_attrib(Color(1, 1, 1,1)); + } + + + if (!c.uvs.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + if (!c.uvs2.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); + glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs2.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); + } + + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false,sizeof(Vector3),c.vertices.ptr()); + glDrawArrays(gl_primitive[c.primitive],0,c.vertices.size()); + + + } + + + if (restore_tex) { + + glActiveTexture(GL_TEXTURE0+tc0_idx); + glBindTexture(GL_TEXTURE_2D,tc0_id_cache); + restore_tex=false; + } + + + } break; case Geometry::GEOMETRY_PARTICLES: { @@ -5126,11 +5484,13 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT,false); material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW,false); material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,false); material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,false); } + bool stores_glow = !shadow && (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) && !p_alpha_pass; bool prev_blend=false; glDisable(GL_BLEND); @@ -5151,7 +5511,6 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (!shadow) { if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) { - texscreen_copied=true; _copy_to_texscreen(); @@ -5179,6 +5538,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT,false); material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW,false); material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,false); material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,true); } else { material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_DIRECTIONAL,(light_type&0x3)==VS::LIGHT_DIRECTIONAL); @@ -5186,6 +5546,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT,(light_type&0x3)==VS::LIGHT_SPOT); material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW,(light_type&0x8)); material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,(light_type&0x10)); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,(light_type&0x20)); material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,false); } @@ -5196,11 +5557,15 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (!*e->additive_ptr) { additive=false; - *e->additive_ptr=true; + *e->additive_ptr=true; } else { additive=true; } + if (stores_glow) + material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,!additive); + + bool desired_blend=false; VS::MaterialBlendMode desired_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; @@ -5216,8 +5581,10 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (desired_blend) { glEnable(GL_BLEND); + glColorMask(1,1,1,0); } else { glDisable(GL_BLEND); + glColorMask(1,1,1,1); } prev_blend=desired_blend; @@ -5278,7 +5645,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (material!=prev_material || rebind) { - rebind = _setup_material(e->geometry,material,additive); + rebind = _setup_material(e->geometry,material,additive,!p_alpha_pass); DEBUG_TEST_ERROR("Setup material"); _rinfo.mat_change_count++; @@ -5471,9 +5838,12 @@ void RasterizerGLES2::_process_glow_bloom() { _copy_screen_quad(); copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_COPY,false); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false); int passes = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]; Vector2 psize(1.0/framebuffer.blur_size,1.0/framebuffer.blur_size); + float pscale = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE]; + float pmag = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH]; + for(int i=0;i<passes;i++) { @@ -5496,6 +5866,8 @@ void RasterizerGLES2::_process_glow_bloom() { copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS,false); copy_shader.bind(); copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize); + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale); + copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,pmag); _draw_gui_primitive(4,dst_pos,NULL,src_uv); @@ -5506,6 +5878,8 @@ void RasterizerGLES2::_process_glow_bloom() { copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS,true); copy_shader.bind(); copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize); + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale); + copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,pmag); _draw_gui_primitive(4,dst_pos,NULL,src_uv); @@ -5634,6 +6008,8 @@ void RasterizerGLES2::_draw_tex_bg() { copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false); } + copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true); + copy_shader.bind(); if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { @@ -5646,6 +6022,7 @@ void RasterizerGLES2::_draw_tex_bg() { if (current_env->fx_enabled[VS::ENV_FX_HDR]) nrg*=0.25; //go down a quarter for hdr copy_shader.set_uniform(CopyShaderGLES2::ENERGY,nrg); + copy_shader.set_uniform(CopyShaderGLES2::CUSTOM_ALPHA,float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW])); Vector3 vertices[4]={ Vector3(-1,-1,1), @@ -5715,6 +6092,7 @@ void RasterizerGLES2::_draw_tex_bg() { copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY,false); copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false); copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,false); } void RasterizerGLES2::end_scene() { @@ -5795,7 +6173,7 @@ void RasterizerGLES2::end_scene() { bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR]; else bgcolor = Globals::get_singleton()->get("render/default_clear_color"); - float a = use_fb ? 0.0 : 1.0; + float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0; glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a); _glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); @@ -5843,7 +6221,7 @@ void RasterizerGLES2::end_scene() { glDisable(GL_BLEND); current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); + //material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); opaque_render_list.sort_mat_light_type_flags(); _render_list_forward(&opaque_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting); @@ -5864,7 +6242,7 @@ void RasterizerGLES2::end_scene() { } alpha_render_list.sort_z(); - _render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,false,true); + _render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); glColorMask(1,1,1,1); // material_shader.set_conditional( MaterialShaderGLES2::USE_FOG,false); @@ -5894,17 +6272,25 @@ void RasterizerGLES2::end_scene() { _process_hdr(); } if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { - _process_glow_bloom(); + _process_glow_bloom(); + int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE]; + if (glow_transfer_mode==1) + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true); + if (glow_transfer_mode==2) + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,true); } glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer); + Size2 size; if (current_rt) { glBindFramebuffer(GL_FRAMEBUFFER, current_rt->fbo); glViewport( 0,0,viewport.width,viewport.height); + size=Size2(viewport.width,viewport.height); } else { glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); + size=Size2(viewport.width,viewport.height); } //time to copy!!! @@ -5913,6 +6299,7 @@ void RasterizerGLES2::end_scene() { copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]); copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,true); + copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]); copy_shader.bind(); //copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0); @@ -5934,6 +6321,9 @@ void RasterizerGLES2::end_scene() { } + if (current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]) + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Size2(1.0/size.x,1.0/size.y)); + if (current_env && current_env->fx_enabled[VS::ENV_FX_BCS]) { @@ -5957,6 +6347,9 @@ void RasterizerGLES2::end_scene() { copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,false); copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false); copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false); material_shader.set_conditional(MaterialShaderGLES2::USE_HDR,false); @@ -6010,18 +6403,45 @@ void RasterizerGLES2::end_shadow_map() { case VS::LIGHT_DIRECTIONAL: { - if (shadow->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_SPLIT) { + if (shadow->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + + cm = shadow->custom_projection[shadow_pass]; + light_transform=shadow->custom_transform[shadow_pass]; if (shadow_pass==0) { - cm = shadow->custom_projection; - light_transform=shadow->custom_transform; + glViewport(0, sb->size*0.5, sb->size*0.5, sb->size*0.5); + glScissor(0, sb->size*0.5, sb->size*0.5, sb->size*0.5); + } else if (shadow_pass==1) { + + glViewport(0, 0, sb->size*0.5, sb->size*0.5); + glScissor(0, 0, sb->size*0.5, sb->size*0.5); + + } else if (shadow_pass==2) { + + glViewport(sb->size*0.5, sb->size*0.5, sb->size*0.5, sb->size*0.5); + glScissor(sb->size*0.5, sb->size*0.5, sb->size*0.5, sb->size*0.5); + } else if (shadow_pass==3) { + + glViewport(sb->size*0.5, 0, sb->size*0.5, sb->size*0.5); + glScissor(sb->size*0.5, 0, sb->size*0.5, sb->size*0.5); + + } + + glEnable(GL_SCISSOR_TEST); + + } else if (shadow->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + + if (shadow_pass==0) { + + cm = shadow->custom_projection[0]; + light_transform=shadow->custom_transform[0]; glViewport(0, sb->size*0.5, sb->size, sb->size*0.5); glScissor(0, sb->size*0.5, sb->size, sb->size*0.5); } else { - cm = shadow->custom_projection2; - light_transform=shadow->custom_transform2; + cm = shadow->custom_projection[1]; + light_transform=shadow->custom_transform[1]; glViewport(0, 0, sb->size, sb->size*0.5); glScissor(0, 0, sb->size, sb->size*0.5); @@ -6030,8 +6450,8 @@ void RasterizerGLES2::end_shadow_map() { glEnable(GL_SCISSOR_TEST); } else { - cm = shadow->custom_projection; - light_transform=shadow->custom_transform; + cm = shadow->custom_projection[0]; + light_transform=shadow->custom_transform[0]; glViewport(0, 0, sb->size, sb->size); } @@ -6122,8 +6542,8 @@ void RasterizerGLES2::end_shadow_map() { //glDisable(GL_POLYGON_OFFSET_FILL); - if (!use_rgba_shadowmaps) - glColorMask(1, 1, 1, 1); + //if (!use_rgba_shadowmaps) + glColorMask(1, 1, 1, 1); DEBUG_TEST_ERROR("Drawing Shadow"); shadow=NULL; @@ -6342,7 +6762,10 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { case VS::MATERIAL_BLEND_MODE_MUL: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - + } break; + case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); } break; } @@ -6853,6 +7276,10 @@ bool RasterizerGLES2::is_mesh(const RID& p_rid) const { return mesh_owner.owns(p_rid); } +bool RasterizerGLES2::is_immediate(const RID& p_rid) const { + + return immediate_owner.owns(p_rid); +} bool RasterizerGLES2::is_multimesh(const RID& p_rid) const { return multimesh_owner.owns(p_rid); @@ -6977,6 +7404,13 @@ void RasterizerGLES2::free(const RID& p_rid) { multimesh_owner.free(p_rid); memdelete(multimesh); + } else if (immediate_owner.owns(p_rid)) { + + Immediate *immediate = immediate_owner.get(p_rid); + ERR_FAIL_COND(!immediate); + + immediate_owner.free(p_rid); + memdelete(immediate); } else if (particles_owner.owns(p_rid)) { Particles *particles = particles_owner.get(p_rid); @@ -7993,9 +8427,11 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo p_default_fragment_lighting=false; fragment_lighting=GLOBAL_DEF("rasterizer/use_fragment_lighting",true); read_depth_supported=true; //todo check for extension - use_shadow_pcf=GLOBAL_DEF("rasterizer/use_shadow_pcf",true); + shadow_filter=ShadowFilterTechnique((int)(GLOBAL_DEF("rasterizer/shadow_filter",SHADOW_FILTER_PCF5))); + Globals::get_singleton()->set_custom_property_info("rasterizer/shadow_filter",PropertyInfo(Variant::INT,"rasterizer/shadow_filter",PROPERTY_HINT_ENUM,"None,PCF5,PCF13,ESM,VSM")); + use_shadow_mapping=true; - use_fast_texture_filter=GLOBAL_DEF("rasterizer/trilinear_mipmap_filter",true); + use_fast_texture_filter=!bool(GLOBAL_DEF("rasterizer/trilinear_mipmap_filter",true)); skel_default.resize(1024*4); for(int i=0;i<1024/3;i++) { @@ -8022,6 +8458,8 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo draw_next_frame=false; use_framebuffers=true; framebuffer.active=false; + tc0_id_cache=0; + tc0_idx=0; }; RasterizerGLES2::~RasterizerGLES2() { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index f18bdd1ff7..0fee8bf918 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -80,6 +80,8 @@ class RasterizerGLES2 : public Rasterizer { bool read_depth_supported; bool use_framebuffers; bool use_shadow_mapping; + ShadowFilterTechnique shadow_filter; + bool use_shadow_esm; bool use_shadow_pcf; bool use_hw_skeleton_xform; @@ -171,8 +173,11 @@ class RasterizerGLES2 : public Rasterizer { bool can_zpass; bool has_texscreen; bool has_screen_uv; + bool writes_vertex; + bool uses_discard; Map<StringName,ShaderLanguage::Uniform> uniforms; + StringName first_texture; SelfList<Shader> dirty_list; @@ -188,6 +193,8 @@ class RasterizerGLES2 : public Rasterizer { can_zpass=true; has_texscreen=false; has_screen_uv=false; + writes_vertex=false; + uses_discard=false; } @@ -233,6 +240,7 @@ class RasterizerGLES2 : public Rasterizer { flags[VS::MATERIAL_FLAG_VISIBLE]=true; for(int i=0;i<VS::MATERIAL_HINT_MAX;i++) hints[i]=false; + hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]=true; line_width=1; has_alpha=false; @@ -254,7 +262,7 @@ class RasterizerGLES2 : public Rasterizer { enum Type { GEOMETRY_INVALID, GEOMETRY_SURFACE, - GEOMETRY_POLY, + GEOMETRY_IMMEDIATE, GEOMETRY_PARTICLES, GEOMETRY_MULTISURFACE, }; @@ -374,6 +382,7 @@ class RasterizerGLES2 : public Rasterizer { Vector<Surface*> surfaces; int morph_target_count; VS::MorphTargetMode morph_target_mode; + AABB custom_aabb; mutable uint64_t last_pass; Mesh() { @@ -454,6 +463,31 @@ class RasterizerGLES2 : public Rasterizer { mutable RID_Owner<MultiMesh> multimesh_owner; mutable SelfList<MultiMesh>::List _multimesh_dirty_list; + struct Immediate : public Geometry { + + struct Chunk { + + RID texture; + VS::PrimitiveType primitive; + Vector<Vector3> vertices; + Vector<Vector3> normals; + Vector<Plane> tangents; + Vector<Color> colors; + Vector<Vector2> uvs; + Vector<Vector2> uvs2; + }; + + List<Chunk> chunks; + bool building; + int mask; + AABB aabb; + + Immediate() { type=GEOMETRY_IMMEDIATE; building=false;} + + }; + + mutable RID_Owner<Immediate> immediate_owner; + struct Particles : public Geometry { ParticleSystemSW data; // software particle system @@ -582,11 +616,15 @@ class RasterizerGLES2 : public Rasterizer { bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID(); bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0; bg_param[VS::ENV_BG_PARAM_SCALE]=1.0; + bg_param[VS::ENV_BG_PARAM_GLOW]=0.0; for(int i=0;i<VS::ENV_FX_MAX;i++) fx_enabled[i]=false; fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1; + fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE]=1.0; + fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH]=1.0; + fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE]=0; fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0; fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5; fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1; @@ -659,11 +697,8 @@ class RasterizerGLES2 : public Rasterizer { Transform transform; CameraMatrix projection; - Transform custom_transform; - CameraMatrix custom_projection; - - Transform custom_transform2; - CameraMatrix custom_projection2; + Transform custom_transform[4]; + CameraMatrix custom_projection[4]; Vector3 light_vector; Vector3 spot_vector; @@ -675,11 +710,9 @@ class RasterizerGLES2 : public Rasterizer { Vector2 dp; - CameraMatrix shadow_projection; - CameraMatrix shadow_projection2; + CameraMatrix shadow_projection[4]; + float shadow_split[4]; - float shadow_split; - float shadow_split2; ShadowBuffer* near_shadow_buffer; @@ -934,7 +967,7 @@ class RasterizerGLES2 : public Rasterizer { void _setup_light(uint16_t p_light); _FORCE_INLINE_ void _setup_shader_params(const Material *p_material); - bool _setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light); + bool _setup_material(const Geometry *p_geometry, const Material *p_material, bool p_no_const_light, bool p_opaque_pass); void _setup_skeleton(const Skeleton *p_skeleton); @@ -1098,6 +1131,16 @@ class RasterizerGLES2 : public Rasterizer { void _copy_screen_quad(); void _copy_to_texscreen(); + + Vector3 chunk_vertex; + Vector3 chunk_normal; + Plane chunk_tangent; + Color chunk_color; + Vector2 chunk_uv; + Vector2 chunk_uv2; + GLuint tc0_id_cache; + GLuint tc0_idx; + public: /* TEXTURE API */ @@ -1183,6 +1226,9 @@ public: virtual AABB mesh_get_aabb(RID p_mesh) const; + virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); + virtual AABB mesh_get_custom_aabb(RID p_mesh) const; + /* MULTIMESH API */ virtual RID multimesh_create(); @@ -1204,6 +1250,22 @@ public: virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); virtual int multimesh_get_visible_instances(RID p_multimesh) const; + /* IMMEDIATE API */ + + virtual RID immediate_create(); + virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID()); + virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); + virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); + virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); + virtual void immediate_color(RID p_immediate,const Color& p_color); + virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv); + virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv); + virtual void immediate_end(RID p_immediate); + virtual void immediate_clear(RID p_immediate); + virtual AABB immediate_get_aabb(RID p_immediate) const; + virtual void immediate_set_material(RID p_immediate,RID p_material); + virtual RID immediate_get_material(RID p_immediate) const; + /* PARTICLES API */ virtual RID particles_create(); @@ -1363,6 +1425,7 @@ public: virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data); virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data); + virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data); virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data); virtual void end_scene(); @@ -1410,6 +1473,7 @@ public: virtual bool is_texture(const RID& p_rid) const; virtual bool is_material(const RID& p_rid) const; virtual bool is_mesh(const RID& p_rid) const; + virtual bool is_immediate(const RID& p_rid) const; virtual bool is_multimesh(const RID& p_rid) const; virtual bool is_particles(const RID &p_beam) const; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 6dc6259fef..db63c3aeba 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -145,6 +145,12 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } break; case SL::Node::TYPE_VARIABLE: { SL::VariableNode *vnode=(SL::VariableNode*)p_node; + if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) { + + if (vnode->name==vname_vertex && p_assign_left) { + vertex_code_writes_vertex=true; + } + } if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) { if (vnode->name==vname_discard) { @@ -644,5 +650,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_binormal_interp="BINORMAL"; vname_var1_interp="VAR1"; vname_var2_interp="VAR2"; + vname_vertex="VERTEX"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 2f4aa7647e..d683f5b4f3 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -61,6 +61,7 @@ private: StringName vname_binormal_interp; StringName vname_var1_interp; StringName vname_var2_interp; + StringName vname_vertex; Map<StringName,ShaderLanguage::Uniform> *uniforms; diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index d665fddd2c..bcd3e6ad4b 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -315,6 +315,7 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() { for(int i=0;i<cc->custom_defines.size();i++) { strings.push_back(cc->custom_defines[i]); + DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i])); } } @@ -349,9 +350,11 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() { strings.push_back(vertex_code2.get_data()); #ifdef DEBUG_SHADER + + DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data())); for(int i=0;i<strings.size();i++) { - print_line("vert strings "+itos(i)+":"+String(strings[i])); + //print_line("vert strings "+itos(i)+":"+String(strings[i])); } #endif @@ -435,9 +438,10 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() { strings.push_back(fragment_code2.get_data()); #ifdef DEBUG_SHADER + DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data())); for(int i=0;i<strings.size();i++) { - print_line("frag strings "+itos(i)+":"+String(strings[i])); + //print_line("frag strings "+itos(i)+":"+String(strings[i])); } #endif diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 66bdf15db4..f36741d586 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -64,6 +64,9 @@ void main() { highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ); color = vec4(vec3(enc32),1.0); #endif + +// color.rgb*=color.a; gl_FragColor = color; + } diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index d4b0c31b7d..2f1b349618 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -99,6 +99,8 @@ uniform float bloom_treshold; #if defined(BLUR_V_PASS) || defined(BLUR_H_PASS) || defined(USE_HDR_REDUCE) uniform vec2 pixel_size; +uniform float pixel_scale; +uniform float blur_magnitude; #ifdef USE_HDR_STORE @@ -110,6 +112,11 @@ uniform sampler2D source_vd_lum; #endif +//endif +#elif defined(USE_FXAA) + +uniform vec2 pixel_size; + #endif #ifdef USE_ENERGY @@ -118,6 +125,10 @@ uniform highp float energy; #endif +#ifdef USE_CUSTOM_ALPHA +uniform float custom_alpha; +#endif + void main() { @@ -129,6 +140,55 @@ void main() { vec4 color = texture2D( source, uv_interp ); #endif + +#ifdef USE_FXAA + +#define FXAA_REDUCE_MIN (1.0/ 128.0) +#define FXAA_REDUCE_MUL (1.0 / 8.0) +#define FXAA_SPAN_MAX 8.0 + + { + vec3 rgbNW = texture2D(source, uv_interp + vec2(-1.0, -1.0) * pixel_size).xyz; + vec3 rgbNE = texture2D(source, uv_interp + vec2(1.0, -1.0) * pixel_size).xyz; + vec3 rgbSW = texture2D(source, uv_interp + vec2(-1.0, 1.0) * pixel_size).xyz; + vec3 rgbSE = texture2D(source, uv_interp + vec2(1.0, 1.0) * pixel_size).xyz; + vec3 rgbM = color.rgb; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * pixel_size; + + vec3 rgbA = 0.5 * ( + texture2D(source, uv_interp + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(source, uv_interp + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(source, uv_interp + dir * -0.5).xyz + + texture2D(source, uv_interp + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color.rgb = rgbA; + else + color.rgb = rgbB; + } + +#endif //color.rg=uv_interp; #ifdef USE_BCS @@ -141,28 +201,28 @@ void main() { #ifdef BLUR_V_PASS - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)); + color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale); - color*=(1.0/7.0); + color*=(1.0/7.0)*blur_magnitude; #endif #ifdef BLUR_H_PASS - color+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)); + color+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale); + color+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale); - color*=(1.0/7.0); + color*=(1.0/7.0)*blur_magnitude; #endif @@ -195,7 +255,29 @@ void main() { vec4 glow = texture2D( glow_source, uv2_interp ); +#ifdef USE_GLOW_SCREEN + + color.rgb = clamp((color.rgb + glow.rgb) - (color.rgb * glow.rgb), 0.0, 1.0); + +#endif + +#ifdef USE_GLOW_SOFTLIGHT + + { + + glow.rgb = (glow.rgb * 0.5) + 0.5; + color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); + color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); + color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); + } + +#endif + +#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) color.rgb+=glow.rgb; +#endif + + #endif @@ -253,6 +335,9 @@ void main() { color.a=1.0; #endif +#ifdef USE_CUSTOM_ALPHA + color.a=custom_alpha; +#endif gl_FragColor = color; } diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index 9c2fbaee6c..a919e3b1e2 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -140,6 +140,12 @@ varying highp vec4 shadow_coord; uniform highp mat4 shadow_matrix2; varying highp vec4 shadow_coord2; #endif +#ifdef LIGHT_USE_PSSM4 +uniform highp mat4 shadow_matrix3; +varying highp vec4 shadow_coord3; +uniform highp mat4 shadow_matrix4; +varying highp vec4 shadow_coord4; +#endif #endif @@ -290,6 +296,22 @@ VERTEX_SHADER_CODE shadow_coord2.xyz/=shadow_coord2.w; shadow_coord2.y*=0.5; #endif +#ifdef LIGHT_USE_PSSM4 + shadow_coord.x*=0.5; + shadow_coord2.x*=0.5; + + shadow_coord3 = shadow_matrix3 * vec4(vertex_interp,1.0); + shadow_coord3.xyz/=shadow_coord3.w; + shadow_coord3.xy*=vec2(0.5); + shadow_coord3.xy+=vec2(0.5); + + shadow_coord4 = shadow_matrix4 * vec4(vertex_interp,1.0); + shadow_coord4.xyz/=shadow_coord4.w; + shadow_coord4.xy*=vec2(0.5); + shadow_coord4.x+=0.5; + +#endif + #endif #ifdef USE_FOG @@ -364,6 +386,7 @@ VERTEX_SHADER_CODE specular_interp=vec3(0.0); } } + #else #ifdef SHADELESS @@ -428,7 +451,7 @@ varying vec4 var2_interp; #endif #ifdef LIGHT_USE_PSSM -uniform float light_pssm_split; +uniform vec3 light_pssm_split; #endif varying vec3 vertex_interp; @@ -504,6 +527,11 @@ varying highp vec4 shadow_coord; #ifdef LIGHT_USE_PSSM varying highp vec4 shadow_coord2; #endif +#ifdef LIGHT_USE_PSSM4 +varying highp vec4 shadow_coord3; +varying highp vec4 shadow_coord4; +#endif + uniform highp sampler2D shadow_texture; uniform highp vec2 shadow_texel_size; @@ -523,6 +551,29 @@ uniform float shadow_darkening; #ifdef USE_SHADOW_PCF +#ifdef USE_SHADOW_PCF_HQ + + +float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) { + + float avg=(SHADOW_DEPTH(shadow_texture,coord) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x,0.0)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,0.0)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x*2.0,0.0)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x*2.0,0.0)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,shadow_texel_size.y*2.0)) < refdepth ? 0.0 : 1.0); + avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,-shadow_texel_size.y*2.0)) < refdepth ? 0.0 : 1.0); + return avg*(1.0/13.0); +} + +#else + float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) { float avg=(SHADOW_DEPTH(shadow_texture,coord) < refdepth ? 0.0 : 1.0); @@ -530,9 +581,13 @@ float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) { avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,0.0)) < refdepth ? 0.0 : 1.0); avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - return avg*0.2; + return avg*0.2; } +#endif + + + /* 16x averaging @@ -668,21 +723,28 @@ void main() { -#ifdef FRAGMENT_SHADER_CODE_USE_DISCARD - float discard_=0.0; +#if defined(ENABLE_DISCARD) + bool discard_=false; #endif FRAGMENT_SHADER_CODE -#ifdef FRAGMENT_SHADER_CODE_USE_DISCARD - if (discard_>0.0) { +#if defined(ENABLE_DISCARD) + if (discard_) { //easy to eliminate dead code discard; } #endif +#ifdef ENABLE_CLIP_ALPHA + if (diffuse.a<0.99) { + //used for doublepass and shadowmapping + discard; + } +#endif + float shadow_attenuation = 1.0; @@ -697,7 +759,7 @@ FRAGMENT_SHADER_CODE #if 0 highp vec3 splane = vec3(0.0,0.0,0.0); - if (gl_FragCoord.w > light_pssm_split) { + if (gl_FragCoord.w > light_pssm_split.x) { splane = shadow_coord.xyz; splane.y+=1.0; @@ -711,19 +773,56 @@ FRAGMENT_SHADER_CODE /* float sa_a = SAMPLE_SHADOW_TEX(shadow_coord.xy,shadow_coord.z); float sa_b = SAMPLE_SHADOW_TEX(shadow_coord2.xy,shadow_coord2.z); - if (gl_FragCoord.w > light_pssm_split) { + if (gl_FragCoord.w > light_pssm_split.x) { shadow_attenuation=sa_a; } else { shadow_attenuation=sa_b; } */ - if (gl_FragCoord.w > light_pssm_split) { - shadow_attenuation=SAMPLE_SHADOW_TEX(shadow_coord.xy,shadow_coord.z); + vec2 pssm_coord; + float pssm_z; + +#ifdef LIGHT_USE_PSSM4 + + + if (gl_FragCoord.w > light_pssm_split.y) { + + if (gl_FragCoord.w > light_pssm_split.x) { + pssm_coord=shadow_coord.xy; + pssm_z=shadow_coord.z; + + } else { + pssm_coord=shadow_coord2.xy; + pssm_z=shadow_coord2.z; + } + } else { + + + if (gl_FragCoord.w > light_pssm_split.z) { + pssm_coord=shadow_coord3.xy; + pssm_z=shadow_coord3.z; + } else { + pssm_coord=shadow_coord4.xy; + pssm_z=shadow_coord4.z; + } + } + +#else + + if (gl_FragCoord.w > light_pssm_split.x) { + pssm_coord=shadow_coord.xy; + pssm_z=shadow_coord.z; + } else { - shadow_attenuation=SAMPLE_SHADOW_TEX(shadow_coord2.xy,shadow_coord2.z); + pssm_coord=shadow_coord2.xy; + pssm_z=shadow_coord2.z; } +#endif + + //one one sample + shadow_attenuation=SAMPLE_SHADOW_TEX(pssm_coord,pssm_z); #endif @@ -811,7 +910,10 @@ FRAGMENT_SHADER_CODE # if !defined(LIGHT_TYPE_DIRECTIONAL) && !defined(LIGHT_TYPE_OMNI) && !defined (LIGHT_TYPE_SPOT) //none +#ifndef SHADELESS diffuse.rgb=vec3(0.0,0.0,0.0); +#endif + # endif diffuse.rgb+=const_light_mult*emission; @@ -868,6 +970,7 @@ FRAGMENT_SHADER_CODE #ifdef USE_HDR diffuse.rgb*=0.25; #endif + gl_FragColor = diffuse; #endif } |