diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gles2/rasterizer_canvas_gles2.cpp | 569 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_canvas_gles2.h | 17 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.cpp | 201 | ||||
| -rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 29 | ||||
| -rw-r--r-- | drivers/gles2/shaders/SCsub | 2 | ||||
| -rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 381 | ||||
| -rw-r--r-- | drivers/gles2/shaders/canvas_shadow.glsl | 41 | ||||
| -rw-r--r-- | drivers/gles2/shaders/copy.glsl | 2 | ||||
| -rw-r--r-- | drivers/gles2/shaders/cube_to_dp.glsl | 2 | ||||
| -rw-r--r-- | drivers/gles2/shaders/cubemap_filter.glsl | 2 | ||||
| -rw-r--r-- | drivers/gles2/shaders/lens_distorted.glsl | 2 | ||||
| -rw-r--r-- | drivers/gles2/shaders/scene.glsl | 6 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 6 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 4 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 1 | ||||
| -rw-r--r-- | drivers/gles3/shaders/scene.glsl | 2 | ||||
| -rw-r--r-- | drivers/unix/ip_unix.cpp | 8 | ||||
| -rw-r--r-- | drivers/unix/os_unix.cpp | 6 | ||||
| -rw-r--r-- | drivers/unix/os_unix.h | 1 |
19 files changed, 1226 insertions, 56 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index e6be0f57fc..f3fc356879 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -67,6 +67,12 @@ void RasterizerCanvasGLES2::_set_uniforms() { state.canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size); } + + if (state.using_skeleton) { + state.canvas_shader.set_uniform(CanvasShaderGLES2::SKELETON_TRANSFORM, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SKELETON_TEXTURE_SIZE, state.skeleton_texture_size); + } } void RasterizerCanvasGLES2::canvas_begin() { @@ -140,6 +146,7 @@ void RasterizerCanvasGLES2::canvas_end() { } state.using_texture_rect = false; + state.using_skeleton = false; state.using_ninepatch = false; } @@ -186,13 +193,46 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); } - return tex_return; -} + if (p_normal_map == state.current_normal) { + //do none + state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, state.current_normal.is_valid()); + + } else if (p_normal_map.is_valid()) { + + RasterizerStorageGLES2::Texture *normal_map = storage->texture_owner.getornull(p_normal_map); + + if (!normal_map) { + state.current_normal = RID(); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); + glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); + state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false); + + } else { + + normal_map = normal_map->get_ptr(); + + if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies + VisualServerRaster::redraw_request(); + } + + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); + glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); + state.current_normal = p_normal_map; + state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, true); + } + + } else { -void RasterizerCanvasGLES2::_set_texture_rect_mode(bool p_enable, bool p_ninepatch) { + state.current_normal = RID(); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); + glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); + state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false); + } + + return tex_return; } -void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { +void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const float *p_weights, const int *p_bones) { glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); @@ -226,6 +266,22 @@ void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_coun glDisableVertexAttribArray(VS::ARRAY_TEX_UV); } + if (p_weights && p_bones) { + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights); + glEnableVertexAttribArray(VS::ARRAY_WEIGHTS); + glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(float) * 4 * p_vertex_count; + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones); + glEnableVertexAttribArray(VS::ARRAY_BONES); + glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, GL_FALSE, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(int) * 4 * p_vertex_count; + + } else { + glDisableVertexAttribArray(VS::ARRAY_WEIGHTS); + glDisableVertexAttribArray(VS::ARRAY_BONES); + } + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); @@ -334,6 +390,16 @@ void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_v glBindBuffer(GL_ARRAY_BUFFER, 0); } +static const GLenum gl_primitive[] = { + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_LINE_LOOP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN +}; + void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material) { int command_count = p_item->commands.size(); @@ -758,9 +824,190 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); } - _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); + _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1, polygon->weights.ptr(), polygon->bones.ptr()); + } break; + case Item::Command::TYPE_MESH: { + + Item::CommandMesh *mesh = static_cast<Item::CommandMesh *>(command); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + + if (state.canvas_shader.bind()) { + _set_uniforms(); + state.canvas_shader.use_material((void *)p_material); + } + + RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(mesh->texture, mesh->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + } + + RasterizerStorageGLES2::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); + if (mesh_data) { + + for (int j = 0; j < mesh_data->surfaces.size(); j++) { + RasterizerStorageGLES2::Surface *s = mesh_data->surfaces[j]; + // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing + + glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id); + + if (s->index_array_len > 0) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); + } + + for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { + if (s->attribs[i].enabled) { + glEnableVertexAttribArray(i); + glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset); + } else { + glDisableVertexAttribArray(i); + switch (i) { + case VS::ARRAY_NORMAL: { + glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); + } break; + case VS::ARRAY_COLOR: { + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + + } break; + default: {} + } + } + } + + if (s->index_array_len > 0) { + glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); + } else { + glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); + } + } + + for (int i = 1; i < VS::ARRAY_MAX - 1; i++) { + glDisableVertexAttribArray(i); + } + } + } break; + case Item::Command::TYPE_MULTIMESH: { + Item::CommandMultiMesh *mmesh = static_cast<Item::CommandMultiMesh *>(command); + RasterizerStorageGLES2::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); + + if (!multi_mesh) + break; + + RasterizerStorageGLES2::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh); + + if (!mesh_data) + break; + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != VS::MULTIMESH_CUSTOM_DATA_NONE); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCING, true); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + + if (state.canvas_shader.bind()) { + _set_uniforms(); + state.canvas_shader.use_material((void *)p_material); + } + + RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + } + + //reset shader and force rebind + + int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); + + if (amount == -1) { + amount = multi_mesh->size; + } + + int stride = multi_mesh->color_floats + multi_mesh->custom_data_floats + multi_mesh->xform_floats; + + int color_ofs = multi_mesh->xform_floats; + int custom_data_ofs = color_ofs + multi_mesh->color_floats; + + // drawing + + const float *base_buffer = multi_mesh->data.ptr(); + + for (int j = 0; j < mesh_data->surfaces.size(); j++) { + RasterizerStorageGLES2::Surface *s = mesh_data->surfaces[j]; + // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing + + //bind buffers for mesh surface + glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id); + + if (s->index_array_len > 0) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); + } + + for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { + if (s->attribs[i].enabled) { + glEnableVertexAttribArray(i); + glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset); + } else { + glDisableVertexAttribArray(i); + switch (i) { + case VS::ARRAY_NORMAL: { + glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); + } break; + case VS::ARRAY_COLOR: { + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + + } break; + default: {} + } + } + } + + for (int i = 0; i < amount; i++) { + const float *buffer = base_buffer + i * stride; + + { + + glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 0, &buffer[0]); + glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 1, &buffer[4]); + if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) { + glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 2, &buffer[8]); + } else { + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 2, 0.0, 0.0, 1.0, 0.0); + } + } + + if (multi_mesh->color_floats) { + if (multi_mesh->color_format == VS::MULTIMESH_COLOR_8BIT) { + uint8_t *color_data = (uint8_t *)(buffer + color_ofs); + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, color_data[0] / 255.0, color_data[1] / 255.0, color_data[2] / 255.0, color_data[3] / 255.0); + } else { + glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs); + } + } + + if (multi_mesh->custom_data_floats) { + if (multi_mesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { + uint8_t *custom_data = (uint8_t *)(buffer + custom_data_ofs); + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 4, custom_data[0] / 255.0, custom_data[1] / 255.0, custom_data[2] / 255.0, custom_data[3] / 255.0); + } else { + glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 4, buffer + custom_data_ofs); + } + } + + if (s->index_array_len > 0) { + glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); + } else { + glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); + } + } + } + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCE_CUSTOM, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCING, false); + + } break; case Item::Command::TYPE_POLYLINE: { Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(command); @@ -880,6 +1127,8 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons RasterizerStorageGLES2::Shader *shader_cache = NULL; bool rebind_shader = true; + bool prev_use_skeleton = false; + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, false); state.current_tex = RID(); state.current_tex_ptr = NULL; @@ -921,6 +1170,37 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons } } + RasterizerStorageGLES2::Skeleton *skeleton = NULL; + + { + //skeleton handling + if (ci->skeleton.is_valid() && storage->skeleton_owner.owns(ci->skeleton)) { + skeleton = storage->skeleton_owner.get(ci->skeleton); + if (!skeleton->use_2d) { + skeleton = NULL; + } else { + state.skeleton_transform = p_base_transform * skeleton->base_transform_2d; + state.skeleton_transform_inverse = state.skeleton_transform.affine_inverse(); + state.skeleton_texture_size = Vector2(skeleton->size * 2, 0); + } + } + + bool use_skeleton = skeleton != NULL; + if (prev_use_skeleton != use_skeleton) { + rebind_shader = true; + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, use_skeleton); + prev_use_skeleton = use_skeleton; + } + + if (skeleton) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); + state.using_skeleton = true; + } else { + state.using_skeleton = false; + } + } + Item *material_owner = ci->material_owner ? ci->material_owner : ci; RID material = material_owner->material; @@ -1008,7 +1288,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons } int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX; - bool unshaded = (shader_cache && blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX); + bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES2::Shader::CanvasItem::LIGHT_MODE_UNSHADED || (blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX && blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA)); bool reclip = false; if (last_blend_mode != blend_mode) { @@ -1053,10 +1333,164 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons _set_uniforms(); - _canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr); + if (unshaded || (state.uniforms.final_modulate.a > 0.001 && (!shader_cache || shader_cache->canvas_item.light_mode != RasterizerStorageGLES2::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked)) + _canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr); rebind_shader = true; // hacked in for now. + if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) { + + Light *light = p_light; + bool light_used = false; + VS::CanvasLightMode mode = VS::CANVAS_LIGHT_MODE_ADD; + state.uniforms.final_modulate = ci->final_modulate; // remove the canvas modulate + + while (light) { + + if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { + + //intersects this light + + if (!light_used || mode != light->mode) { + + mode = light->mode; + + switch (mode) { + + case VS::CANVAS_LIGHT_MODE_ADD: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + } break; + case VS::CANVAS_LIGHT_MODE_SUB: { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } break; + case VS::CANVAS_LIGHT_MODE_MIX: + case VS::CANVAS_LIGHT_MODE_MASK: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + } break; + } + } + + if (!light_used) { + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, true); + light_used = true; + } + + bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask & light->item_shadow_mask; + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow); + if (has_shadow) { + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0); + switch (light->shadow_filter) { + + case VS::CANVAS_LIGHT_FILTER_NONE: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, true); break; + case VS::CANVAS_LIGHT_FILTER_PCF3: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, true); break; + case VS::CANVAS_LIGHT_FILTER_PCF5: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, true); break; + case VS::CANVAS_LIGHT_FILTER_PCF7: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, true); break; + case VS::CANVAS_LIGHT_FILTER_PCF9: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, true); break; + case VS::CANVAS_LIGHT_FILTER_PCF13: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, true); break; + } + } + + bool light_rebind = state.canvas_shader.bind(); + + if (light_rebind) { + + _set_uniforms(); + } + + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX, light->light_shader_xform); + Transform2D basis_inverse = light->light_shader_xform.affine_inverse().orthonormalized(); + basis_inverse[2] = Vector2(); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX_INVERSE, basis_inverse); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX, light->xform_cache.affine_inverse()); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR, light->color * light->energy); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS, light->light_shader_pos); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT, light->height); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, light->mode == VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0); + + if (has_shadow) { + RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); + glBindTexture(GL_TEXTURE_2D, cls->distance); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX, light->shadow_matrix_cache); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR, light->shadow_color); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE, (1.0 / light->shadow_buffer_size) * (1.0 + light->shadow_smooth)); + if (light->radius_cache == 0) { + state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_GRADIENT, 0.0); + } else { + state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_GRADIENT, light->shadow_gradient_length / (light->radius_cache * 1.1)); + } + state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_DISTANCE_MULT, light->radius_cache * 1.1); + + /*canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR,light->shadow_color);*/ + } + + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture); + if (!t) { + glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); + } else { + t = t->get_ptr(); + + glBindTexture(t->target, t->tex_id); + } + + glActiveTexture(GL_TEXTURE0); + _canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr); //redraw using light + } + + light = light->next_ptr; + } + + if (light_used) { + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, false); + + state.canvas_shader.bind(); + + last_blend_mode = -1; + + /* + //this is set again, so it should not be needed anyway? + state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( + ci->final_modulate.r * p_modulate.r, + ci->final_modulate.g * p_modulate.g, + ci->final_modulate.b * p_modulate.b, + ci->final_modulate.a * p_modulate.a ); + + + state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,state.final_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Transform2D()); + state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE,state.canvas_item_modulate); + + 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); + } + + //@TODO RESET canvas_blend_mode + */ + } + } + if (reclip) { glEnable(GL_SCISSOR_TEST); int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y); @@ -1071,14 +1505,129 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons if (current_clip) { glDisable(GL_SCISSOR_TEST); } + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, false); } void RasterizerCanvasGLES2::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { } void RasterizerCanvasGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) { -} + RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(p_buffer); + ERR_FAIL_COND(!cls); + + glDisable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + state.canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); + state.canvas_shadow_shader.bind(); + + glViewport(0, 0, cls->size, cls->height); + glClearDepth(1.0f); + glClearColor(1, 1, 1, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + VS::CanvasOccluderPolygonCullMode cull = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + + for (int i = 0; i < 4; i++) { + + //make sure it remains orthogonal, makes easy to read angle later + + Transform light; + light.origin[0] = p_light_xform[2][0]; + light.origin[1] = p_light_xform[2][1]; + light.basis[0][0] = p_light_xform[0][0]; + light.basis[0][1] = p_light_xform[1][0]; + light.basis[1][0] = p_light_xform[0][1]; + light.basis[1][1] = p_light_xform[1][1]; + + //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); + + //p_near=1; + CameraMatrix projection; + { + real_t fov = 90; + real_t nearp = p_near; + real_t farp = p_far; + real_t aspect = 1.0; + + real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5)); + real_t ymin = -ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; + + projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); + } + + Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * (i / 4.0))).xform(Vector3(0, 1, 0)); + projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); + + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX, projection); + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX, light); + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::DISTANCE_NORM, 1.0 / p_far); + + if (i == 0) + *p_xform_cache = projection; + + glViewport(0, (cls->height / 4) * i, cls->size, cls->height / 4); + + LightOccluderInstance *instance = p_occluders; + + while (instance) { + + RasterizerStorageGLES2::CanvasOccluder *cc = storage->canvas_occluder_owner.get(instance->polygon_buffer); + if (!cc || cc->len == 0 || !(p_light_mask & instance->light_mask)) { + + instance = instance->next; + continue; + } + + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX, instance->xform_cache); + if (cull != instance->cull_cache) { + + cull = instance->cull_cache; + switch (cull) { + case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { + + glDisable(GL_CULL_FACE); + + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + } break; + } + } + + glBindBuffer(GL_ARRAY_BUFFER, cc->vertex_id); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cc->index_id); + + glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, 0); + + instance = instance->next; + } + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} void RasterizerCanvasGLES2::reset_canvas() { glDisable(GL_CULL_FACE); @@ -1094,7 +1643,7 @@ void RasterizerCanvasGLES2::reset_canvas() { } // bind the back buffer to a texture so shaders can use it. - // It should probably use texture unit -3 (as GLES3 does as well) but currently that's buggy. + // It should probably use texture unit -3 (as GLES2 does as well) but currently that's buggy. // keeping this for now as there's nothing else that uses texture unit 2 // TODO ^ if (storage->frame.current_rt) { @@ -1264,6 +1813,8 @@ void RasterizerCanvasGLES2::initialize() { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } + state.canvas_shadow_shader.init(); + state.canvas_shader.init(); state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true); diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h index cf1c239b6e..b6c11491ff 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.h +++ b/drivers/gles2/rasterizer_canvas_gles2.h @@ -36,12 +36,16 @@ #include "shaders/canvas.glsl.gen.h" #include "shaders/lens_distorted.glsl.gen.h" -// #include "shaders/canvas_shadow.glsl.gen.h" +#include "shaders/canvas_shadow.glsl.gen.h" class RasterizerSceneGLES2; class RasterizerCanvasGLES2 : public RasterizerCanvas { public: + enum { + INSTANCE_ATTRIB_BASE = 8, + }; + struct Uniforms { Transform projection_matrix; @@ -70,11 +74,16 @@ public: Uniforms uniforms; bool canvas_texscreen_used; CanvasShaderGLES2 canvas_shader; - // CanvasShadowShaderGLES3 canvas_shadow_shader; + CanvasShadowShaderGLES2 canvas_shadow_shader; LensDistortedShaderGLES2 lens_shader; bool using_texture_rect; bool using_ninepatch; + bool using_skeleton; + + Transform2D skeleton_transform; + Transform2D skeleton_transform_inverse; + Vector2i skeleton_texture_size; RID current_tex; RID current_normal; @@ -99,10 +108,8 @@ public: virtual void canvas_begin(); virtual void canvas_end(); - _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false); - _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); - _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); + _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const float *p_weights = NULL, const int *p_bones = NULL); _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index e68d0f1cc5..30d515cec5 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -56,6 +56,8 @@ GLuint RasterizerStorageGLES2::system_fbo = 0; #define _DEPTH_COMPONENT24_OES 0x81A6 +#define _RED_OES 0x1903 + void RasterizerStorageGLES2::bind_quad_array() const { glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); @@ -1138,6 +1140,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { case VS::SHADER_CANVAS_ITEM: { + p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL; p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX; p_shader->canvas_item.uses_screen_texture = false; @@ -1150,8 +1153,8 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL); shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA); - // shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED); - // shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); + shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED); + shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv; shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv; @@ -2938,9 +2941,9 @@ void RasterizerStorageGLES2::skeleton_allocate(RID p_skeleton, int p_bones, bool glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); #ifdef GLES_OVER_GL - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_bones * 3, 1, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_bones * (skeleton->use_2d ? 2 : 3), 1, 0, GL_RGBA, GL_FLOAT, NULL); #else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_bones * 3, 1, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_bones * (skeleton->use_2d ? 2 : 3), 1, 0, GL_RGBA, GL_FLOAT, NULL); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -3074,6 +3077,11 @@ Transform2D RasterizerStorageGLES2::skeleton_bone_get_transform_2d(RID p_skeleto } void RasterizerStorageGLES2::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + skeleton->base_transform_2d = p_base_transform; } void RasterizerStorageGLES2::_update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size) { @@ -3106,7 +3114,7 @@ void RasterizerStorageGLES2::update_dirty_skeletons() { if (skeleton->size) { glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, skeleton->size * 3, 1, GL_RGBA, GL_FLOAT, skeleton->bone_data.ptr()); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, skeleton->size * (skeleton->use_2d ? 2 : 3), 1, GL_RGBA, GL_FLOAT, skeleton->bone_data.ptr()); } for (Set<RasterizerScene::InstanceBase *>::Element *E = skeleton->instances.front(); E; E = E->next()) { @@ -4096,6 +4104,7 @@ RID RasterizerStorageGLES2::render_target_create() { Texture *t = memnew(Texture); + t->type = VS::TEXTURE_TYPE_2D; t->flags = 0; t->width = 0; t->height = 0; @@ -4193,16 +4202,158 @@ void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, VS::Vie /* CANVAS SHADOW */ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) { - return RID(); + + CanvasLightShadow *cls = memnew(CanvasLightShadow); + if (p_width > config.max_texture_size) + p_width = config.max_texture_size; + + cls->size = p_width; + cls->height = 16; + + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &cls->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + glGenRenderbuffers(1, &cls->depth); + glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, cls->size, cls->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glGenTextures(1, &cls->distance); + glBindTexture(GL_TEXTURE_2D, cls->distance); + if (config.use_rgba_2d_shadows) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } else { +#ifdef GLES_OVER_GL + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, _RED_OES, GL_FLOAT, NULL); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_FLOAT, cls->size, cls->height, 0, _RED_OES, GL_FLOAT, NULL); +#endif + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + //printf("errnum: %x\n",status); + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + memdelete(cls); + ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID()); + } + + return canvas_light_shadow_owner.make_rid(cls); } /* LIGHT SHADOW MAPPING */ RID RasterizerStorageGLES2::canvas_light_occluder_create() { - return RID(); + + CanvasOccluder *co = memnew(CanvasOccluder); + co->index_id = 0; + co->vertex_id = 0; + co->len = 0; + + return canvas_occluder_owner.make_rid(co); } void RasterizerStorageGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) { + + CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!co); + + co->lines = p_lines; + + if (p_lines.size() != co->len) { + + if (co->index_id) + glDeleteBuffers(1, &co->index_id); + if (co->vertex_id) + glDeleteBuffers(1, &co->vertex_id); + + co->index_id = 0; + co->vertex_id = 0; + co->len = 0; + } + + if (p_lines.size()) { + + PoolVector<float> geometry; + PoolVector<uint16_t> indices; + int lc = p_lines.size(); + + geometry.resize(lc * 6); + indices.resize(lc * 3); + + PoolVector<float>::Write vw = geometry.write(); + PoolVector<uint16_t>::Write iw = indices.write(); + + PoolVector<Vector2>::Read lr = p_lines.read(); + + const int POLY_HEIGHT = 16384; + + for (int i = 0; i < lc / 2; i++) { + + vw[i * 12 + 0] = lr[i * 2 + 0].x; + vw[i * 12 + 1] = lr[i * 2 + 0].y; + vw[i * 12 + 2] = POLY_HEIGHT; + + vw[i * 12 + 3] = lr[i * 2 + 1].x; + vw[i * 12 + 4] = lr[i * 2 + 1].y; + vw[i * 12 + 5] = POLY_HEIGHT; + + vw[i * 12 + 6] = lr[i * 2 + 1].x; + vw[i * 12 + 7] = lr[i * 2 + 1].y; + vw[i * 12 + 8] = -POLY_HEIGHT; + + vw[i * 12 + 9] = lr[i * 2 + 0].x; + vw[i * 12 + 10] = lr[i * 2 + 0].y; + vw[i * 12 + 11] = -POLY_HEIGHT; + + iw[i * 6 + 0] = i * 4 + 0; + iw[i * 6 + 1] = i * 4 + 1; + iw[i * 6 + 2] = i * 4 + 2; + + iw[i * 6 + 3] = i * 4 + 2; + iw[i * 6 + 4] = i * 4 + 3; + iw[i * 6 + 5] = i * 4 + 0; + } + + //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush + + if (!co->vertex_id) { + glGenBuffers(1, &co->vertex_id); + glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); + glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW); + } else { + + glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); + glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr()); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + + if (!co->index_id) { + + glGenBuffers(1, &co->index_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW); + } else { + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr()); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind + + co->len = lc; + } } VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const { @@ -4415,6 +4566,30 @@ bool RasterizerStorageGLES2::free(RID p_rid) { lightmap_capture_data_owner.free(p_rid); memdelete(lightmap_capture); return true; + + } else if (canvas_occluder_owner.owns(p_rid)) { + + CanvasOccluder *co = canvas_occluder_owner.get(p_rid); + if (co->index_id) + glDeleteBuffers(1, &co->index_id); + if (co->vertex_id) + glDeleteBuffers(1, &co->vertex_id); + + canvas_occluder_owner.free(p_rid); + memdelete(co); + + return true; + + } else if (canvas_light_shadow_owner.owns(p_rid)) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid); + glDeleteFramebuffers(1, &cls->fbo); + glDeleteRenderbuffers(1, &cls->depth); + glDeleteTextures(1, &cls->distance); + canvas_light_shadow_owner.free(p_rid); + memdelete(cls); + + return true; } else { return false; } @@ -4468,10 +4643,20 @@ void RasterizerStorageGLES2::initialize() { config.keep_original_textures = false; config.shrink_textures_x2 = false; +#ifdef GLES_OVER_GL + config.float_texture_supported = true; + config.s3tc_supported = true; + config.etc1_supported = false; +#else config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float"); config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc"); config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); - +#endif +#ifdef GLES_OVER_GL + config.use_rgba_2d_shadows = false; +#else + config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg")); +#endif frame.count = 0; frame.delta = 0; frame.current_rt = NULL; diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index ec7616b9f3..b7c175e186 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -76,6 +76,8 @@ public: bool keep_original_textures; bool force_vertex_shading; + + bool use_rgba_2d_shadows; } config; struct Resources { @@ -86,6 +88,7 @@ public: GLuint aniso_tex; GLuint radical_inverse_vdc_cache_tex; + bool use_rgba_2d_shadows; GLuint quadie; @@ -261,6 +264,7 @@ public: alloc_width(0), alloc_height(0), format(Image::FORMAT_L8), + type(VS::TEXTURE_TYPE_2D), target(0), data_size(0), total_data_size(0), @@ -400,7 +404,6 @@ public: int blend_mode; - /* enum LightMode { LIGHT_MODE_NORMAL, LIGHT_MODE_UNSHADED, @@ -408,7 +411,6 @@ public: }; int light_mode; - */ bool uses_screen_texture; bool uses_screen_uv; @@ -837,6 +839,8 @@ public: SelfList<Skeleton> update_list; Set<RasterizerScene::InstanceBase *> instances; + Transform2D base_transform_2d; + Skeleton() : use_2d(false), size(0), @@ -1161,10 +1165,31 @@ public: /* CANVAS SHADOW */ + struct CanvasLightShadow : public RID_Data { + + int size; + int height; + GLuint fbo; + GLuint depth; + GLuint distance; //for older devices + }; + + RID_Owner<CanvasLightShadow> canvas_light_shadow_owner; + virtual RID canvas_light_shadow_buffer_create(int p_width); /* LIGHT SHADOW MAPPING */ + struct CanvasOccluder : public RID_Data { + + GLuint vertex_id; // 0 means, unconfigured + GLuint index_id; // 0 means, unconfigured + PoolVector<Vector2> lines; + int len; + }; + + RID_Owner<CanvasOccluder> canvas_occluder_owner; + virtual RID canvas_light_occluder_create(); virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines); diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub index d959d3f740..085c43319c 100644 --- a/drivers/gles2/shaders/SCsub +++ b/drivers/gles2/shaders/SCsub @@ -6,7 +6,7 @@ if 'GLES2_GLSL' in env['BUILDERS']: env.GLES2_GLSL('copy.glsl'); # env.GLES2_GLSL('resolve.glsl'); env.GLES2_GLSL('canvas.glsl'); -# env.GLES2_GLSL('canvas_shadow.glsl'); + env.GLES2_GLSL('canvas_shadow.glsl'); env.GLES2_GLSL('scene.glsl'); env.GLES2_GLSL('cubemap_filter.glsl'); env.GLES2_GLSL('cube_to_dp.glsl'); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 87a615ade1..2292e3e068 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -2,6 +2,7 @@ [vertex] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -11,12 +12,40 @@ precision mediump int; uniform highp mat4 projection_matrix; /* clang-format on */ + +#include "stdlib.glsl" + uniform highp mat4 modelview_matrix; uniform highp mat4 extra_matrix; attribute highp vec2 vertex; // attrib:0 attribute vec4 color_attrib; // attrib:3 attribute vec2 uv_attrib; // attrib:4 +#ifdef USE_SKELETON +attribute highp vec4 bone_indices; // attrib:6 +attribute highp vec4 bone_weights; // attrib:7 +#endif + +#ifdef USE_INSTANCING + +attribute highp vec4 instance_xform0; //attrib:8 +attribute highp vec4 instance_xform1; //attrib:9 +attribute highp vec4 instance_xform2; //attrib:10 +attribute highp vec4 instance_color; //attrib:11 + +#ifdef USE_INSTANCE_CUSTOM +attribute highp vec4 instance_custom_data; //attrib:12 +#endif + +#endif + +#ifdef USE_SKELETON +uniform highp sampler2D skeleton_texture; // texunit:-3 +uniform highp ivec2 skeleton_texture_size; +uniform highp mat4 skeleton_transform; +uniform highp mat4 skeleton_transform_inverse; +#endif + varying vec2 uv_interp; varying vec4 color_interp; @@ -31,6 +60,35 @@ uniform vec4 src_rect; uniform highp float time; +#ifdef USE_LIGHTING + +// light matrices +uniform highp mat4 light_matrix; +uniform highp mat4 light_matrix_inverse; +uniform highp mat4 light_local_matrix; +uniform highp mat4 shadow_matrix; +uniform highp vec4 light_color; +uniform highp vec4 light_shadow_color; +uniform highp vec2 light_pos; +uniform highp float shadowpixel_size; +uniform highp float shadow_gradient; +uniform highp float light_height; +uniform highp float light_outside_alpha; +uniform highp float shadow_distance_mult; + +varying vec4 light_uv_interp; +varying vec2 transformed_light_uv; +varying vec4 local_rot; + +#ifdef USE_SHADOWS +varying highp vec2 pos; +#endif + +const bool at_light_pass = true; +#else +const bool at_light_pass = false; +#endif + /* clang-format off */ VERTEX_SHADER_GLOBALS @@ -50,6 +108,16 @@ void main() { vec4 color = color_attrib; +#ifdef USE_INSTANCING + mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0))); + color *= instance_color; + vec4 instance_custom = instance_custom_data; + +#else + mat4 extra_matrix_instance = extra_matrix; + vec4 instance_custom = vec4(0.0); +#endif + #ifdef USE_TEXTURE_RECT if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z @@ -73,8 +141,6 @@ void main() { vec4 outvec = vec4(vertex.xy, 0.0, 1.0); uv_interp = uv_attrib; - - #endif { @@ -87,7 +153,7 @@ VERTEX_SHADER_CODE } #if !defined(SKIP_TRANSFORM_USED) - outvec = extra_matrix * outvec; + outvec = extra_matrix_instance * outvec; outvec = modelview_matrix * outvec; #endif @@ -97,13 +163,63 @@ VERTEX_SHADER_CODE outvec.xy = floor(outvec + 0.5).xy; #endif +#ifdef USE_SKELETON + + // look up transform from the "pose texture" + if (bone_weights != vec4(0.0)) { + + highp mat4 bone_transform = mat4(0.0); + + for (int i = 0; i < 4; i++) { + ivec2 tex_ofs = ivec2(int(bone_indices[i]) * 2, 0); + + highp mat4 b = mat4( + texel2DFetch(skeleton_texture, skeleton_texture_size, tex_ofs + ivec2(0, 0)), + texel2DFetch(skeleton_texture, skeleton_texture_size, tex_ofs + ivec2(1, 0)), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); + + bone_transform += b * bone_weights[i]; + } + + mat4 bone_matrix = skeleton_transform * transpose(bone_transform) * skeleton_transform_inverse; + + outvec = bone_matrix * outvec; + + } + + +#endif + + gl_Position = projection_matrix * outvec; + +#ifdef USE_LIGHTING + + light_uv_interp.xy = (light_matrix * outvec).xy; + light_uv_interp.zw = (light_local_matrix * outvec).xy; + + transformed_light_uv = (mat3(light_matrix_inverse) * vec3(light_uv_interp.zw, 0.0)).xy; //for normal mapping + +#ifdef USE_SHADOWS + pos = outvec.xy; +#endif + + local_rot.xy = normalize((modelview_matrix * (extra_matrix_instance * vec4(1.0, 0.0, 0.0, 0.0))).xy); + local_rot.zw = normalize((modelview_matrix * (extra_matrix_instance * vec4(0.0, 1.0, 0.0, 0.0))).xy); +#ifdef USE_TEXTURE_RECT + local_rot.xy *= sign(src_rect.z); + local_rot.zw *= sign(src_rect.w); +#endif + +#endif } /* clang-format off */ [fragment] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -125,7 +241,7 @@ uniform vec4 final_modulate; #ifdef SCREEN_TEXTURE_USED -uniform sampler2D screen_texture; // texunit:-3 +uniform sampler2D screen_texture; // texunit:-4 #endif @@ -135,6 +251,40 @@ uniform vec2 screen_pixel_size; #endif +#ifdef USE_LIGHTING + +uniform highp mat4 light_matrix; +uniform highp mat4 light_local_matrix; +uniform highp mat4 shadow_matrix; +uniform highp vec4 light_color; +uniform highp vec4 light_shadow_color; +uniform highp vec2 light_pos; +uniform highp float shadowpixel_size; +uniform highp float shadow_gradient; +uniform highp float light_height; +uniform highp float light_outside_alpha; +uniform highp float shadow_distance_mult; + +uniform lowp sampler2D light_texture; // texunit:-4 +varying vec4 light_uv_interp; +varying vec2 transformed_light_uv; + +varying vec4 local_rot; + +#ifdef USE_SHADOWS + +uniform highp sampler2D shadow_texture; // texunit:-5 +varying highp vec2 pos; + +#endif + +const bool at_light_pass = true; +#else +const bool at_light_pass = false; +#endif + +uniform bool use_default_normal; + /* clang-format off */ FRAGMENT_SHADER_GLOBALS @@ -153,15 +303,236 @@ void main() { #ifdef SCREEN_UV_USED vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; #endif + + vec3 normal; + +#if defined(NORMAL_USED) + + bool normal_used = true; +#else + bool normal_used = false; +#endif + + if (use_default_normal) { + normal.xy = texture2D(normal_texture, uv_interp).xy * 2.0 - 1.0; + normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); + normal_used = true; + } else { + normal = vec3(0.0, 0.0, 1.0); + } + { + float normal_depth = 1.0; + +#if defined(NORMALMAP_USED) + vec3 normal_map = vec3(0.0, 0.0, 1.0); + normal_used = true; +#endif + /* clang-format off */ FRAGMENT_SHADER_CODE /* clang-format on */ - } +#if defined(NORMALMAP_USED) + normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth); +#endif + } color *= final_modulate; +#ifdef USE_LIGHTING + + vec2 light_vec = transformed_light_uv; + + if (normal_used) { + normal.xy = mat2(local_rot.xy, local_rot.zw) * normal.xy; + } + + float att = 1.0; + + vec2 light_uv = light_uv_interp.xy; + vec4 light = texture2D(light_texture, light_uv); + + if (any(lessThan(light_uv_interp.xy, vec2(0.0, 0.0))) || any(greaterThanEqual(light_uv_interp.xy, vec2(1.0, 1.0)))) { + color.a *= light_outside_alpha; //invisible + + } else { + float real_light_height = light_height; + vec4 real_light_color = light_color; + vec4 real_light_shadow_color = light_shadow_color; + +#if defined(USE_LIGHT_SHADER_CODE) + //light is written by the light shader + light_compute( + light, + light_vec, + real_light_height, + real_light_color, + light_uv, + real_light_shadow_color, + normal, + uv, +#if defined(SCREEN_UV_USED) + screen_uv, +#endif + color); +#endif + + light *= real_light_color; + + if (normal_used) { + vec3 light_normal = normalize(vec3(light_vec, -real_light_height)); + light *= max(dot(-light_normal, normal), 0.0); + } + + color *= light; + +#ifdef USE_SHADOWS + light_vec = light_uv_interp.zw; //for shadows + float angle_to_light = -atan(light_vec.x, light_vec.y); + float PI = 3.14159265358979323846264; + /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays + float ang*/ + + float su, sz; + + float abs_angle = abs(angle_to_light); + vec2 point; + float sh; + if (abs_angle < 45.0 * PI / 180.0) { + point = light_vec; + sh = 0.0 + (1.0 / 8.0); + } else if (abs_angle > 135.0 * PI / 180.0) { + point = -light_vec; + sh = 0.5 + (1.0 / 8.0); + } else if (angle_to_light > 0.0) { + + point = vec2(light_vec.y, -light_vec.x); + sh = 0.25 + (1.0 / 8.0); + } else { + + point = vec2(-light_vec.y, light_vec.x); + sh = 0.75 + (1.0 / 8.0); + } + + highp vec4 s = shadow_matrix * vec4(point, 0.0, 1.0); + s.xyz /= s.w; + su = s.x * 0.5 + 0.5; + sz = s.z * 0.5 + 0.5; + //sz=lightlength(light_vec); + + highp float shadow_attenuation = 0.0; + +#ifdef USE_RGBA_SHADOWS + +#define SHADOW_DEPTH(m_tex, m_uv) dot(texture2D((m_tex), (m_uv)), vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1)) + +#else + +#define SHADOW_DEPTH(m_tex, m_uv) (texture2D((m_tex), (m_uv)).r) + +#endif + +#ifdef SHADOW_USE_GRADIENT + +#define SHADOW_TEST(m_ofs) \ + { \ + highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \ + shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); \ + } + +#else + +#define SHADOW_TEST(m_ofs) \ + { \ + highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \ + shadow_attenuation += step(sz, sd); \ + } + +#endif + +#ifdef SHADOW_FILTER_NEAREST + + SHADOW_TEST(su); + +#endif + +#ifdef SHADOW_FILTER_PCF3 + + SHADOW_TEST(su + shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su - shadowpixel_size); + shadow_attenuation /= 3.0; + +#endif + +#ifdef SHADOW_FILTER_PCF5 + + SHADOW_TEST(su + shadowpixel_size * 2.0); + SHADOW_TEST(su + shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su - shadowpixel_size); + SHADOW_TEST(su - shadowpixel_size * 2.0); + shadow_attenuation /= 5.0; + +#endif + +#ifdef SHADOW_FILTER_PCF7 + + SHADOW_TEST(su + shadowpixel_size * 3.0); + SHADOW_TEST(su + shadowpixel_size * 2.0); + SHADOW_TEST(su + shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su - shadowpixel_size); + SHADOW_TEST(su - shadowpixel_size * 2.0); + SHADOW_TEST(su - shadowpixel_size * 3.0); + shadow_attenuation /= 7.0; + +#endif + +#ifdef SHADOW_FILTER_PCF9 + + SHADOW_TEST(su + shadowpixel_size * 4.0); + SHADOW_TEST(su + shadowpixel_size * 3.0); + SHADOW_TEST(su + shadowpixel_size * 2.0); + SHADOW_TEST(su + shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su - shadowpixel_size); + SHADOW_TEST(su - shadowpixel_size * 2.0); + SHADOW_TEST(su - shadowpixel_size * 3.0); + SHADOW_TEST(su - shadowpixel_size * 4.0); + shadow_attenuation /= 9.0; + +#endif + +#ifdef SHADOW_FILTER_PCF13 + + SHADOW_TEST(su + shadowpixel_size * 6.0); + SHADOW_TEST(su + shadowpixel_size * 5.0); + SHADOW_TEST(su + shadowpixel_size * 4.0); + SHADOW_TEST(su + shadowpixel_size * 3.0); + SHADOW_TEST(su + shadowpixel_size * 2.0); + SHADOW_TEST(su + shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su - shadowpixel_size); + SHADOW_TEST(su - shadowpixel_size * 2.0); + SHADOW_TEST(su - shadowpixel_size * 3.0); + SHADOW_TEST(su - shadowpixel_size * 4.0); + SHADOW_TEST(su - shadowpixel_size * 5.0); + SHADOW_TEST(su - shadowpixel_size * 6.0); + shadow_attenuation /= 13.0; + +#endif + + //color *= shadow_attenuation; + color = mix(real_light_shadow_color, color, shadow_attenuation); +//use shadows +#endif + } + +//use lighting +#endif + gl_FragColor = color; } diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl index e3c8140e31..d39212826e 100644 --- a/drivers/gles2/shaders/canvas_shadow.glsl +++ b/drivers/gles2/shaders/canvas_shadow.glsl @@ -1,15 +1,24 @@ /* clang-format off */ [vertex] +#ifdef USE_GLES_OVER_GL +#define lowp +#define mediump +#define highp +#else +precision highp float; +precision highp int; +#endif + +attribute highp vec3 vertex; // attrib:0 + uniform highp mat4 projection_matrix; /* clang-format on */ uniform highp mat4 light_matrix; uniform highp mat4 world_matrix; uniform highp float distance_norm; -layout(location = 0) in highp vec3 vertex; - -out highp vec4 position_interp; +varying highp vec4 position_interp; void main() { @@ -20,31 +29,29 @@ void main() { /* clang-format off */ [fragment] -in highp vec4 position_interp; -/* clang-format on */ - -#ifdef USE_RGBA_SHADOWS - -layout(location = 0) out lowp vec4 distance_buf; - +#ifdef USE_GLES_OVER_GL +#define lowp +#define mediump +#define highp #else - -layout(location = 0) out highp float distance_buf; - +precision mediump float; +precision mediump int; #endif +varying highp vec4 position_interp; +/* clang-format on */ + void main() { - highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; //bias; + highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias #ifdef USE_RGBA_SHADOWS highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - distance_buf = comp; + gl_FragColor = comp; #else - distance_buf = depth; - + gl_FragColor = vec4(depth); #endif } diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index 97a24212a5..f3c2a7eec4 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -2,6 +2,7 @@ [vertex] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -56,6 +57,7 @@ void main() { #define M_PI 3.14159265359 #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else diff --git a/drivers/gles2/shaders/cube_to_dp.glsl b/drivers/gles2/shaders/cube_to_dp.glsl index 3d24c36336..cb4b3f6dec 100644 --- a/drivers/gles2/shaders/cube_to_dp.glsl +++ b/drivers/gles2/shaders/cube_to_dp.glsl @@ -2,6 +2,7 @@ [vertex] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -25,6 +26,7 @@ void main() { [fragment] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl index b1553c7cd5..06274a7698 100644 --- a/drivers/gles2/shaders/cubemap_filter.glsl +++ b/drivers/gles2/shaders/cubemap_filter.glsl @@ -2,6 +2,7 @@ [vertex] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -32,6 +33,7 @@ void main() { #endif #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else diff --git a/drivers/gles2/shaders/lens_distorted.glsl b/drivers/gles2/shaders/lens_distorted.glsl index efa35adf7d..81898a75a5 100644 --- a/drivers/gles2/shaders/lens_distorted.glsl +++ b/drivers/gles2/shaders/lens_distorted.glsl @@ -2,6 +2,7 @@ [vertex] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -29,6 +30,7 @@ void main() { [fragment] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index aba283970a..5cdf4ff04d 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -2,6 +2,7 @@ [vertex] #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -653,6 +654,7 @@ VERTEX_SHADER_CODE #endif #ifdef USE_GLES_OVER_GL +#define lowp #define mediump #define highp #else @@ -1091,7 +1093,6 @@ void light_compute( inout vec3 diffuse_light, inout vec3 specular_light) { - //this makes lights behave closer to linear, but then addition of lights looks bad //better left disabled @@ -1253,7 +1254,7 @@ LIGHT_SHADER_CODE float YdotH = dot(B, H); float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH, cNdotH); //float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); - float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL)) + float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL); #else float alpha = roughness * roughness; @@ -1914,7 +1915,6 @@ FRAGMENT_SHADER_CODE #ifdef USE_SHADOW { highp vec4 splane = shadow_coord; - splane.xyz /= splane.w; float shadow = sample_shadow(light_shadow_atlas, splane); light_att *= shadow; diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 4166cb8361..8b02458983 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -862,7 +862,11 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); } - int amount = MAX(multi_mesh->size, multi_mesh->visible_instances); + int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); + + if (amount == -1) { + amount = multi_mesh->size; + } for (int j = 0; j < mesh_data->surfaces.size(); j++) { RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 2b038fcc0e..84d3d80e0e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1995,7 +1995,8 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { actions = &shaders.actions_particles; actions->uniforms = &p_shader->uniforms; } break; - case VS::SHADER_MAX: break; // Can't happen, but silences warning + case VS::SHADER_MAX: + break; // Can't happen, but silences warning } Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code); @@ -7019,6 +7020,7 @@ RID RasterizerStorageGLES3::render_target_create() { Texture *t = memnew(Texture); + t->type = VS::TEXTURE_TYPE_2D; t->flags = 0; t->width = 0; t->height = 0; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 958086f6c7..bd234d7fbe 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -291,6 +291,7 @@ public: width(0), height(0), format(Image::FORMAT_L8), + type(VS::TEXTURE_TYPE_2D), target(GL_TEXTURE_2D), data_size(0), compressed(false), diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index ff273e4e9f..8b1f18ccbd 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -2028,7 +2028,7 @@ FRAGMENT_SHADER_CODE //apply fog if (fog_depth_enabled) { - float fog_far = fog_depth_end > 0 ? fog_depth_end : z_far; + float fog_far = fog_depth_end > 0.0 ? fog_depth_end : z_far; float fog_z = smoothstep(fog_depth_begin, fog_far, length(vertex)); diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 949609bb9a..b39be64bef 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -55,10 +55,12 @@ #include <iphlpapi.h> #endif // MINGW hack #endif -#else +#else // UNIX #include <netdb.h> #ifdef ANDROID_ENABLED -#include "platform/android/ifaddrs_android.h" +// We could drop this file once we up our API level to 24, +// where the NDK's ifaddrs.h supports to needed getifaddrs. +#include "thirdparty/misc/ifaddrs-android.h" #else #ifdef __FreeBSD__ #include <sys/types.h> @@ -201,7 +203,7 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { #endif -#else +#else // UNIX void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 279274734f..12a1263042 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -202,6 +202,12 @@ uint64_t OS_Unix::get_system_time_secs() const { return uint64_t(tv_now.tv_sec); } +uint64_t OS_Unix::get_system_time_msecs() const { + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + return uint64_t(tv_now.tv_sec * 1000 + tv_now.tv_usec / 1000); +} + OS::Date OS_Unix::get_date(bool utc) const { time_t t = time(NULL); diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index b702454603..94a8d040cd 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -84,6 +84,7 @@ public: virtual uint64_t get_unix_time() const; virtual uint64_t get_system_time_secs() const; + virtual uint64_t get_system_time_msecs() const; virtual void delay_usec(uint32_t p_usec) const; virtual uint64_t get_ticks_usec() const; |