diff options
Diffstat (limited to 'drivers/gles2/rasterizer_storage_gles2.cpp')
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.cpp | 214 |
1 files changed, 203 insertions, 11 deletions
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index d646500a23..af698f3988 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -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); @@ -965,7 +967,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra // attachements for it, so we can fill them by issuing draw calls. GLuint tmp_fb; - int size = p_radiance_size; + int size = p_radiance_size / 4; //divide by four because its a cubemap (this is an approximation because GLES3 uses a dual paraboloid) int lod = 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()) { @@ -3842,6 +3850,10 @@ RID RasterizerStorageGLES2::particles_get_draw_pass_mesh(RID p_particles, int p_ void RasterizerStorageGLES2::update_particles() { } +bool RasterizerStorageGLES2::particles_is_inactive(RID p_particles) const { + return true; +} + //////// void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { @@ -4092,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; @@ -4189,16 +4202,159 @@ 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 { @@ -4411,6 +4567,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; } @@ -4464,10 +4644,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; @@ -4478,6 +4668,8 @@ void RasterizerStorageGLES2::initialize() { shaders.copy.init(); shaders.cubemap_filter.init(); + bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx.mobile"); + shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::LOW_QUALITY, !ggx_hq); { // quad for copying stuff |