diff options
Diffstat (limited to 'drivers/gles2')
37 files changed, 0 insertions, 23053 deletions
diff --git a/drivers/gles2/SCsub b/drivers/gles2/SCsub deleted file mode 100644 index 987ddcd16e..0000000000 --- a/drivers/gles2/SCsub +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -env.add_source_files(env.drivers_sources, "*.cpp") - -SConscript("shaders/SCsub") diff --git a/drivers/gles2/rasterizer_canvas_base_gles2.cpp b/drivers/gles2/rasterizer_canvas_base_gles2.cpp deleted file mode 100644 index 44eeede757..0000000000 --- a/drivers/gles2/rasterizer_canvas_base_gles2.cpp +++ /dev/null @@ -1,1218 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_base_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_canvas_base_gles2.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/os/os.h" -#include "drivers/gles_common/rasterizer_asserts.h" -#include "rasterizer_scene_gles2.h" - -#ifdef GODOT_3 -#include "core/project_settings.h" -#include "servers/visual/visual_server_raster.h" -#else -#include "core/config/project_settings.h" -#include "servers/rendering/rendering_server_default.h" -#endif - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf -#endif - -RID RasterizerCanvasBaseGLES2::light_internal_create() { - return RID(); -} - -void RasterizerCanvasBaseGLES2::light_internal_update(RID p_rid, Light *p_light) { -} - -void RasterizerCanvasBaseGLES2::light_internal_free(RID p_rid) { -} - -void RasterizerCanvasBaseGLES2::canvas_begin() { - state.using_transparent_rt = false; - - // always start with light_angle unset - state.using_light_angle = false; - state.using_large_vertex = false; - state.using_modulate = false; - - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LIGHT_ANGLE, false); - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_MODULATE, false); - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LARGE_VERTEX, false); - state.canvas_shader.bind(); - - int viewport_x, viewport_y, viewport_width, viewport_height; - - if (storage->frame.current_rt) { - storage->bind_framebuffer(storage->frame.current_rt->fbo); - state.using_transparent_rt = storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]; - - if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { - // set Viewport and Scissor when rendering directly to screen - viewport_width = storage->_dims.rt_width; - viewport_height = storage->_dims.rt_height; - viewport_x = storage->frame.current_rt->x; - // FTODO - // viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y; - viewport_y = storage->frame.current_rt->y; - - // viewport_x = 0; - // viewport_y = 0; - - glScissor(viewport_x, viewport_y, viewport_width, viewport_height); - glViewport(viewport_x, viewport_y, viewport_width, viewport_height); - glEnable(GL_SCISSOR_TEST); - } - } - - // FTODO .. this was commented out to try and get the clear color correct - //#ifdef GODOT3 - // OLD METHOD .. now done by render target rather than frame -#if 0 - if (storage->frame.clear_request) { - glClearColor(storage->frame.clear_request_color.r, - storage->frame.clear_request_color.g, - storage->frame.clear_request_color.b, - state.using_transparent_rt ? storage->frame.clear_request_color.a : 1.0); - glClear(GL_COLOR_BUFFER_BIT); - storage->frame.clear_request = false; - } -#endif - - // NEW METHOD - if (storage->frame.current_rt && storage->frame.current_rt->clear_requested) { - const Color &col = storage->frame.current_rt->clear_color; - glClearColor(col.r, col.g, col.b, col.a); - - // clear EVERYTHING. - // not clearing everything can be devastating on tiled renderers especially, - // because if anything is preserved, often the whole frame buffer needs to be preserved. - // Not sure if GL_ACCUM_BUFFER_BIT is needed or supported in GLES. - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - storage->frame.current_rt->clear_requested = false; - } - - //#endif - - /* - if (storage->frame.current_rt) { - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); - glColorMask(1, 1, 1, 1); - } - */ - - reset_canvas(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - - // set up default uniforms - - Transform3D canvas_transform; - - if (storage->frame.current_rt) { - float csy = 1.0; - // FTODO - // if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_VFLIP]) { - // csy = -1.0; - // } - canvas_transform.translate(-(storage->frame.current_rt->width / 2.0f), -(storage->frame.current_rt->height / 2.0f), 0.0f); - canvas_transform.scale(Vector3(2.0f / storage->frame.current_rt->width, csy * -2.0f / storage->frame.current_rt->height, 1.0f)); - } else { - // FTODO - // Vector2 ssize = OS::get_singleton()->get_window_size(); - Vector2 ssize; - ssize.x = storage->_dims.win_width; - ssize.y = storage->_dims.win_height; - - canvas_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); - canvas_transform.scale(Vector3(2.0f / ssize.width, -2.0f / ssize.height, 1.0f)); - } - - state.uniforms.projection_matrix = canvas_transform; - - state.uniforms.final_modulate = Color(1, 1, 1, 1); - - state.uniforms.modelview_matrix = Transform2D(); - state.uniforms.extra_matrix = Transform2D(); - - _set_uniforms(); - _bind_quad_buffer(); -} - -void RasterizerCanvasBaseGLES2::canvas_end() { - glBindBuffer(GL_ARRAY_BUFFER, 0); - - for (int i = 0; i < GD_VS::ARRAY_MAX; i++) { - glDisableVertexAttribArray(i); - } - - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { - //reset viewport to full window size - // int viewport_width = OS::get_singleton()->get_window_size().width; - // int viewport_height = OS::get_singleton()->get_window_size().height; - int viewport_width = storage->_dims.win_width; - int viewport_height = storage->_dims.win_height; - glViewport(0, 0, viewport_width, viewport_height); - glScissor(0, 0, viewport_width, viewport_height); - } - - state.using_texture_rect = false; - state.using_skeleton = false; - state.using_ninepatch = false; - state.using_transparent_rt = false; -} - -void RasterizerCanvasBaseGLES2::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) { - state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y)); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -} - -void RasterizerCanvasBaseGLES2::_set_texture_rect_mode(bool p_texture_rect, bool p_light_angle, bool p_modulate, bool p_large_vertex) { - // always set this directly (this could be state checked) - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, p_texture_rect); - - if (state.using_light_angle != p_light_angle) { - state.using_light_angle = p_light_angle; - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LIGHT_ANGLE, p_light_angle); - } - - if (state.using_modulate != p_modulate) { - state.using_modulate = p_modulate; - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_MODULATE, p_modulate); - } - - if (state.using_large_vertex != p_large_vertex) { - state.using_large_vertex = p_large_vertex; - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LARGE_VERTEX, p_large_vertex); - } -} - -RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { - RasterizerStorageGLES2::Texture *tex_return = NULL; - - if (p_texture.is_valid()) { - RasterizerStorageGLES2::Texture *texture = storage->texture_owner.getornull(p_texture); - - if (!texture) { - state.current_tex = RID(); - state.current_tex_ptr = NULL; - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - - } else { - if (texture->redraw_if_visible) { - RenderingServerDefault::redraw_request(); - } - - texture = texture->get_ptr(); - - if (texture->render_target) { - texture->render_target->used_in_frame = true; - } - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - - state.current_tex = p_texture; - state.current_tex_ptr = texture; - - // new for Godot 4. Set the texture min mag filter and repeat per item - // we use a wrapper to avoid noop GL state changes - texture->GLSetFilter(GL_TEXTURE_2D, state.current_filter); - - tex_return = texture; - } - } else { - state.current_tex = RID(); - state.current_tex_ptr = NULL; - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - } - - 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 { - if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies - RenderingServerDefault::redraw_request(); - } - - normal_map = normal_map->get_ptr(); - - 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 { - 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 RasterizerCanvasBaseGLES2::draw_window_margins(int *black_margin, RID *black_image) { - return; - - // FTODO - int window_w = storage->_dims.rt_width; - int window_h = storage->_dims.rt_height; - //Vector2 window_size = Vector2(window_w, window_h); - - // int window_h = window_size.height; - // int window_w = window_size.width; - - // glBindFramebuffer(GL_FRAMEBUFFER, storage->system_fbo); - // glViewport(0, 0, window_size.width, window_size.height); - - canvas_begin(); - - if (black_image[SIDE_LEFT].is_valid()) { - _bind_canvas_texture(black_image[SIDE_LEFT], RID()); - Size2 sz(storage->texture_get_width(black_image[SIDE_LEFT]), storage->texture_get_height(black_image[SIDE_LEFT])); - draw_generic_textured_rect(Rect2(0, 0, black_margin[SIDE_LEFT], window_h), - Rect2(0, 0, (float)black_margin[SIDE_LEFT] / sz.x, (float)(window_h) / sz.y)); - } else if (black_margin[SIDE_LEFT]) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(0, 0, black_margin[SIDE_LEFT], window_h), Rect2(0, 0, 1, 1)); - } - - if (black_image[SIDE_RIGHT].is_valid()) { - _bind_canvas_texture(black_image[SIDE_RIGHT], RID()); - Size2 sz(storage->texture_get_width(black_image[SIDE_RIGHT]), storage->texture_get_height(black_image[SIDE_RIGHT])); - draw_generic_textured_rect(Rect2(window_w - black_margin[SIDE_RIGHT], 0, black_margin[SIDE_RIGHT], window_h), - Rect2(0, 0, (float)black_margin[SIDE_RIGHT] / sz.x, (float)window_h / sz.y)); - } else if (black_margin[SIDE_RIGHT]) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(window_w - black_margin[SIDE_RIGHT], 0, black_margin[SIDE_RIGHT], window_h), Rect2(0, 0, 1, 1)); - } - - if (black_image[SIDE_TOP].is_valid()) { - _bind_canvas_texture(black_image[SIDE_TOP], RID()); - - Size2 sz(storage->texture_get_width(black_image[SIDE_TOP]), storage->texture_get_height(black_image[SIDE_TOP])); - draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[SIDE_TOP]), - Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[SIDE_TOP] / sz.y)); - - } else if (black_margin[SIDE_TOP]) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[SIDE_TOP]), Rect2(0, 0, 1, 1)); - } - - if (black_image[SIDE_BOTTOM].is_valid()) { - _bind_canvas_texture(black_image[SIDE_BOTTOM], RID()); - - Size2 sz(storage->texture_get_width(black_image[SIDE_BOTTOM]), storage->texture_get_height(black_image[SIDE_BOTTOM])); - draw_generic_textured_rect(Rect2(0, window_h - black_margin[SIDE_BOTTOM], window_w, black_margin[SIDE_BOTTOM]), - Rect2(0, 0, (float)window_w / sz.x, (float)black_margin[SIDE_BOTTOM] / sz.y)); - - } else if (black_margin[SIDE_BOTTOM]) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(0, window_h - black_margin[SIDE_BOTTOM], window_w, black_margin[SIDE_BOTTOM]), Rect2(0, 0, 1, 1)); - } - - canvas_end(); -} -*/ - -void RasterizerCanvasBaseGLES2::_bind_quad_buffer() { - glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices); - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, NULL); -} - -void RasterizerCanvasBaseGLES2::_set_uniforms() { - state.canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX, state.uniforms.projection_matrix); - state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); - state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, state.uniforms.extra_matrix); - - state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE, state.uniforms.final_modulate); - - state.canvas_shader.set_uniform(CanvasShaderGLES2::TIME, storage->frame.time[0]); - - if (storage->frame.current_rt) { - Vector2 screen_pixel_size; - screen_pixel_size.x = 1.0 / storage->frame.current_rt->width; - screen_pixel_size.y = 1.0 / storage->frame.current_rt->height; - - 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); - } - - if (state.using_light) { - Light *light = state.using_light; - state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX, light->light_shader_xform); - Transform2D basis_inverse = light->light_shader_xform.affine_inverse().orthonormalized(); - basis_inverse.elements[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); - // FTODO - state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS, light->light_shader_xform.elements[2]); - state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT, light->height); - - // FTODO - //state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, light->mode == GD_VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0); - state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, 0.0f); - - if (state.using_shadow) { - // FTODO -#if 0 - 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); -#endif - } - } -} - -void RasterizerCanvasBaseGLES2::reset_canvas() { - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DITHER); - glEnable(GL_BLEND); - - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::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); - } - - // bind the back buffer to a texture so shaders can use it. - // 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) { - // glActiveTexture(GL_TEXTURE0 + 2); - // glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasBaseGLES2::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { -} - -void RasterizerCanvasBaseGLES2::_copy_texscreen(const Rect2 &p_rect) { - state.canvas_texscreen_used = true; - - _copy_screen(p_rect); - - // back to canvas, force rebind - state.using_texture_rect = false; - state.canvas_shader.bind(); - _bind_canvas_texture(state.current_tex, state.current_normal); - _set_uniforms(); -} - -void RasterizerCanvasBaseGLES2::_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); - - uint32_t buffer_ofs = 0; - uint32_t buffer_ofs_after = buffer_ofs + (sizeof(Vector2) * p_vertex_count); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs_after > data.polygon_buffer_size); -#endif - - storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); - buffer_ofs = buffer_ofs_after; - - if (p_singlecolor) { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - Color m = *p_colors; - glVertexAttrib4f(GD_VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - } else { - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttribPointer(GD_VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - } - - if (p_uvs) { - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - } - - if (p_weights && p_bones) { - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_WEIGHTS); - glVertexAttribPointer(GD_VS::ARRAY_WEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_BONES); - glVertexAttribPointer(GD_VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, GL_FALSE, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_WEIGHTS); - glDisableVertexAttribArray(GD_VS::ARRAY_BONES); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); - - if (storage->config.support_32_bits_indices) { //should check for -#ifdef DEBUG_ENABLED - ERR_FAIL_COND((sizeof(int) * p_index_count) > data.polygon_index_buffer_size); -#endif - storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - - glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0); - storage->info.render._2d_draw_call_count++; - } else { -#ifdef DEBUG_ENABLED - ERR_FAIL_COND((sizeof(uint16_t) * p_index_count) > data.polygon_index_buffer_size); -#endif - uint16_t *index16 = (uint16_t *)alloca(sizeof(uint16_t) * p_index_count); - for (int i = 0; i < p_index_count; i++) { - index16[i] = uint16_t(p_indices[i]); - } - storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(uint16_t) * p_index_count, index16, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_SHORT, 0); - storage->info.render._2d_draw_call_count++; - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasBaseGLES2::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - - uint32_t buffer_ofs = 0; - uint32_t buffer_ofs_after = buffer_ofs + (sizeof(Vector2) * p_vertex_count); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs_after > data.polygon_buffer_size); -#endif - storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); - buffer_ofs = buffer_ofs_after; - - if (p_singlecolor) { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - Color m = *p_colors; - glVertexAttrib4f(GD_VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - } else { - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttribPointer(GD_VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - } - - if (p_uvs) { - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - } - - glDrawArrays(p_primitive, 0, p_vertex_count); - storage->info.render._2d_draw_call_count++; - - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasBaseGLES2::_draw_generic_indices(GLuint p_primitive, 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) { - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - - uint32_t buffer_ofs = 0; - uint32_t buffer_ofs_after = buffer_ofs + (sizeof(Vector2) * p_vertex_count); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs_after > data.polygon_buffer_size); -#endif - storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); - buffer_ofs = buffer_ofs_after; - - if (p_singlecolor) { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - Color m = *p_colors; - glVertexAttrib4f(GD_VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - } else { - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttribPointer(GD_VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - } - - if (p_uvs) { - RAST_FAIL_COND(!storage->safe_buffer_sub_data(data.polygon_buffer_size, GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs, buffer_ofs_after)); - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs = buffer_ofs_after; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - } - -#ifdef RASTERIZER_EXTRA_CHECKS - // very slow, do not enable in normal use - for (int n = 0; n < p_index_count; n++) { - RAST_DEV_DEBUG_ASSERT(p_indices[n] < p_vertex_count); - } -#endif - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); - - if (storage->config.support_32_bits_indices) { //should check for -#ifdef DEBUG_ENABLED - ERR_FAIL_COND((sizeof(int) * p_index_count) > data.polygon_index_buffer_size); -#endif - storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0); - storage->info.render._2d_draw_call_count++; - } else { -#ifdef DEBUG_ENABLED - ERR_FAIL_COND((sizeof(uint16_t) * p_index_count) > data.polygon_index_buffer_size); -#endif - uint16_t *index16 = (uint16_t *)alloca(sizeof(uint16_t) * p_index_count); - for (int i = 0; i < p_index_count; i++) { - index16[i] = uint16_t(p_indices[i]); - } - storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(uint16_t) * p_index_count, index16, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_SHORT, 0); - storage->info.render._2d_draw_call_count++; - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasBaseGLES2::_legacy_draw_poly_triangles(Item::CommandPolygon *p_poly, RasterizerStorageGLES2::Material *p_material) { - // return; - - const PolyData &pd = _polydata[p_poly->polygon.polygon_id]; - - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - // FTODO - //RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map); - RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(p_poly->texture, RID()); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); - } - - _draw_polygon(pd.indices.ptr(), pd.indices.size(), pd.points.size(), pd.points.ptr(), pd.uvs.ptr(), pd.colors.ptr(), pd.colors.size() == 1, nullptr, nullptr); - -// _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()); -#ifdef GLES_OVER_GL -#if 0 - if (polygon->antialiased) { - glEnable(GL_LINE_SMOOTH); - if (polygon->antialiasing_use_indices) { - _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); - } else { - _draw_generic(GL_LINE_LOOP, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); - } - glDisable(GL_LINE_SMOOTH); - } -#endif -#endif -} - -void RasterizerCanvasBaseGLES2::_legacy_draw_primitive(Item::CommandPrimitive *p_pr, RasterizerStorageGLES2::Material *p_material) { - // return; - - if (p_pr->point_count != 4) - return; // not sure if supported - - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - _bind_canvas_texture(RID(), RID()); - - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4fv(GD_VS::ARRAY_COLOR, p_pr->colors[0].components); - - state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); - - _draw_gui_primitive(p_pr->point_count, p_pr->points, NULL, NULL); -} - -void RasterizerCanvasBaseGLES2::_legacy_draw_line(Item::CommandPrimitive *p_pr, RasterizerStorageGLES2::Material *p_material) { - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - _bind_canvas_texture(RID(), RID()); - - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4fv(GD_VS::ARRAY_COLOR, p_pr->colors[0].components); - - state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); - -#ifdef GLES_OVER_GL -// if (line->antialiased) -// glEnable(GL_LINE_SMOOTH); -#endif - _draw_gui_primitive(2, p_pr->points, NULL, NULL); - -#ifdef GLES_OVER_GL -// if (line->antialiased) -// glDisable(GL_LINE_SMOOTH); -#endif -} - -void RasterizerCanvasBaseGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs, const float *p_light_angles) { - static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; - - int color_offset = 0; - int uv_offset = 0; - int light_angle_offset = 0; - int stride = 2; - - if (p_colors) { - color_offset = stride; - stride += 4; - } - - if (p_uvs) { - uv_offset = stride; - stride += 2; - } - - if (p_light_angles) { //light_angles - light_angle_offset = stride; - stride += 1; - } - - RAST_DEV_DEBUG_ASSERT(p_points <= 4); - float buffer_data[(2 + 2 + 4 + 1) * 4]; - - for (int i = 0; i < p_points; i++) { - buffer_data[stride * i + 0] = p_vertices[i].x; - buffer_data[stride * i + 1] = p_vertices[i].y; - } - - if (p_colors) { - for (int i = 0; i < p_points; i++) { - buffer_data[stride * i + color_offset + 0] = p_colors[i].r; - buffer_data[stride * i + color_offset + 1] = p_colors[i].g; - buffer_data[stride * i + color_offset + 2] = p_colors[i].b; - buffer_data[stride * i + color_offset + 3] = p_colors[i].a; - } - } - - if (p_uvs) { - for (int i = 0; i < p_points; i++) { - buffer_data[stride * i + uv_offset + 0] = p_uvs[i].x; - buffer_data[stride * i + uv_offset + 1] = p_uvs[i].y; - } - } - - if (p_light_angles) { - for (int i = 0; i < p_points; i++) { - buffer_data[stride * i + light_angle_offset + 0] = p_light_angles[i]; - } - } - - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, p_points * stride * 4 * sizeof(float), buffer_data, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true); - - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL); - - if (p_colors) { - glVertexAttribPointer(GD_VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(color_offset * sizeof(float))); - glEnableVertexAttribArray(GD_VS::ARRAY_COLOR); - } - - if (p_uvs) { - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(uv_offset * sizeof(float))); - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - } - - if (p_light_angles) { - glVertexAttribPointer(GD_VS::ARRAY_TANGENT, 1, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(light_angle_offset * sizeof(float))); - glEnableVertexAttribArray(GD_VS::ARRAY_TANGENT); - } - - glDrawArrays(prim[p_points], 0, p_points); - storage->info.render._2d_draw_call_count++; - - if (p_light_angles) { - // may not be needed - glDisableVertexAttribArray(GD_VS::ARRAY_TANGENT); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasBaseGLES2::_copy_screen(const Rect2 &p_rect) { - if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { - ERR_PRINT_ONCE("Cannot use screen texture copying in render target set to render direct to screen."); - return; - } - - ERR_FAIL_COND_MSG(storage->frame.current_rt->copy_screen_effect.color == 0, "Can't use screen texture copying in a render target configured without copy buffers."); - - glDisable(GL_BLEND); - - Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); - - Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y); - - if (p_rect != Rect2()) { - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true); - } - - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, !state.using_transparent_rt); - - storage->bind_framebuffer(storage->frame.current_rt->copy_screen_effect.fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - - storage->shaders.copy.bind(); - storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section); - - const Vector2 vertpos[4] = { - Vector2(-1, -1), - Vector2(-1, 1), - Vector2(1, 1), - Vector2(1, -1), - }; - - const Vector2 uvpos[4] = { - Vector2(0, 0), - Vector2(0, 1), - Vector2(1, 1), - Vector2(1, 0) - }; - - const int indexpos[6] = { - 0, 1, 2, - 2, 3, 0 - }; - - _draw_polygon(indexpos, 6, 4, vertpos, uvpos, NULL, false); - - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, false); - - storage->bind_framebuffer(storage->frame.current_rt->fbo); - glEnable(GL_BLEND); -} - -void RasterizerCanvasBaseGLES2::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) { -#if 0 - 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); - - GD_VS::CanvasOccluderPolygonCullMode cull = GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; - - for (int i = 0; i < 4; i++) { - //make sure it remains orthogonal, makes easy to read angle later - - Transform3D 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(Transform3D().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.getornull(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); - - GD_VS::CanvasOccluderPolygonCullMode transformed_cull_cache = instance->cull_cache; - - if (transformed_cull_cache != GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED && - (p_light_xform.basis_determinant() * instance->xform_cache.basis_determinant()) < 0) { - transformed_cull_cache = - transformed_cull_cache == GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE ? - GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE : - GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE; - } - - if (cull != transformed_cull_cache) { - cull = transformed_cull_cache; - switch (cull) { - case GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { - glDisable(GL_CULL_FACE); - - } break; - case GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); - } break; - case GD_VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - } break; - } - } - - glBindBuffer(GL_ARRAY_BUFFER, cc->vertex_id); - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glVertexAttribPointer(GD_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); -#endif -} - -void RasterizerCanvasBaseGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) { - Vector2 half_size; - if (storage->frame.current_rt) { - half_size = Vector2(storage->frame.current_rt->width, storage->frame.current_rt->height); - } else { - // half_size = OS::get_singleton()->get_window_size(); - half_size = Vector2(storage->_dims.win_width, storage->_dims.win_height); - } - half_size *= 0.5; - Vector2 offset((p_rect.position.x - half_size.x) / half_size.x, (p_rect.position.y - half_size.y) / half_size.y); - Vector2 scale(p_rect.size.x / half_size.x, p_rect.size.y / half_size.y); - - float aspect_ratio = p_rect.size.x / p_rect.size.y; - - // setup our lens shader - state.lens_shader.bind(); - state.lens_shader.set_uniform(LensDistortedShaderGLES2::OFFSET, offset); - state.lens_shader.set_uniform(LensDistortedShaderGLES2::SCALE, scale); - state.lens_shader.set_uniform(LensDistortedShaderGLES2::K1, p_k1); - state.lens_shader.set_uniform(LensDistortedShaderGLES2::K2, p_k2); - state.lens_shader.set_uniform(LensDistortedShaderGLES2::EYE_CENTER, p_eye_center); - state.lens_shader.set_uniform(LensDistortedShaderGLES2::UPSCALE, p_oversample); - state.lens_shader.set_uniform(LensDistortedShaderGLES2::ASPECT_RATIO, aspect_ratio); - - // bind our quad buffer - _bind_quad_buffer(); - - // and draw - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - // and cleanup - glBindBuffer(GL_ARRAY_BUFFER, 0); - - for (int i = 0; i < GD_VS::ARRAY_MAX; i++) { - glDisableVertexAttribArray(i); - } -} - -void RasterizerCanvasBaseGLES2::initialize() { - bool flag_stream = false; - //flag_stream = GLOBAL_GET("rendering/options/api_usage_legacy/flag_stream"); - if (flag_stream) - _buffer_upload_usage_flag = GL_STREAM_DRAW; - else - _buffer_upload_usage_flag = GL_DYNAMIC_DRAW; - - // quad buffer - { - glGenBuffers(1, &data.canvas_quad_vertices); - glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices); - - const float qv[8] = { - 0, 0, - 0, 1, - 1, 1, - 1, 0 - }; - - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, qv, GL_STATIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - // polygon buffer - { - uint32_t poly_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/canvas_polygon_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/canvas_polygon_buffer_size_kb", PROPERTY_HINT_RANGE, "0,256,1,or_greater")); - poly_size = MAX(poly_size, 128); // minimum 2k, may still see anomalies in editor - poly_size *= 1024; - glGenBuffers(1, &data.polygon_buffer); - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW); - - data.polygon_buffer_size = poly_size; - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - uint32_t index_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", 128); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", PROPERTY_HINT_RANGE, "0,256,1,or_greater")); - index_size = MAX(index_size, 128); - index_size *= 1024; // kb - glGenBuffers(1, &data.polygon_index_buffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - data.polygon_index_buffer_size = index_size; - } - - // ninepatch buffers - { - // array buffer - glGenBuffers(1, &data.ninepatch_vertices); - glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices); - - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, NULL, GL_DYNAMIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // element buffer - glGenBuffers(1, &data.ninepatch_elements); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements); - -#define _EIDX(y, x) (y * 4 + x) - uint8_t elems[3 * 2 * 9] = { - // first row - - _EIDX(0, 0), _EIDX(0, 1), _EIDX(1, 1), - _EIDX(1, 1), _EIDX(1, 0), _EIDX(0, 0), - - _EIDX(0, 1), _EIDX(0, 2), _EIDX(1, 2), - _EIDX(1, 2), _EIDX(1, 1), _EIDX(0, 1), - - _EIDX(0, 2), _EIDX(0, 3), _EIDX(1, 3), - _EIDX(1, 3), _EIDX(1, 2), _EIDX(0, 2), - - // second row - - _EIDX(1, 0), _EIDX(1, 1), _EIDX(2, 1), - _EIDX(2, 1), _EIDX(2, 0), _EIDX(1, 0), - - // the center one would be here, but we'll put it at the end - // so it's easier to disable the center and be able to use - // one draw call for both - - _EIDX(1, 2), _EIDX(1, 3), _EIDX(2, 3), - _EIDX(2, 3), _EIDX(2, 2), _EIDX(1, 2), - - // third row - - _EIDX(2, 0), _EIDX(2, 1), _EIDX(3, 1), - _EIDX(3, 1), _EIDX(3, 0), _EIDX(2, 0), - - _EIDX(2, 1), _EIDX(2, 2), _EIDX(3, 2), - _EIDX(3, 2), _EIDX(3, 1), _EIDX(2, 1), - - _EIDX(2, 2), _EIDX(2, 3), _EIDX(3, 3), - _EIDX(3, 3), _EIDX(3, 2), _EIDX(2, 2), - - // center field - - _EIDX(1, 1), _EIDX(1, 2), _EIDX(2, 2), - _EIDX(2, 2), _EIDX(2, 1), _EIDX(1, 1) - }; -#undef _EIDX - - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elems), elems, GL_STATIC_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - state.canvas_shadow_shader.init(); - - state.canvas_shader.init(); - - _set_texture_rect_mode(true); - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); - - state.canvas_shader.bind(); - - state.lens_shader.init(); - - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false)); - - state.using_light = NULL; - state.using_transparent_rt = false; - state.using_skeleton = false; -} - -RendererCanvasRender::PolygonID RasterizerCanvasBaseGLES2::request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights) { - uint32_t id = _polydata.alloc(); - PolyData &pd = _polydata[id]; - pd.indices = p_indices; - pd.points = p_points; - pd.colors = p_colors; - pd.uvs = p_uvs; - return id; -} -void RasterizerCanvasBaseGLES2::free_polygon(PolygonID p_polygon) { - _polydata.free(p_polygon); -} - -void RasterizerCanvasBaseGLES2::finalize() { -} - -RasterizerCanvasBaseGLES2::RasterizerCanvasBaseGLES2() { -} - -#endif diff --git a/drivers/gles2/rasterizer_canvas_base_gles2.h b/drivers/gles2/rasterizer_canvas_base_gles2.h deleted file mode 100644 index e2b396dca8..0000000000 --- a/drivers/gles2/rasterizer_canvas_base_gles2.h +++ /dev/null @@ -1,176 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_base_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "drivers/gles_common/rasterizer_array.h" -#include "drivers/gles_common/rasterizer_common_stubs.h" -#include "drivers/gles_common/rasterizer_storage_common.h" -#include "drivers/gles_common/rasterizer_version.h" -#include "rasterizer_scene_gles2.h" -#include "rasterizer_storage_gles2.h" -#include "servers/rendering/renderer_compositor.h" - -#include "shaders/canvas.glsl.gen.h" -#include "shaders/canvas_shadow.glsl.gen.h" -#include "shaders/lens_distorted.glsl.gen.h" - -class RasterizerCanvasBaseGLES2 : public StubsCanvas { -public: - enum { - INSTANCE_ATTRIB_BASE = 8, - }; - - struct Uniforms { - Transform3D projection_matrix; - - Transform2D modelview_matrix; - Transform2D extra_matrix; - - Color final_modulate; - - float time; - }; - - struct Data { - GLuint canvas_quad_vertices; - GLuint polygon_buffer; - GLuint polygon_index_buffer; - - uint32_t polygon_buffer_size; - uint32_t polygon_index_buffer_size; - - GLuint ninepatch_vertices; - GLuint ninepatch_elements; - } data; - - struct State { - Uniforms uniforms; - bool canvas_texscreen_used; - CanvasShaderGLES2 canvas_shader; - CanvasShadowShaderGLES2 canvas_shadow_shader; - LensDistortedShaderGLES2 lens_shader; - - bool using_texture_rect; - - bool using_light_angle; - bool using_modulate; - bool using_large_vertex; - - bool using_ninepatch; - bool using_skeleton; - - Transform2D skeleton_transform; - Transform2D skeleton_transform_inverse; - Size2i skeleton_texture_size; - - RID current_tex; - RID current_normal; - RasterizerStorageGLES2::Texture *current_tex_ptr; - - Transform3D vp; - Light *using_light; - bool using_shadow; - bool using_transparent_rt; - - // new for Godot 4.0 - // min mag filter is per item, and repeat - RS::CanvasItemTextureFilter current_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; - RS::CanvasItemTextureRepeat current_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; - } state; - - typedef void Texture; - - RasterizerSceneGLES2 *scene_render; - - RasterizerStorageGLES2 *storage; - - // allow user to choose api usage - GLenum _buffer_upload_usage_flag; - - void _set_uniforms(); - - virtual RID light_internal_create(); - virtual void light_internal_update(RID p_rid, Light *p_light); - virtual void light_internal_free(RID p_rid); - - virtual void canvas_begin(); - virtual void canvas_end(); - -protected: - void _legacy_draw_primitive(Item::CommandPrimitive *p_pr, RasterizerStorageGLES2::Material *p_material); - void _legacy_draw_line(Item::CommandPrimitive *p_pr, RasterizerStorageGLES2::Material *p_material); - void _legacy_draw_poly_triangles(Item::CommandPolygon *p_poly, RasterizerStorageGLES2::Material *p_material); - -public: - void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs, const float *p_light_angles = nullptr); - 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); - 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); - void _draw_generic_indices(GLuint p_primitive, 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 _bind_quad_buffer(); - void _copy_texscreen(const Rect2 &p_rect); - void _copy_screen(const Rect2 &p_rect); - - //virtual void draw_window_margins(int *black_margin, RID *black_image) override; - void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src); - void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); - - virtual void reset_canvas(); - virtual void 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); - virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override; - - RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); - void _set_texture_rect_mode(bool p_texture_rect, bool p_light_angle = false, bool p_modulate = false, bool p_large_vertex = false); - - // NEW API - struct PolyData { - LocalVector<int> indices; - LocalVector<Point2> points; - LocalVector<Color> colors; - LocalVector<Point2> uvs; - }; - - RendererCanvasRender::PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override; - void free_polygon(PolygonID p_polygon) override; - - RasterizerPooledIndirectList<PolyData> _polydata; - - ////////////////////// - void initialize(); - void finalize(); - - RasterizerCanvasBaseGLES2(); -}; - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp deleted file mode 100644 index ef4159563f..0000000000 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ /dev/null @@ -1,2393 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_canvas_gles2.h" -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/os/os.h" -#include "drivers/gles_common/rasterizer_asserts.h" -#include "rasterizer_scene_gles2.h" -#include "rasterizer_storage_gles2.h" - -#ifdef GODOT_4 -#include "core/config/project_settings.h" -#include "servers/rendering/rendering_server_default.h" -#else -#include "core/project_settings.h" -#include "servers/visual/visual_server_raster.h" -#endif - -//static const GLenum gl_primitive[] = { -// GL_POINTS, -// GL_LINES, -// GL_LINE_STRIP, -// GL_LINE_LOOP, -// GL_TRIANGLES, -// GL_TRIANGLE_STRIP, -// GL_TRIANGLE_FAN -//}; - -#if 0 -void RasterizerCanvasGLES2::_batch_upload_buffers() { - // noop? - if (!bdata.vertices.size()) - return; - - glBindBuffer(GL_ARRAY_BUFFER, bdata.gl_vertex_buffer); - - // usage flag is a project setting - GLenum buffer_usage_flag = GL_DYNAMIC_DRAW; - if (bdata.buffer_mode_batch_upload_flag_stream) { - buffer_usage_flag = GL_STREAM_DRAW; - } - - // orphan the old (for now) - if (bdata.buffer_mode_batch_upload_send_null) { - glBufferData(GL_ARRAY_BUFFER, 0, 0, buffer_usage_flag); // GL_DYNAMIC_DRAW); - } - - switch (bdata.fvf) { - case RasterizerStorageCommon::FVF_UNBATCHED: // should not happen - break; - case RasterizerStorageCommon::FVF_REGULAR: // no change - glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertex) * bdata.vertices.size(), bdata.vertices.get_data(), buffer_usage_flag); - break; - case RasterizerStorageCommon::FVF_COLOR: - glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexColored) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag); - break; - case RasterizerStorageCommon::FVF_LIGHT_ANGLE: - glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLightAngled) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag); - break; - case RasterizerStorageCommon::FVF_MODULATED: - glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexModulated) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag); - break; - case RasterizerStorageCommon::FVF_LARGE: - glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLarge) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag); - break; - } - - // might not be necessary - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasGLES2::_batch_render_lines(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material, bool p_anti_alias) { - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - _bind_canvas_texture(RID(), RID()); - - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4fv(GD_VS::ARRAY_COLOR, (float *)&p_batch.color); - -#ifdef GLES_OVER_GL - if (p_anti_alias) - glEnable(GL_LINE_SMOOTH); -#endif - - int sizeof_vert = sizeof(BatchVertex); - - // bind the index and vertex buffer - glBindBuffer(GL_ARRAY_BUFFER, bdata.gl_vertex_buffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bdata.gl_index_buffer); - - uint64_t pointer = 0; - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof_vert, (const void *)pointer); - - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - - int64_t offset = p_batch.first_vert; // 6 inds per quad at 2 bytes each - - int num_elements = p_batch.num_commands * 2; - glDrawArrays(GL_LINES, offset, num_elements); - - storage->info.render._2d_draw_call_count++; - - // may not be necessary .. state change optimization still TODO - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - -#ifdef GLES_OVER_GL - if (p_anti_alias) - glDisable(GL_LINE_SMOOTH); -#endif -} - -void RasterizerCanvasGLES2::_batch_render_generic(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material) { - ERR_FAIL_COND(p_batch.num_commands <= 0); - - const bool &use_light_angles = bdata.use_light_angles; - const bool &use_modulate = bdata.use_modulate; - const bool &use_large_verts = bdata.use_large_verts; - const bool &colored_verts = bdata.use_colored_vertices | use_light_angles | use_modulate | use_large_verts; - - int sizeof_vert; - - switch (bdata.fvf) { - default: - sizeof_vert = 0; // prevent compiler warning - this should never happen - break; - case RasterizerStorageCommon::FVF_UNBATCHED: { - sizeof_vert = 0; // prevent compiler warning - this should never happen - return; - } break; - case RasterizerStorageCommon::FVF_REGULAR: // no change - sizeof_vert = sizeof(BatchVertex); - break; - case RasterizerStorageCommon::FVF_COLOR: - sizeof_vert = sizeof(BatchVertexColored); - break; - case RasterizerStorageCommon::FVF_LIGHT_ANGLE: - sizeof_vert = sizeof(BatchVertexLightAngled); - break; - case RasterizerStorageCommon::FVF_MODULATED: - sizeof_vert = sizeof(BatchVertexModulated); - break; - case RasterizerStorageCommon::FVF_LARGE: - sizeof_vert = sizeof(BatchVertexLarge); - break; - } - - // make sure to set all conditionals BEFORE binding the shader - _set_texture_rect_mode(false, use_light_angles, use_modulate, use_large_verts); - - // batch tex - const BatchTex &tex = bdata.batch_textures[p_batch.batch_texture_id]; - //VSG::rasterizer->gl_check_for_error(); - - // force repeat is set if non power of 2 texture, and repeat is needed if hardware doesn't support npot - if (tex.tile_mode == BatchTex::TILE_FORCE_REPEAT) { - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_FORCE_REPEAT, true); - } - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - _bind_canvas_texture(tex.RID_texture, tex.RID_normal); - - // bind the index and vertex buffer - glBindBuffer(GL_ARRAY_BUFFER, bdata.gl_vertex_buffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bdata.gl_index_buffer); - - uint64_t pointer = 0; - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof_vert, (const void *)pointer); - - // always send UVs, even within a texture specified because a shader can still use UVs - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (2 * 4))); - - // color - if (!colored_verts) { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4fv(GD_VS::ARRAY_COLOR, p_batch.color.get_data()); - } else { - glEnableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttribPointer(GD_VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (4 * 4))); - } - - if (use_light_angles) { - glEnableVertexAttribArray(GD_VS::ARRAY_TANGENT); - glVertexAttribPointer(GD_VS::ARRAY_TANGENT, 1, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (8 * 4))); - } - - if (use_modulate) { - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV2); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV2, 4, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (9 * 4))); - } - - if (use_large_verts) { - glEnableVertexAttribArray(GD_VS::ARRAY_BONES); - glVertexAttribPointer(GD_VS::ARRAY_BONES, 2, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (13 * 4))); - glEnableVertexAttribArray(GD_VS::ARRAY_WEIGHTS); - glVertexAttribPointer(GD_VS::ARRAY_WEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (15 * 4))); - } - - // We only want to set the GL wrapping mode if the texture is not already tiled (i.e. set in Import). - // This is an optimization left over from the legacy renderer. - // If we DID set tiling in the API, and reverted to clamped, then the next draw using this texture - // may use clamped mode incorrectly. - bool tex_is_already_tiled = tex.flags & RasterizerStorageGLES2::TEXTURE_FLAG_REPEAT; - - if (tex.tile_mode == BatchTex::TILE_NORMAL) { - // if the texture is imported as tiled, no need to set GL state, as it will already be bound with repeat - if (!tex_is_already_tiled) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - } - - // we need to convert explicitly from pod Vec2 to Vector2 ... - // could use a cast but this might be unsafe in future - Vector2 tps; - tex.tex_pixel_size.to(tps); - state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, tps); - - switch (p_batch.type) { - default: { - // prevent compiler warning - } break; - case RasterizerStorageCommon::BT_RECT: { - int64_t offset = p_batch.first_vert * 3; - - int num_elements = p_batch.num_commands * 6; - glDrawElements(GL_TRIANGLES, num_elements, GL_UNSIGNED_SHORT, (void *)offset); - } break; - case RasterizerStorageCommon::BT_POLY: { - int64_t offset = p_batch.first_vert; - - int num_elements = p_batch.num_commands; - glDrawArrays(GL_TRIANGLES, offset, num_elements); - } break; - } - - storage->info.render._2d_draw_call_count++; - - switch (tex.tile_mode) { - case BatchTex::TILE_FORCE_REPEAT: { - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_FORCE_REPEAT, false); - } break; - case BatchTex::TILE_NORMAL: { - // if the texture is imported as tiled, no need to revert GL state - if (!tex_is_already_tiled) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - } break; - default: { - } break; - } - - // could these have ifs? - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glDisableVertexAttribArray(GD_VS::ARRAY_TANGENT); - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV2); - glDisableVertexAttribArray(GD_VS::ARRAY_BONES); - glDisableVertexAttribArray(GD_VS::ARRAY_WEIGHTS); - - // may not be necessary .. state change optimization still TODO - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} -#endif -void RasterizerCanvasGLES2::render_batches(Item::Command *const *p_commands, Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material) { - int num_batches = bdata.batches.size(); - - for (int batch_num = 0; batch_num < num_batches; batch_num++) { - const Batch &batch = bdata.batches[batch_num]; - - switch (batch.type) { - case RasterizerStorageCommon::BT_RECT: { - //_batch_render_generic(batch, p_material); - } break; - case RasterizerStorageCommon::BT_POLY: { - //_batch_render_generic(batch, p_material); - } break; - case RasterizerStorageCommon::BT_LINE: { - //_batch_render_lines(batch, p_material, false); - } break; - case RasterizerStorageCommon::BT_LINE_AA: { - //_batch_render_lines(batch, p_material, true); - } break; - default: { - int end_command = batch.first_command + batch.num_commands; - - for (int i = batch.first_command; i < end_command; i++) { - Item::Command *command = p_commands[i]; - - switch (command->type) { -#if 0 - case Item::Command::TYPE_LINE: { - Item::CommandLine *line = static_cast<Item::CommandLine *>(command); - - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - _bind_canvas_texture(RID(), RID()); - - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4fv(GD_VS::ARRAY_COLOR, line->color.components); - - state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); - - if (line->width <= 1) { - Vector2 verts[2] = { - Vector2(line->from.x, line->from.y), - Vector2(line->to.x, line->to.y) - }; - -#ifdef GLES_OVER_GL - if (line->antialiased) - glEnable(GL_LINE_SMOOTH); -#endif - _draw_gui_primitive(2, verts, NULL, NULL); - -#ifdef GLES_OVER_GL - if (line->antialiased) - glDisable(GL_LINE_SMOOTH); -#endif - } else { - Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5; - - Vector2 verts[4] = { - line->from - t, - line->from + t, - line->to + t, - line->to - t - }; - - _draw_gui_primitive(4, verts, NULL, NULL); -#ifdef GLES_OVER_GL - if (line->antialiased) { - glEnable(GL_LINE_SMOOTH); - for (int j = 0; j < 4; j++) { - Vector2 vertsl[2] = { - verts[j], - verts[(j + 1) % 4], - }; - _draw_gui_primitive(2, vertsl, NULL, NULL); - } - glDisable(GL_LINE_SMOOTH); - } -#endif - } - } break; -#endif - case Item::Command::TYPE_PRIMITIVE: { - Item::CommandPrimitive *pr = static_cast<Item::CommandPrimitive *>(command); - - switch (pr->point_count) { - case 2: { - _legacy_draw_line(pr, p_material); - } break; - default: { - _legacy_draw_primitive(pr, p_material); - } break; - } - - } break; - - case Item::Command::TYPE_RECT: { - Item::CommandRect *r = static_cast<Item::CommandRect *>(command); - - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4fv(GD_VS::ARRAY_COLOR, r->modulate.components); - - bool can_tile = true; - - // we will take account of render target textures which need to be drawn upside down - // quirk of opengl - bool upside_down = r->flags & CANVAS_RECT_FLIP_V; - - // very inefficient, improve this - if (r->texture.is_valid()) { - RasterizerStorageGLES2::Texture *texture = storage->texture_owner.getornull(r->texture); - - if (texture) { - if (texture->is_upside_down()) - upside_down = true; - } - } - - if (r->texture.is_valid() && r->flags & CANVAS_RECT_TILE && !storage->config.support_npot_repeat_mipmap) { - // workaround for when setting tiling does not work due to hardware limitation - - RasterizerStorageGLES2::Texture *texture = storage->texture_owner.getornull(r->texture); - - if (texture) { - texture = texture->get_ptr(); - - if (next_power_of_2(texture->alloc_width) != (unsigned int)texture->alloc_width && next_power_of_2(texture->alloc_height) != (unsigned int)texture->alloc_height) { - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_FORCE_REPEAT, true); - can_tile = false; - } - } - } - - // On some widespread Nvidia cards, the normal draw method can produce some - // flickering in draw_rect and especially TileMap rendering (tiles randomly flicker). - // See GH-9913. - // To work it around, we use a simpler draw method which does not flicker, but gives - // a non negligible performance hit, so it's opt-in (GH-24466). - if (use_nvidia_rect_workaround) { - // are we using normal maps, if so we want to use light angle - bool send_light_angles = false; - - // only need to use light angles when normal mapping - // otherwise we can use the default shader - if (state.current_normal != RID()) { - send_light_angles = true; - } - - _set_texture_rect_mode(false, send_light_angles); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - Vector2 points[4] = { - r->rect.position, - r->rect.position + Vector2(r->rect.size.x, 0.0), - r->rect.position + r->rect.size, - r->rect.position + Vector2(0.0, r->rect.size.y), - }; - - if (r->rect.size.x < 0) { - SWAP(points[0], points[1]); - SWAP(points[2], points[3]); - } - if (r->rect.size.y < 0) { - SWAP(points[0], points[3]); - SWAP(points[1], points[2]); - } - - // FTODO - //RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(r->texture, r->normal_map); - RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(r->texture, RID()); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - - Rect2 src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1); - - Vector2 uvs[4] = { - src_rect.position, - src_rect.position + Vector2(src_rect.size.x, 0.0), - src_rect.position + src_rect.size, - src_rect.position + Vector2(0.0, src_rect.size.y), - }; - - // for encoding in light angle - bool flip_h = false; - bool flip_v = false; - - if (r->flags & CANVAS_RECT_TRANSPOSE) { - SWAP(uvs[1], uvs[3]); - } - - if (r->flags & CANVAS_RECT_FLIP_H) { - SWAP(uvs[0], uvs[1]); - SWAP(uvs[2], uvs[3]); - flip_h = true; - flip_v = !flip_v; - } - if (upside_down) { - SWAP(uvs[0], uvs[3]); - SWAP(uvs[1], uvs[2]); - flip_v = !flip_v; - } - - state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); - - bool untile = false; - - if (can_tile && r->flags & CANVAS_RECT_TILE && !(texture->flags & RasterizerStorageGLES2::TEXTURE_FLAG_REPEAT)) { - texture->GLSetRepeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - untile = true; - } - - if (send_light_angles) { - // for single rects, there is no need to fully utilize the light angle, - // we only need it to encode flips (horz and vert). But the shader can be reused with - // batching in which case the angle encodes the transform as well as - // the flips. - // Note transpose is NYI. I don't think it worked either with the non-nvidia method. - - // if horizontal flip, angle is 180 - float angle = 0.0f; - if (flip_h) - angle = Math_PI; - - // add 1 (to take care of zero floating point error with sign) - angle += 1.0f; - - // flip if necessary - if (flip_v) - angle *= -1.0f; - - // light angle must be sent for each vert, instead as a single uniform in the uniform draw method - // this has the benefit of enabling batching with light angles. - float light_angles[4] = { angle, angle, angle, angle }; - - _draw_gui_primitive(4, points, NULL, uvs, light_angles); - } else { - _draw_gui_primitive(4, points, NULL, uvs); - } - - if (untile) { - texture->GLSetRepeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } - } else { - static const Vector2 uvs[4] = { - Vector2(0.0, 0.0), - Vector2(0.0, 1.0), - Vector2(1.0, 1.0), - Vector2(1.0, 0.0), - }; - - state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, Vector2()); - _draw_gui_primitive(4, points, NULL, uvs); - } - - } else { - // This branch is better for performance, but can produce flicker on Nvidia, see above comment. - _bind_quad_buffer(); - - _set_texture_rect_mode(true); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - // FTODO - //RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map); - RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, RID()); - - if (!tex) { - Rect2 dst_rect = Rect2(r->rect.position, r->rect.size); - - if (dst_rect.size.width < 0) { - dst_rect.position.x += dst_rect.size.width; - dst_rect.size.width *= -1; - } - if (dst_rect.size.height < 0) { - dst_rect.position.y += dst_rect.size.height; - dst_rect.size.height *= -1; - } - - state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(0, 0, 1, 1)); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - storage->info.render._2d_draw_call_count++; - } else { - bool untile = false; - - if (can_tile && r->flags & CANVAS_RECT_TILE && !(tex->flags & RasterizerStorageGLES2::TEXTURE_FLAG_REPEAT)) { - tex->GLSetRepeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - untile = true; - } - - Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height); - Rect2 src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1); - - Rect2 dst_rect = Rect2(r->rect.position, r->rect.size); - - if (dst_rect.size.width < 0) { - dst_rect.position.x += dst_rect.size.width; - dst_rect.size.width *= -1; - } - if (dst_rect.size.height < 0) { - dst_rect.position.y += dst_rect.size.height; - dst_rect.size.height *= -1; - } - - if (r->flags & CANVAS_RECT_FLIP_H) { - src_rect.size.x *= -1; - } - - if (upside_down) { - src_rect.size.y *= -1; - } - - if (r->flags & CANVAS_RECT_TRANSPOSE) { - dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform - } - - state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); - - state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y)); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - storage->info.render._2d_draw_call_count++; - - if (untile) { - tex->GLSetRepeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_FORCE_REPEAT, false); - - } break; - case Item::Command::TYPE_NINEPATCH: { - Item::CommandNinePatch *np = static_cast<Item::CommandNinePatch *>(command); - - _set_texture_rect_mode(false); - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - glVertexAttrib4fv(GD_VS::ARRAY_COLOR, np->color.components); - - // FTODO - //RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(np->texture, np->normal_map); - RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(np->texture, RID()); - - if (!tex) { - // FIXME: Handle textureless ninepatch gracefully - WARN_PRINT("NinePatch without texture not supported yet in GLES2 backend, skipping."); - continue; - } - if (tex->width == 0 || tex->height == 0) { - WARN_PRINT("Cannot set empty texture to NinePatch."); - continue; - } - - Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height); - - // state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); - state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); - - Rect2 source = np->source; - if (source.size.x == 0 && source.size.y == 0) { - source.size.x = tex->width; - source.size.y = tex->height; - } - - float screen_scale = 1.0; - - if ((bdata.settings_ninepatch_mode == 1) && (source.size.x != 0) && (source.size.y != 0)) { - screen_scale = MIN(np->rect.size.x / source.size.x, np->rect.size.y / source.size.y); - screen_scale = MIN(1.0, screen_scale); - } - - // prepare vertex buffer - - // this buffer contains [ POS POS UV UV ] * - - float buffer[16 * 2 + 16 * 2]; - - { - // first row - - buffer[(0 * 4 * 4) + 0] = np->rect.position.x; - buffer[(0 * 4 * 4) + 1] = np->rect.position.y; - - buffer[(0 * 4 * 4) + 2] = source.position.x * texpixel_size.x; - buffer[(0 * 4 * 4) + 3] = source.position.y * texpixel_size.y; - - buffer[(0 * 4 * 4) + 4] = np->rect.position.x + np->margin[SIDE_LEFT] * screen_scale; - buffer[(0 * 4 * 4) + 5] = np->rect.position.y; - - buffer[(0 * 4 * 4) + 6] = (source.position.x + np->margin[SIDE_LEFT]) * texpixel_size.x; - buffer[(0 * 4 * 4) + 7] = source.position.y * texpixel_size.y; - - buffer[(0 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[SIDE_RIGHT] * screen_scale; - buffer[(0 * 4 * 4) + 9] = np->rect.position.y; - - buffer[(0 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[SIDE_RIGHT]) * texpixel_size.x; - buffer[(0 * 4 * 4) + 11] = source.position.y * texpixel_size.y; - - buffer[(0 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; - buffer[(0 * 4 * 4) + 13] = np->rect.position.y; - - buffer[(0 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x; - buffer[(0 * 4 * 4) + 15] = source.position.y * texpixel_size.y; - - // second row - - buffer[(1 * 4 * 4) + 0] = np->rect.position.x; - buffer[(1 * 4 * 4) + 1] = np->rect.position.y + np->margin[SIDE_TOP] * screen_scale; - - buffer[(1 * 4 * 4) + 2] = source.position.x * texpixel_size.x; - buffer[(1 * 4 * 4) + 3] = (source.position.y + np->margin[SIDE_TOP]) * texpixel_size.y; - - buffer[(1 * 4 * 4) + 4] = np->rect.position.x + np->margin[SIDE_LEFT] * screen_scale; - buffer[(1 * 4 * 4) + 5] = np->rect.position.y + np->margin[SIDE_TOP] * screen_scale; - - buffer[(1 * 4 * 4) + 6] = (source.position.x + np->margin[SIDE_LEFT]) * texpixel_size.x; - buffer[(1 * 4 * 4) + 7] = (source.position.y + np->margin[SIDE_TOP]) * texpixel_size.y; - - buffer[(1 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[SIDE_RIGHT] * screen_scale; - buffer[(1 * 4 * 4) + 9] = np->rect.position.y + np->margin[SIDE_TOP] * screen_scale; - - buffer[(1 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[SIDE_RIGHT]) * texpixel_size.x; - buffer[(1 * 4 * 4) + 11] = (source.position.y + np->margin[SIDE_TOP]) * texpixel_size.y; - - buffer[(1 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; - buffer[(1 * 4 * 4) + 13] = np->rect.position.y + np->margin[SIDE_TOP] * screen_scale; - - buffer[(1 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x; - buffer[(1 * 4 * 4) + 15] = (source.position.y + np->margin[SIDE_TOP]) * texpixel_size.y; - - // third row - - buffer[(2 * 4 * 4) + 0] = np->rect.position.x; - buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[SIDE_BOTTOM] * screen_scale; - - buffer[(2 * 4 * 4) + 2] = source.position.x * texpixel_size.x; - buffer[(2 * 4 * 4) + 3] = (source.position.y + source.size.y - np->margin[SIDE_BOTTOM]) * texpixel_size.y; - - buffer[(2 * 4 * 4) + 4] = np->rect.position.x + np->margin[SIDE_LEFT] * screen_scale; - buffer[(2 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y - np->margin[SIDE_BOTTOM] * screen_scale; - - buffer[(2 * 4 * 4) + 6] = (source.position.x + np->margin[SIDE_LEFT]) * texpixel_size.x; - buffer[(2 * 4 * 4) + 7] = (source.position.y + source.size.y - np->margin[SIDE_BOTTOM]) * texpixel_size.y; - - buffer[(2 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[SIDE_RIGHT] * screen_scale; - buffer[(2 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y - np->margin[SIDE_BOTTOM] * screen_scale; - - buffer[(2 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[SIDE_RIGHT]) * texpixel_size.x; - buffer[(2 * 4 * 4) + 11] = (source.position.y + source.size.y - np->margin[SIDE_BOTTOM]) * texpixel_size.y; - - buffer[(2 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; - buffer[(2 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y - np->margin[SIDE_BOTTOM] * screen_scale; - - buffer[(2 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x; - buffer[(2 * 4 * 4) + 15] = (source.position.y + source.size.y - np->margin[SIDE_BOTTOM]) * texpixel_size.y; - - // fourth row - - buffer[(3 * 4 * 4) + 0] = np->rect.position.x; - buffer[(3 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y; - - buffer[(3 * 4 * 4) + 2] = source.position.x * texpixel_size.x; - buffer[(3 * 4 * 4) + 3] = (source.position.y + source.size.y) * texpixel_size.y; - - buffer[(3 * 4 * 4) + 4] = np->rect.position.x + np->margin[SIDE_LEFT] * screen_scale; - buffer[(3 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y; - - buffer[(3 * 4 * 4) + 6] = (source.position.x + np->margin[SIDE_LEFT]) * texpixel_size.x; - buffer[(3 * 4 * 4) + 7] = (source.position.y + source.size.y) * texpixel_size.y; - - buffer[(3 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[SIDE_RIGHT] * screen_scale; - buffer[(3 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y; - - buffer[(3 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[SIDE_RIGHT]) * texpixel_size.x; - buffer[(3 * 4 * 4) + 11] = (source.position.y + source.size.y) * texpixel_size.y; - - buffer[(3 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; - buffer[(3 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y; - - buffer[(3 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x; - buffer[(3 * 4 * 4) + 15] = (source.position.y + source.size.y) * texpixel_size.y; - } - - glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, buffer, _buffer_upload_usage_flag); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements); - - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), NULL); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), CAST_INT_TO_UCHAR_PTR((sizeof(float) * 2))); - - glDrawElements(GL_TRIANGLES, 18 * 3 - (np->draw_center ? 0 : 6), GL_UNSIGNED_BYTE, NULL); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - storage->info.render._2d_draw_call_count++; - - } break; -#if 0 - case Item::Command::TYPE_CIRCLE: { - Item::CommandCircle *circle = static_cast<Item::CommandCircle *>(command); - - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - static const int num_points = 32; - - Vector2 points[num_points + 1]; - points[num_points] = circle->pos; - - int indices[num_points * 3]; - - for (int j = 0; j < num_points; j++) { - points[j] = circle->pos + Vector2(Math::sin(j * Math_PI * 2.0 / num_points), Math::cos(j * Math_PI * 2.0 / num_points)) * circle->radius; - indices[j * 3 + 0] = j; - indices[j * 3 + 1] = (j + 1) % num_points; - indices[j * 3 + 2] = num_points; - } - - _bind_canvas_texture(RID(), RID()); - - _draw_polygon(indices, num_points * 3, num_points + 1, points, NULL, &circle->color, true); - } break; -#endif - case Item::Command::TYPE_POLYGON: { - Item::CommandPolygon *polygon = static_cast<Item::CommandPolygon *>(command); - //const PolyData &pd = _polydata[polygon->polygon.polygon_id]; - - switch (polygon->primitive) { - case RS::PRIMITIVE_TRIANGLES: { - _legacy_draw_poly_triangles(polygon, p_material); - } break; - default: - break; - } - - } break; -#if 0 - case Item::Command::TYPE_MESH: { - Item::CommandMesh *mesh = static_cast<Item::CommandMesh *>(command); - - _set_texture_rect_mode(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 k = 0; k < GD_VS::ARRAY_MAX - 1; k++) { - if (s->attribs[k].enabled) { - glEnableVertexAttribArray(k); - glVertexAttribPointer(s->attribs[k].index, s->attribs[k].size, s->attribs[k].type, s->attribs[k].normalized, s->attribs[k].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[k].offset)); - } else { - glDisableVertexAttribArray(k); - switch (k) { - case GD_VS::ARRAY_NORMAL: { - glVertexAttrib4f(GD_VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); - } break; - case GD_VS::ARRAY_COLOR: { - glVertexAttrib4f(GD_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 j = 1; j < GD_VS::ARRAY_MAX - 1; j++) { - glDisableVertexAttribArray(j); - } - } - - storage->info.render._2d_draw_call_count++; - } 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 != GD_VS::MULTIMESH_CUSTOM_DATA_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCING, true); - _set_texture_rect_mode(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 k = 0; k < GD_VS::ARRAY_MAX - 1; k++) { - if (s->attribs[k].enabled) { - glEnableVertexAttribArray(k); - glVertexAttribPointer(s->attribs[k].index, s->attribs[k].size, s->attribs[k].type, s->attribs[k].normalized, s->attribs[k].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[k].offset)); - } else { - glDisableVertexAttribArray(k); - switch (k) { - case GD_VS::ARRAY_NORMAL: { - glVertexAttrib4f(GD_VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); - } break; - case GD_VS::ARRAY_COLOR: { - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - - } break; - default: { - } - } - } - } - - for (int k = 0; k < amount; k++) { - const float *buffer = base_buffer + k * stride; - - { - glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 0, &buffer[0]); - glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 1, &buffer[4]); - if (multi_mesh->transform_format == GD_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 == GD_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); - } - } else { - glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0); - } - - if (multi_mesh->custom_data_floats) { - if (multi_mesh->custom_data_format == GD_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); - } - } - } - - // LIGHT ANGLE PR replaced USE_INSTANCE_CUSTOM line with below .. think it was a typo, - // but just in case, made this note. - //_set_texture_rect_mode(false); - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCING, false); - - storage->info.render._2d_draw_call_count++; - } break; - case Item::Command::TYPE_POLYLINE: { - Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(command); - - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - _bind_canvas_texture(RID(), RID()); - - if (pline->triangles.size()) { - _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1); -#ifdef GLES_OVER_GL - glEnable(GL_LINE_SMOOTH); - if (pline->multiline) { - //needs to be different - } else { - _draw_generic(GL_LINE_LOOP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); - } - glDisable(GL_LINE_SMOOTH); -#endif - } else { -#ifdef GLES_OVER_GL - if (pline->antialiased) - glEnable(GL_LINE_SMOOTH); -#endif - - if (pline->multiline) { - int todo = pline->lines.size() / 2; - int max_per_call = data.polygon_buffer_size / (sizeof(real_t) * 4); - int offset = 0; - - while (todo) { - int to_draw = MIN(max_per_call, todo); - _draw_generic(GL_LINES, to_draw * 2, &pline->lines.ptr()[offset], NULL, pline->line_colors.size() == 1 ? pline->line_colors.ptr() : &pline->line_colors.ptr()[offset], pline->line_colors.size() == 1); - todo -= to_draw; - offset += to_draw * 2; - } - } else { - _draw_generic(GL_LINE_STRIP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); - } - -#ifdef GLES_OVER_GL - if (pline->antialiased) - glDisable(GL_LINE_SMOOTH); -#endif - } - } break; - - case Item::Command::TYPE_PRIMITIVE: { - Item::CommandPrimitive *primitive = static_cast<Item::CommandPrimitive *>(command); - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - ERR_CONTINUE(primitive->points.size() < 1); - - RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(primitive->texture, primitive->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); - } - - // we need a temporary because this must be nulled out - // if only a single color specified - const Color *colors = primitive->colors.ptr(); - if (primitive->colors.size() == 1 && primitive->points.size() > 1) { - Color c = primitive->colors[0]; - glVertexAttrib4f(GD_VS::ARRAY_COLOR, c.r, c.g, c.b, c.a); - colors = nullptr; - } else if (primitive->colors.empty()) { - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - } -#ifdef RASTERIZER_EXTRA_CHECKS - else { - RAST_DEV_DEBUG_ASSERT(primitive->colors.size() == primitive->points.size()); - } - - if (primitive->uvs.ptr()) { - RAST_DEV_DEBUG_ASSERT(primitive->uvs.size() == primitive->points.size()); - } -#endif - - _draw_gui_primitive(primitive->points.size(), primitive->points.ptr(), colors, primitive->uvs.ptr()); - } break; -#endif - case Item::Command::TYPE_TRANSFORM: { - Item::CommandTransform *transform = static_cast<Item::CommandTransform *>(command); - state.uniforms.extra_matrix = transform->xform; - state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, state.uniforms.extra_matrix); - } break; - - case Item::Command::TYPE_PARTICLES: { - } break; - case Item::Command::TYPE_CLIP_IGNORE: { - Item::CommandClipIgnore *ci = static_cast<Item::CommandClipIgnore *>(command); - if (p_current_clip) { - if (ci->ignore != r_reclip) { - if (ci->ignore) { - glDisable(GL_SCISSOR_TEST); - r_reclip = true; - } else { - glEnable(GL_SCISSOR_TEST); - - int x = p_current_clip->final_clip_rect.position.x; - int y = storage->frame.current_rt->height - (p_current_clip->final_clip_rect.position.y + p_current_clip->final_clip_rect.size.y); - int w = p_current_clip->final_clip_rect.size.x; - int h = p_current_clip->final_clip_rect.size.y; - - // FTODO - // if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_VFLIP]) - // y = p_current_clip->final_clip_rect.position.y; - - glScissor(x, y, w, h); - - r_reclip = false; - } - } - } - - } break; - default: { - // FIXME: Proper error handling if relevant - //print_line("other"); - } break; - } - } - - } // default - break; - } - } -} - -void RasterizerCanvasGLES2::canvas_end() { - batch_canvas_end(); - RasterizerCanvasBaseGLES2::canvas_end(); -} - -void RasterizerCanvasGLES2::canvas_begin() { - batch_canvas_begin(); - RasterizerCanvasBaseGLES2::canvas_begin(); -} - -void RasterizerCanvasGLES2::canvas_render_items_begin(const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) { - batch_canvas_render_items_begin(p_modulate, p_light, p_base_transform); -} - -void RasterizerCanvasGLES2::canvas_render_items_end() { - batch_canvas_render_items_end(); -} - -void RasterizerCanvasGLES2::canvas_render_items_internal(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) { - batch_canvas_render_items(p_item_list, p_z, p_modulate, p_light, p_base_transform); - - //glClearColor(Math::randf(), 0, 1, 1); -} - -void RasterizerCanvasGLES2::canvas_render_items_implementation(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) { - // parameters are easier to pass around in a structure - RenderItemState ris; - ris.item_group_z = p_z; - ris.item_group_modulate = p_modulate; - ris.item_group_light = p_light; - ris.item_group_base_transform = p_base_transform; - - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, false); - - state.current_tex = RID(); - state.current_tex_ptr = NULL; - state.current_normal = RID(); - state.canvas_texscreen_used = false; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - - if (bdata.settings_use_batching) { -#ifdef GODOT_3 - for (int j = 0; j < bdata.items_joined.size(); j++) { - render_joined_item(bdata.items_joined[j], ris); - } -#endif - } else { - while (p_item_list) { - Item *ci = p_item_list; - _legacy_canvas_render_item(ci, ris); - p_item_list = p_item_list->next; - } - } - - if (ris.current_clip) { - glDisable(GL_SCISSOR_TEST); - } - - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, false); -} - -#ifdef GODOT_3 -// This function is a dry run of the state changes when drawing the item. -// It should duplicate the logic in _canvas_render_item, -// to decide whether items are similar enough to join -// i.e. no state differences between the 2 items. -bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bool &r_batch_break) { - // if we set max join items to zero we can effectively prevent any joining, so - // none of the other logic needs to run. Good for testing regression bugs, and - // could conceivably be faster in some games. - if (!bdata.settings_max_join_item_commands) { - return false; - } - - // if there are any state changes we change join to false - // we also set r_batch_break to true if we don't want this item joined to the next - // (e.g. an item that must not be joined at all) - r_batch_break = false; - bool join = true; - - // light_masked may possibly need state checking here. Check for regressions! - - // we will now allow joining even if final modulate is different - // we will instead bake the final modulate into the vertex colors - // if (p_ci->final_modulate != r_ris.final_modulate) { - // join = false; - // r_ris.final_modulate = p_ci->final_modulate; - // } - - if (r_ris.current_clip != p_ci->final_clip_owner) { - r_ris.current_clip = p_ci->final_clip_owner; - join = false; - } - - // TODO: copy back buffer - - if (p_ci->copy_back_buffer) { - join = false; - } - - RasterizerStorageGLES2::Skeleton *skeleton = NULL; - - { - //skeleton handling - if (p_ci->skeleton.is_valid() && storage->skeleton_owner.owns(p_ci->skeleton)) { - skeleton = storage->skeleton_owner.get(p_ci->skeleton); - if (!skeleton->use_2d) { - skeleton = NULL; - } - } - - bool skeleton_prevent_join = false; - - bool use_skeleton = skeleton != NULL; - if (r_ris.prev_use_skeleton != use_skeleton) { - if (!bdata.settings_use_software_skinning) - r_ris.rebind_shader = true; - - r_ris.prev_use_skeleton = use_skeleton; - // join = false; - skeleton_prevent_join = true; - } - - if (skeleton) { - // join = false; - skeleton_prevent_join = true; - state.using_skeleton = true; - } else { - state.using_skeleton = false; - } - - if (skeleton_prevent_join) { - if (!bdata.settings_use_software_skinning) - join = false; - } - } - - Item *material_owner = p_ci->material_owner ? p_ci->material_owner : p_ci; - - RID material = material_owner->material; - RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material); - - if (material != r_ris.canvas_last_material || r_ris.rebind_shader) { - join = false; - RasterizerStorageGLES2::Shader *shader_ptr = NULL; - - if (material_ptr) { - shader_ptr = material_ptr->shader; - - if (shader_ptr && shader_ptr->mode != GD_VS::SHADER_CANVAS_ITEM) { - shader_ptr = NULL; // not a canvas item shader, don't use. - } - } - - if (shader_ptr) { - if (shader_ptr->canvas_item.uses_screen_texture) { - if (!state.canvas_texscreen_used) { - join = false; - } - } - } - - r_ris.shader_cache = shader_ptr; - - r_ris.canvas_last_material = material; - - r_ris.rebind_shader = false; - } - - int blend_mode = r_ris.shader_cache ? r_ris.shader_cache->canvas_item.blend_mode : RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX; - bool unshaded = r_ris.shader_cache && (r_ris.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; - - // we are precalculating the final_modulate ahead of time because we need this for baking of final modulate into vertex colors - // (only in software transform mode) - // This maybe inefficient storing it... - r_ris.final_modulate = unshaded ? p_ci->final_modulate : (p_ci->final_modulate * r_ris.item_group_modulate); - - if (r_ris.last_blend_mode != blend_mode) { - join = false; - r_ris.last_blend_mode = blend_mode; - } - - // does the shader contain BUILTINs which should break the batching? - bdata.joined_item_batch_flags = 0; - if (r_ris.shader_cache) { - unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING | RasterizerStorageCommon::PREVENT_ITEM_JOINING); - if (and_flags) { - // special case for preventing item joining altogether - if (and_flags & RasterizerStorageCommon::PREVENT_ITEM_JOINING) { - join = false; - //r_batch_break = true; // don't think we need a batch break - - // save the flags so that they don't need to be recalculated in the 2nd pass - bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; - } else { - bool use_larger_fvfs = true; - - if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { - // in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color - // will still be okay to do in the shader with no ill effects - if (r_ris.final_modulate == Color(1, 1, 1, 1)) { - use_larger_fvfs = false; - } - } - - // new .. always use large FVF - if (use_larger_fvfs) { - if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { - bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF; - } else { - // we need to save on the joined item that it should use large fvf. - // This info will then be used in filling and rendering - bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF; - } - - bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; - } - -#if 0 - if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { - // in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color - // will still be okay to do in the shader with no ill effects - if (r_ris.final_modulate == Color(1, 1, 1, 1)) { - break_batching = false; - } - else - { - // new .. large FVF - break_batching = false; - - // we need to save on the joined item that it should use large fvf. - // This info will then be used in filling and rendering - bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF; - } - } - - if (break_batching) { - join = false; - r_batch_break = true; - - // save the flags so that they don't need to be recalculated in the 2nd pass - bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; - } -#endif - } // if not prevent item joining - } - } - - if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && r_ris.item_group_light && !unshaded) { - // we cannot join lit items easily. - // it is possible, but not if they overlap, because - // a + light_blend + b + light_blend IS NOT THE SAME AS - // a + b + light_blend - - bool light_allow_join = true; - - // this is a quick getout if we have turned off light joining - if ((bdata.settings_light_max_join_items == 0) || r_ris.light_region.too_many_lights) { - light_allow_join = false; - } else { - // do light joining... - - // first calculate the light bitfield - uint64_t light_bitfield = 0; - uint64_t shadow_bitfield = 0; - Light *light = r_ris.item_group_light; - - int light_count = -1; - while (light) { - light_count++; - uint64_t light_bit = 1ULL << light_count; - - // note that as a cost of batching, the light culling will be less effective - if (p_ci->light_mask & light->item_mask && r_ris.item_group_z >= light->z_min && r_ris.item_group_z <= light->z_max) { - // Note that with the above test, it is possible to also include a bound check. - // Tests so far have indicated better performance without it, but there may be reason to change this at a later stage, - // so I leave the line here for reference: - // && p_ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { - light_bitfield |= light_bit; - - bool has_shadow = light->shadow_buffer.is_valid() && p_ci->light_mask & light->item_shadow_mask; - - if (has_shadow) { - shadow_bitfield |= light_bit; - } - } - - light = light->next_ptr; - } - - // now compare to previous - if ((r_ris.light_region.light_bitfield != light_bitfield) || (r_ris.light_region.shadow_bitfield != shadow_bitfield)) { - light_allow_join = false; - - r_ris.light_region.light_bitfield = light_bitfield; - r_ris.light_region.shadow_bitfield = shadow_bitfield; - } else { - // only do these checks if necessary - if (join && (!r_batch_break)) { - // we still can't join, even if the lights are exactly the same, if there is overlap between the previous and this item - if (r_ris.joined_item && light_bitfield) { - if ((int)r_ris.joined_item->num_item_refs <= bdata.settings_light_max_join_items) { - for (uint32_t r = 0; r < r_ris.joined_item->num_item_refs; r++) { - Item *pRefItem = bdata.item_refs[r_ris.joined_item->first_item_ref + r].item; - if (p_ci->global_rect_cache.intersects(pRefItem->global_rect_cache)) { - light_allow_join = false; - break; - } - } - -#ifdef DEBUG_ENABLED - if (light_allow_join) { - bdata.stats_light_items_joined++; - } -#endif - - } // if below max join items - else { - // just don't allow joining if above overlap check max items - light_allow_join = false; - } - } - - } // if not batch broken already (no point in doing expensive overlap tests if not needed) - } // if bitfields don't match - } // if do light joining - - if (!light_allow_join) { - // can't join - join = false; - // we also dont want to allow joining this item with the next item, because the next item could have no lights! - r_batch_break = true; - } - - } else { - // if the last item had lights, we should not join it to this one (which has no lights) - if (r_ris.light_region.light_bitfield || r_ris.light_region.shadow_bitfield) { - join = false; - - // setting these to zero ensures that any following item with lights will, by definition, - // be affected by a different set of lights, and thus prevent a join - r_ris.light_region.light_bitfield = 0; - r_ris.light_region.shadow_bitfield = 0; - } - } - - if (reclip) { - join = false; - } - - // non rects will break the batching anyway, we don't want to record item changes, detect this - if (!r_batch_break && _detect_item_batch_break(r_ris, p_ci, r_batch_break)) { - join = false; - - r_batch_break = true; - } - - return join; -} -#endif // godot 3 - -// Legacy non-batched implementation for regression testing. -// Should be removed after testing phase to avoid duplicate codepaths. -void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemState &r_ris) { - storage->info.render._2d_item_count++; - - // defaults - state.current_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; - state.current_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; - - if (p_ci->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { - state.current_filter = p_ci->texture_filter; - } - - if (p_ci->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { - state.current_repeat = p_ci->texture_repeat; - } - - if (r_ris.current_clip != p_ci->final_clip_owner) { - r_ris.current_clip = p_ci->final_clip_owner; - - if (r_ris.current_clip) { - glEnable(GL_SCISSOR_TEST); - int y = storage->_dims.rt_height - (r_ris.current_clip->final_clip_rect.position.y + r_ris.current_clip->final_clip_rect.size.y); - // int y = storage->frame.current_rt->height - (r_ris.current_clip->final_clip_rect.position.y + r_ris.current_clip->final_clip_rect.size.y); - // FTODO - // if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_VFLIP]) - // y = r_ris.current_clip->final_clip_rect.position.y; - glScissor(r_ris.current_clip->final_clip_rect.position.x, y, r_ris.current_clip->final_clip_rect.size.width, r_ris.current_clip->final_clip_rect.size.height); - - // debug VFLIP - // if ((r_ris.current_clip->final_clip_rect.position.x == 223) - // && (y == 54) - // && (r_ris.current_clip->final_clip_rect.size.width == 1383)) - // { - // glScissor(r_ris.current_clip->final_clip_rect.position.x, y, r_ris.current_clip->final_clip_rect.size.width, r_ris.current_clip->final_clip_rect.size.height); - // } - - } else { - glDisable(GL_SCISSOR_TEST); - } - } - - // TODO: copy back buffer - - if (p_ci->copy_back_buffer) { - if (p_ci->copy_back_buffer->full) { - _copy_texscreen(Rect2()); - } else { - _copy_texscreen(p_ci->copy_back_buffer->rect); - } - } - -#if 0 - RasterizerStorageGLES2::Skeleton *skeleton = NULL; - - { - //skeleton handling - if (p_ci->skeleton.is_valid() && storage->skeleton_owner.owns(p_ci->skeleton)) { - skeleton = storage->skeleton_owner.get(p_ci->skeleton); - if (!skeleton->use_2d) { - skeleton = NULL; - } else { - state.skeleton_transform = r_ris.item_group_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 (r_ris.prev_use_skeleton != use_skeleton) { - r_ris.rebind_shader = true; - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, use_skeleton); - r_ris.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; - } - } -#endif - - Item *material_owner = p_ci->material_owner ? p_ci->material_owner : p_ci; - - RID material = material_owner->material; - RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material); - - if (material != r_ris.canvas_last_material || r_ris.rebind_shader) { - RasterizerStorageGLES2::Shader *shader_ptr = NULL; - - if (material_ptr) { - shader_ptr = material_ptr->shader; - - if (shader_ptr && shader_ptr->mode != GD_VS::SHADER_CANVAS_ITEM) { - shader_ptr = NULL; // not a canvas item shader, don't use. - } - } - - if (shader_ptr) { - if (shader_ptr->canvas_item.uses_screen_texture) { - if (!state.canvas_texscreen_used) { - //copy if not copied before - _copy_texscreen(Rect2()); - - // blend mode will have been enabled so make sure we disable it again later on - //last_blend_mode = last_blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; - } - - if (storage->frame.current_rt->copy_screen_effect.color) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); - } - } - - if (shader_ptr != r_ris.shader_cache) { - if (shader_ptr->canvas_item.uses_time) { - RenderingServerDefault::redraw_request(); - } - - state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); - state.canvas_shader.bind(); - } - - int tc = material_ptr->textures.size(); - Pair<StringName, RID> *textures = material_ptr->textures.ptrw(); - - ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw(); - - for (int i = 0; i < tc; i++) { - glActiveTexture(GL_TEXTURE0 + i); - - RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second); - - if (!t) { - switch (texture_hints[i]) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); - } break; - default: { - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - } break; - } - - continue; - } - - if (t->redraw_if_visible) { - RenderingServerDefault::redraw_request(); - } - - t = t->get_ptr(); - -#ifdef TOOLS_ENABLED - if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) { - t->detect_normal(t->detect_normal_ud); - } -#endif - if (t->render_target) - t->render_target->used_in_frame = true; - - glBindTexture(t->target, t->tex_id); - } - - } else { - state.canvas_shader.set_custom_shader(0); - state.canvas_shader.bind(); - } - state.canvas_shader.use_material((void *)material_ptr); - - r_ris.shader_cache = shader_ptr; - - r_ris.canvas_last_material = material; - - r_ris.rebind_shader = false; - } - - int blend_mode = r_ris.shader_cache ? r_ris.shader_cache->canvas_item.blend_mode : RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX; - bool unshaded = r_ris.shader_cache && (r_ris.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 (r_ris.last_blend_mode != blend_mode) { - switch (blend_mode) { - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - } - - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_ADD: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); - } - - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); - } - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO); - } else { - glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE); - } - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - } - } break; - } - } - - state.uniforms.final_modulate = unshaded ? p_ci->final_modulate : Color(p_ci->final_modulate.r * r_ris.item_group_modulate.r, p_ci->final_modulate.g * r_ris.item_group_modulate.g, p_ci->final_modulate.b * r_ris.item_group_modulate.b, p_ci->final_modulate.a * r_ris.item_group_modulate.a); - - state.uniforms.modelview_matrix = p_ci->final_transform; - state.uniforms.extra_matrix = Transform2D(); - - _set_uniforms(); - - if (unshaded || (state.uniforms.final_modulate.a > 0.001 && (!r_ris.shader_cache || r_ris.shader_cache->canvas_item.light_mode != RasterizerStorageGLES2::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !p_ci->light_masked)) - _legacy_canvas_item_render_commands(p_ci, NULL, reclip, material_ptr); - - r_ris.rebind_shader = true; // hacked in for now. - - if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && r_ris.item_group_light && !unshaded) { - Light *light = r_ris.item_group_light; - bool light_used = false; - GD_VS::CanvasLightBlendMode bmode = GD_VS::CANVAS_LIGHT_BLEND_MODE_ADD; - state.uniforms.final_modulate = p_ci->final_modulate; // remove the canvas modulate - - while (light) { - if (p_ci->light_mask & light->item_mask && r_ris.item_group_z >= light->z_min && r_ris.item_group_z <= light->z_max && p_ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { - //intersects this light - - if (!light_used || bmode != light->blend_mode) { - bmode = light->blend_mode; - - switch (bmode) { - case GD_VS::CANVAS_LIGHT_BLEND_MODE_ADD: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - - } break; - case GD_VS::CANVAS_LIGHT_BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case GD_VS::CANVAS_LIGHT_BLEND_MODE_MIX: { - // case GD_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; - } - - // FTODO - //bool has_shadow = light->shadow_buffer.is_valid() && p_ci->light_mask & light->item_shadow_mask; - bool has_shadow = light->use_shadow && p_ci->light_mask & light->item_shadow_mask; - - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow); - if (has_shadow) { - // FTODO - //state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, false); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_NONE); - //state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF3); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, false); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF5); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, false); - //state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF7); - //state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF9); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, false); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF13); - } - - state.canvas_shader.bind(); - state.using_light = light; - state.using_shadow = has_shadow; - - //always re-set uniforms, since light parameters changed - _set_uniforms(); - state.canvas_shader.use_material((void *)material_ptr); - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); - 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); - _legacy_canvas_item_render_commands(p_ci, NULL, reclip, material_ptr); //redraw using light - - state.using_light = NULL; - } - - 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(); - - r_ris.last_blend_mode = -1; - -#if 0 - //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[RendererStorage::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 -#endif - } - } - - if (reclip) { - glEnable(GL_SCISSOR_TEST); - int y = storage->frame.current_rt->height - (r_ris.current_clip->final_clip_rect.position.y + r_ris.current_clip->final_clip_rect.size.y); - // FTODO - // if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_VFLIP]) - // y = r_ris.current_clip->final_clip_rect.position.y; - glScissor(r_ris.current_clip->final_clip_rect.position.x, y, r_ris.current_clip->final_clip_rect.size.width, r_ris.current_clip->final_clip_rect.size.height); - } -} - -#ifdef GODOT_3 -void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderItemState &r_ris) { - storage->info.render._2d_item_count++; - -#ifdef DEBUG_ENABLED - if (bdata.diagnose_frame) { - bdata.frame_string += "\tjoined_item " + itos(p_bij.num_item_refs) + " refs\n"; - if (p_bij.z_index != 0) { - bdata.frame_string += "\t\t(z " + itos(p_bij.z_index) + ")\n"; - } - } -#endif - - // all the joined items will share the same state with the first item - Item *ci = bdata.item_refs[p_bij.first_item_ref].item; - - if (r_ris.current_clip != ci->final_clip_owner) { - r_ris.current_clip = ci->final_clip_owner; - - if (r_ris.current_clip) { - glEnable(GL_SCISSOR_TEST); - int y = storage->frame.current_rt->height - (r_ris.current_clip->final_clip_rect.position.y + r_ris.current_clip->final_clip_rect.size.y); - if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_VFLIP]) - y = r_ris.current_clip->final_clip_rect.position.y; - glScissor(r_ris.current_clip->final_clip_rect.position.x, y, r_ris.current_clip->final_clip_rect.size.width, r_ris.current_clip->final_clip_rect.size.height); - } else { - glDisable(GL_SCISSOR_TEST); - } - } - - // TODO: copy back buffer - - if (ci->copy_back_buffer) { - if (ci->copy_back_buffer->full) { - _copy_texscreen(Rect2()); - } else { - _copy_texscreen(ci->copy_back_buffer->rect); - } - } - - if (!bdata.settings_use_batching || !bdata.settings_use_software_skinning) { - 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 = r_ris.item_group_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 (r_ris.prev_use_skeleton != use_skeleton) { - r_ris.rebind_shader = true; - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, use_skeleton); - r_ris.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; - } - - } // if not using batching - - Item *material_owner = ci->material_owner ? ci->material_owner : ci; - - RID material = material_owner->material; - RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material); - - if (material != r_ris.canvas_last_material || r_ris.rebind_shader) { - RasterizerStorageGLES2::Shader *shader_ptr = NULL; - - if (material_ptr) { - shader_ptr = material_ptr->shader; - - if (shader_ptr && shader_ptr->mode != GD_VS::SHADER_CANVAS_ITEM) { - shader_ptr = NULL; // not a canvas item shader, don't use. - } - } - - if (shader_ptr) { - if (shader_ptr->canvas_item.uses_screen_texture) { - if (!state.canvas_texscreen_used) { - //copy if not copied before - _copy_texscreen(Rect2()); - - // blend mode will have been enabled so make sure we disable it again later on - //last_blend_mode = last_blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; - } - - if (storage->frame.current_rt->copy_screen_effect.color) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); - } - } - - if (shader_ptr != r_ris.shader_cache) { - if (shader_ptr->canvas_item.uses_time) { - VisualServerRaster::redraw_request(); - } - - state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); - state.canvas_shader.bind(); - } - - int tc = material_ptr->textures.size(); - Pair<StringName, RID> *textures = material_ptr->textures.ptrw(); - - ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw(); - - for (int i = 0; i < tc; i++) { - glActiveTexture(GL_TEXTURE0 + i); - - RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second); - - if (!t) { - switch (texture_hints[i]) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); - } break; - default: { - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - } break; - } - - continue; - } - - if (t->redraw_if_visible) { - VisualServerRaster::redraw_request(); - } - - t = t->get_ptr(); - -#ifdef TOOLS_ENABLED - if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) { - t->detect_normal(t->detect_normal_ud); - } -#endif - if (t->render_target) - t->render_target->used_in_frame = true; - - glBindTexture(t->target, t->tex_id); - } - - } else { - state.canvas_shader.set_custom_shader(0); - state.canvas_shader.bind(); - } - state.canvas_shader.use_material((void *)material_ptr); - - r_ris.shader_cache = shader_ptr; - - r_ris.canvas_last_material = material; - - r_ris.rebind_shader = false; - } - - int blend_mode = r_ris.shader_cache ? r_ris.shader_cache->canvas_item.blend_mode : RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX; - bool unshaded = r_ris.shader_cache && (r_ris.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 (r_ris.last_blend_mode != blend_mode) { - switch (blend_mode) { - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - } - - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_ADD: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); - } - - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); - } - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO); - } else { - glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE); - } - } break; - case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - } - } break; - } - } - - // using software transform? - // (i.e. don't send the transform matrix, send identity, and either use baked verts, - // or large fvf where the transform is done in the shader from transform stored in the fvf.) - if (!p_bij.use_hardware_transform()) { - state.uniforms.modelview_matrix = Transform2D(); - // final_modulate will be baked per item ref so the final_modulate can be an identity color - state.uniforms.final_modulate = Color(1, 1, 1, 1); - } else { - state.uniforms.modelview_matrix = ci->final_transform; - // could use the stored version of final_modulate in item ref? Test which is faster NYI - state.uniforms.final_modulate = unshaded ? ci->final_modulate : (ci->final_modulate * r_ris.item_group_modulate); - } - state.uniforms.extra_matrix = Transform2D(); - - _set_uniforms(); - - if (unshaded || (state.uniforms.final_modulate.a > 0.001 && (!r_ris.shader_cache || r_ris.shader_cache->canvas_item.light_mode != RasterizerStorageGLES2::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked)) - render_joined_item_commands(p_bij, NULL, reclip, material_ptr, false); - - r_ris.rebind_shader = true; // hacked in for now. - - if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && r_ris.item_group_light && !unshaded) { - Light *light = r_ris.item_group_light; - bool light_used = false; - VS::CanvasLightMode mode = GD_VS::CANVAS_LIGHT_MODE_ADD; - - // we leave this set to 1, 1, 1, 1 if using software because the colors are baked into the vertices - if (p_bij.use_hardware_transform()) { - state.uniforms.final_modulate = ci->final_modulate; // remove the canvas modulate - } - - while (light) { - // use the bounding rect of the joined items, NOT only the bounding rect of the first item. - // note this is a cost of batching, the light culling will be less effective - - // note that the r_ris.item_group_z will be out of date because we are using deferred rendering till canvas_render_items_end() - // so we have to test z against the stored value in the joined item - if (ci->light_mask & light->item_mask && p_bij.z_index >= light->z_min && p_bij.z_index <= light->z_max && p_bij.bounding_rect.intersects_transformed(light->xform_cache, light->rect_cache)) { - //intersects this light - - if (!light_used || mode != light->mode) { - mode = light->mode; - - switch (mode) { - case GD_VS::CANVAS_LIGHT_MODE_ADD: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - - } break; - case GD_VS::CANVAS_LIGHT_MODE_SUB: { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case GD_VS::CANVAS_LIGHT_MODE_MIX: - case GD_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); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF3); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF5); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF7); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF9); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, light->shadow_filter == GD_VS::CANVAS_LIGHT_FILTER_PCF13); - } - - state.canvas_shader.bind(); - state.using_light = light; - state.using_shadow = has_shadow; - - //always re-set uniforms, since light parameters changed - _set_uniforms(); - state.canvas_shader.use_material((void *)material_ptr); - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); - 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); - - // redraw using light. - // if there is no clip item, we can consider scissoring to the intersection area between the light and the item - // this can greatly reduce fill rate .. - // at the cost of glScissor commands, so is optional - if (!bdata.settings_scissor_lights || r_ris.current_clip) { - render_joined_item_commands(p_bij, NULL, reclip, material_ptr, true); - } else { - bool scissor = _light_scissor_begin(p_bij.bounding_rect, light->xform_cache, light->rect_cache); - render_joined_item_commands(p_bij, NULL, reclip, material_ptr, true); - if (scissor) { - glDisable(GL_SCISSOR_TEST); - } - } - - state.using_light = NULL; - } - - 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(); - - r_ris.last_blend_mode = -1; - -#if 0 - //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[RendererStorage::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 -#endif - } - } - - if (reclip) { - glEnable(GL_SCISSOR_TEST); - int y = storage->frame.current_rt->height - (r_ris.current_clip->final_clip_rect.position.y + r_ris.current_clip->final_clip_rect.size.y); - if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_VFLIP]) - y = r_ris.current_clip->final_clip_rect.position.y; - glScissor(r_ris.current_clip->final_clip_rect.position.x, y, r_ris.current_clip->final_clip_rect.size.width, r_ris.current_clip->final_clip_rect.size.height); - } -} -#endif // def GODOT 3 - -void RasterizerCanvasGLES2::gl_enable_scissor(int p_x, int p_y, int p_width, int p_height) const { - glEnable(GL_SCISSOR_TEST); - glScissor(p_x, p_y, p_width, p_height); -} - -void RasterizerCanvasGLES2::gl_disable_scissor() const { - glDisable(GL_SCISSOR_TEST); -} - -void RasterizerCanvasGLES2::initialize() { - RasterizerCanvasBaseGLES2::initialize(); - - batch_initialize(); - - // just reserve some space (may not be needed as we are orphaning, but hey ho) - glGenBuffers(1, &bdata.gl_vertex_buffer); - - if (bdata.vertex_buffer_size_bytes) { - glBindBuffer(GL_ARRAY_BUFFER, bdata.gl_vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, bdata.vertex_buffer_size_bytes, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // pre fill index buffer, the indices never need to change so can be static - glGenBuffers(1, &bdata.gl_index_buffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bdata.gl_index_buffer); - - Vector<uint16_t> indices; - indices.resize(bdata.index_buffer_size_units); - - for (unsigned int q = 0; q < bdata.max_quads; q++) { - int i_pos = q * 6; // 6 inds per quad - int q_pos = q * 4; // 4 verts per quad - indices.set(i_pos, q_pos); - indices.set(i_pos + 1, q_pos + 1); - indices.set(i_pos + 2, q_pos + 2); - indices.set(i_pos + 3, q_pos); - indices.set(i_pos + 4, q_pos + 2); - indices.set(i_pos + 5, q_pos + 3); - - // we can only use 16 bit indices in GLES2! -#ifdef DEBUG_ENABLED - CRASH_COND((q_pos + 3) > 65535); -#endif - } - - glBufferData(GL_ELEMENT_ARRAY_BUFFER, bdata.index_buffer_size_bytes, &indices[0], GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - } // only if there is a vertex buffer (batching is on) -} - -RasterizerCanvasGLES2::RasterizerCanvasGLES2() { - batch_constructor(); -} - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h deleted file mode 100644 index fd4da5434e..0000000000 --- a/drivers/gles2/rasterizer_canvas_gles2.h +++ /dev/null @@ -1,104 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZERCANVASGLES2_H -#define RASTERIZERCANVASGLES2_H - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "drivers/gles_common/rasterizer_canvas_batcher.h" -#include "drivers/gles_common/rasterizer_version.h" -#include "rasterizer_canvas_base_gles2.h" - -class RasterizerSceneGLES2; - -class RasterizerCanvasGLES2 : public RasterizerCanvasBaseGLES2, public RasterizerCanvasBatcher<RasterizerCanvasGLES2, RasterizerStorageGLES2> { - friend class RasterizerCanvasBatcher<RasterizerCanvasGLES2, RasterizerStorageGLES2>; - -public: - virtual void canvas_render_items_begin(const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform); - virtual void canvas_render_items_end(); - void canvas_render_items_internal(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform); - virtual void canvas_begin() override; - virtual void canvas_end() override; - - void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override { - storage->frame.current_rt = nullptr; - - //if (p_to_render_target.is_valid()) - // print_line("canvas_render_items " + itos(p_to_render_target.get_id()) ); - // print_line("canvas_render_items "); - - // first set the current render target - storage->_set_current_render_target(p_to_render_target); - - // binds the render target (framebuffer) - canvas_begin(); - - canvas_render_items_begin(p_modulate, p_light_list, p_canvas_transform); - canvas_render_items_internal(p_item_list, 0, p_modulate, p_light_list, p_canvas_transform); - canvas_render_items_end(); - - canvas_end(); - - // not sure why these are needed to get frame to render? - storage->_set_current_render_target(RID()); - // storage->frame.current_rt = nullptr; - // canvas_begin(); - // canvas_end(); - } - -private: - // legacy codepath .. to remove after testing - void _legacy_canvas_render_item(Item *p_ci, RenderItemState &r_ris); - - // high level batch funcs - void canvas_render_items_implementation(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform); - //void render_joined_item(const BItemJoined &p_bij, RenderItemState &r_ris); - //bool try_join_item(Item *p_ci, RenderItemState &r_ris, bool &r_batch_break); - void render_batches(Item::Command *const *p_commands, Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material); - - // low level batch funcs - // void _batch_upload_buffers(); - // void _batch_render_generic(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material); - // void _batch_render_lines(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material, bool p_anti_alias); - - // funcs used from rasterizer_canvas_batcher template - void gl_enable_scissor(int p_x, int p_y, int p_width, int p_height) const; - void gl_disable_scissor() const; - -public: - void initialize(); - RasterizerCanvasGLES2(); -}; - -#endif // GLES2_BACKEND_ENABLED -#endif // RASTERIZERCANVASGLES2_H diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp deleted file mode 100644 index 222c9b8494..0000000000 --- a/drivers/gles2/rasterizer_gles2.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_gles2.h" - -#ifdef GLES2_BACKEND_ENABLED -#include "shader_gles2.h" - -#include "core/config/project_settings.h" -#include "core/os/os.h" - -#define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 -#define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 -#define _EXT_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 -#define _EXT_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 -#define _EXT_DEBUG_SOURCE_API_ARB 0x8246 -#define _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 -#define _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 -#define _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 -#define _EXT_DEBUG_SOURCE_APPLICATION_ARB 0x824A -#define _EXT_DEBUG_SOURCE_OTHER_ARB 0x824B -#define _EXT_DEBUG_TYPE_ERROR_ARB 0x824C -#define _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D -#define _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E -#define _EXT_DEBUG_TYPE_PORTABILITY_ARB 0x824F -#define _EXT_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 -#define _EXT_DEBUG_TYPE_OTHER_ARB 0x8251 -#define _EXT_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 -#define _EXT_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 -#define _EXT_DEBUG_LOGGED_MESSAGES_ARB 0x9145 -#define _EXT_DEBUG_SEVERITY_HIGH_ARB 0x9146 -#define _EXT_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 -#define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148 -#define _EXT_DEBUG_OUTPUT 0x92E0 - -#ifndef GLAPIENTRY -#if defined(WINDOWS_ENABLED) && !defined(UWP_ENABLED) -#define GLAPIENTRY APIENTRY -#else -#define GLAPIENTRY -#endif -#endif - -#ifndef IPHONE_ENABLED -// We include EGL below to get debug callback on GLES2 platforms, -// but EGL is not available on iOS. -#define CAN_DEBUG -#endif - -#if !defined(GLES_OVER_GL) && defined(CAN_DEBUG) -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <GLES2/gl2platform.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#endif - -#if defined(MINGW_ENABLED) || defined(_MSC_VER) -#define strcpy strcpy_s -#endif - -void RasterizerGLES2::begin_frame(double frame_step) { - frame++; - delta = frame_step; - - // from 3.2 - time_total += frame_step * time_scale; - - if (frame_step == 0) { - //to avoid hiccups - frame_step = 0.001; - } - - double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs"); - time_total = Math::fmod(time_total, time_roll_over); - - storage.frame.time[0] = time_total; - storage.frame.time[1] = Math::fmod(time_total, 3600); - storage.frame.time[2] = Math::fmod(time_total, 900); - storage.frame.time[3] = Math::fmod(time_total, 60); - storage.frame.count++; - storage.frame.delta = frame_step; - - storage.update_dirty_resources(); - - storage.info.render_final = storage.info.render; - storage.info.render.reset(); - - //scene->iteration(); -} - -void RasterizerGLES2::end_frame(bool p_swap_buffers) { - // if (OS::get_singleton()->is_layered_allowed()) { - // if (!OS::get_singleton()->get_window_per_pixel_transparency_enabled()) { - //clear alpha - // glColorMask(false, false, false, true); - // glClearColor(0.5, 0, 0, 1); - // glClear(GL_COLOR_BUFFER_BIT); - // glColorMask(true, true, true, true); - // } - // } - - // glClearColor(1, 0, 0, 1); - // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - if (p_swap_buffers) - DisplayServer::get_singleton()->swap_buffers(); - else - glFinish(); -} - -#ifdef CAN_DEBUG -static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) { - if (type == _EXT_DEBUG_TYPE_OTHER_ARB) - return; - - if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB) - return; //these are ultimately annoying, so removing for now - - char debSource[256], debType[256], debSev[256]; - - if (source == _EXT_DEBUG_SOURCE_API_ARB) - strcpy(debSource, "OpenGL"); - else if (source == _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB) - strcpy(debSource, "Windows"); - else if (source == _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB) - strcpy(debSource, "Shader Compiler"); - else if (source == _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB) - strcpy(debSource, "Third Party"); - else if (source == _EXT_DEBUG_SOURCE_APPLICATION_ARB) - strcpy(debSource, "Application"); - else if (source == _EXT_DEBUG_SOURCE_OTHER_ARB) - strcpy(debSource, "Other"); - - if (type == _EXT_DEBUG_TYPE_ERROR_ARB) - strcpy(debType, "Error"); - else if (type == _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB) - strcpy(debType, "Deprecated behavior"); - else if (type == _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB) - strcpy(debType, "Undefined behavior"); - else if (type == _EXT_DEBUG_TYPE_PORTABILITY_ARB) - strcpy(debType, "Portability"); - else if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB) - strcpy(debType, "Performance"); - else if (type == _EXT_DEBUG_TYPE_OTHER_ARB) - strcpy(debType, "Other"); - - if (severity == _EXT_DEBUG_SEVERITY_HIGH_ARB) - strcpy(debSev, "High"); - else if (severity == _EXT_DEBUG_SEVERITY_MEDIUM_ARB) - strcpy(debSev, "Medium"); - else if (severity == _EXT_DEBUG_SEVERITY_LOW_ARB) - strcpy(debSev, "Low"); - - String output = String() + "GL ERROR: Source: " + debSource + "\tType: " + debType + "\tID: " + itos(id) + "\tSeverity: " + debSev + "\tMessage: " + message; - - ERR_PRINT(output); -} -#endif // CAN_DEBUG - -typedef void (*DEBUGPROCARB)(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const char *message, - const void *userParam); - -typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userParam); - -void RasterizerGLES2::initialize() { - print_verbose("Using GLES2 video driver"); - - storage._main_thread_id = Thread::get_caller_id(); - -#ifdef GLAD_ENABLED - if (!gladLoadGL()) { - ERR_PRINT("Error initializing GLAD"); - return; - } -#endif - -#ifdef GLAD_ENABLED - if (OS::get_singleton()->is_stdout_verbose()) { - if (GLAD_GL_ARB_debug_output) { - glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - glDebugMessageCallbackARB(_gl_debug_print, NULL); - glEnable(_EXT_DEBUG_OUTPUT); - } else { - print_line("OpenGL debugging not supported!"); - } - } -#endif // GLAD_ENABLED - - // For debugging -#ifdef CAN_DEBUG -#ifdef GLES_OVER_GL - if (OS::get_singleton()->is_stdout_verbose() && GLAD_GL_ARB_debug_output) { - glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_ERROR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); - glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); - glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); - glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_PORTABILITY_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); - glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_PERFORMANCE_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); - glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_OTHER_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); - // glDebugMessageInsertARB( - // GL_DEBUG_SOURCE_API_ARB, - // GL_DEBUG_TYPE_OTHER_ARB, 1, - // GL_DEBUG_SEVERITY_HIGH_ARB, 5, "hello"); - } -#else - if (OS::get_singleton()->is_stdout_verbose()) { - DebugMessageCallbackARB callback = (DebugMessageCallbackARB)eglGetProcAddress("glDebugMessageCallback"); - if (!callback) { - callback = (DebugMessageCallbackARB)eglGetProcAddress("glDebugMessageCallbackKHR"); - } - - if (callback) { - print_line("godot: ENABLING GL DEBUG"); - glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - callback(_gl_debug_print, NULL); - glEnable(_EXT_DEBUG_OUTPUT); - } - } -#endif // GLES_OVER_GL -#endif // CAN_DEBUG - - print_line("OpenGL ES 2.0 Renderer: " + GD_VS::get_singleton()->get_video_adapter_name()); - storage.initialize(); - canvas.initialize(); - // scene.initialize(); - - // make sure the OS knows to only access the renderer from the main thread - OS::get_singleton()->set_render_main_thread_mode(OS::RENDER_MAIN_THREAD_ONLY); -} - -RasterizerGLES2::RasterizerGLES2() { - canvas.storage = &storage; - canvas.scene_render = &scene; - storage.canvas = &canvas; - //scene.storage = &storage; - storage.scene = &scene; -} - -void RasterizerGLES2::prepare_for_blitting_render_targets() { -} - -void RasterizerGLES2::_blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect) { - ERR_FAIL_COND(storage.frame.current_rt); - - // print_line("_blit_render_target_to_screen " + itos (p_screen) + ", rect " + String(Variant(p_screen_rect))); - - RasterizerStorageGLES2::RenderTarget *rt = storage.render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - canvas._set_texture_rect_mode(true); - canvas.state.canvas_shader.set_custom_shader(0); - canvas.state.canvas_shader.bind(); - - canvas.canvas_begin(); - - glDisable(GL_BLEND); - glActiveTexture(GL_TEXTURE0 + storage.config.max_texture_image_units - 1); - if (rt->external.fbo != 0) { - glBindTexture(GL_TEXTURE_2D, rt->external.color); - } else { - glBindTexture(GL_TEXTURE_2D, rt->color); - } - canvas.draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1)); - glBindTexture(GL_TEXTURE_2D, 0); - - canvas.canvas_end(); -} - -// is this p_screen useless in a multi window environment? -void RasterizerGLES2::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { - // do this once off for all blits - storage.bind_framebuffer_system(); - - storage.frame.current_rt = nullptr; - - for (int i = 0; i < p_amount; i++) { - const BlitToScreen &blit = p_render_targets[i]; - - RID rid_rt = blit.render_target; - - Rect2 dst_rect = blit.dst_rect; - _blit_render_target_to_screen(rid_rt, dst_rect); - } -} - -void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { - if (p_image.is_null() || p_image->is_empty()) - return; - - int window_w = 640; //OS::get_singleton()->get_video_mode(0).width; - int window_h = 480; //OS::get_singleton()->get_video_mode(0).height; - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, window_w, window_h); - glDisable(GL_BLEND); - glDepthMask(GL_FALSE); - if (false) { - // if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) { - glClearColor(0.0, 0.0, 0.0, 0.0); - } else { - glClearColor(p_color.r, p_color.g, p_color.b, 1.0); - } - glClear(GL_COLOR_BUFFER_BIT); - - canvas.canvas_begin(); - - RID texture = storage.texture_create(); - //storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0); - storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), GD_RD::TEXTURE_TYPE_2D); - storage.texture_set_data(texture, p_image); - - Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); - Rect2 screenrect; - if (p_scale) { - if (window_w > window_h) { - //scale horizontally - screenrect.size.y = window_h; - screenrect.size.x = imgrect.size.x * window_h / imgrect.size.y; - screenrect.position.x = (window_w - screenrect.size.x) / 2; - - } else { - //scale vertically - screenrect.size.x = window_w; - screenrect.size.y = imgrect.size.y * window_w / imgrect.size.x; - screenrect.position.y = (window_h - screenrect.size.y) / 2; - } - } else { - screenrect = imgrect; - screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor(); - } - - RasterizerStorageGLES2::Texture *t = storage.texture_owner.getornull(texture); - glActiveTexture(GL_TEXTURE0 + storage.config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, t->tex_id); - canvas.draw_generic_textured_rect(screenrect, Rect2(0, 0, 1, 1)); - glBindTexture(GL_TEXTURE_2D, 0); - canvas.canvas_end(); - - storage.free(texture); - - end_frame(true); -} - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h deleted file mode 100644 index 3066dc421b..0000000000 --- a/drivers/gles2/rasterizer_gles2.h +++ /dev/null @@ -1,90 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "drivers/gles_common/rasterizer_version.h" -#include "rasterizer_canvas_gles2.h" -#include "rasterizer_scene_gles2.h" -#include "rasterizer_storage_gles2.h" -#include "servers/rendering/renderer_compositor.h" - -class RasterizerGLES2 : public RendererCompositor { -private: - uint64_t frame = 1; - float delta = 0; - - double time_total = 0.0; - double time_scale = 1.0; - -protected: - RasterizerCanvasGLES2 canvas; - RasterizerStorageGLES2 storage; - RasterizerSceneGLES2 scene; - - void _blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect); - -public: - RendererStorage *get_storage() { return &storage; } - RendererCanvasRender *get_canvas() { return &canvas; } - RendererSceneRender *get_scene() { return &scene; } - - void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true); - - void initialize(); - void begin_frame(double frame_step); - - void prepare_for_blitting_render_targets(); - void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount); - - void end_frame(bool p_swap_buffers); - - void finalize() {} - - static RendererCompositor *_create_current() { - return memnew(RasterizerGLES2); - } - - static void make_current() { - _create_func = _create_current; - } - - virtual bool is_low_end() const { return true; } - uint64_t get_frame_number() const { return frame; } - double get_frame_delta_time() const { return delta; } - - RasterizerGLES2(); - ~RasterizerGLES2() {} -}; - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp deleted file mode 100644 index 6ef0816934..0000000000 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ /dev/null @@ -1,3955 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_scene_gles2.h" -#ifdef GLES2_BACKEND_ENABLED - -#ifdef GODOT_3 - -#include "core/math/math_funcs.h" -#include "core/math/transform.h" -#include "core/os/os.h" -#include "core/project_settings.h" -#include "core/vmap.h" -#include "rasterizer_canvas_gles2.h" -#include "servers/camera/camera_feed.h" -#include "servers/visual/visual_server_raster.h" - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf -#endif - -#ifndef GLES_OVER_GL -#ifdef IPHONE_ENABLED -#include <OpenGLES/ES2/glext.h> -//void *glResolveMultisampleFramebufferAPPLE; - -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#endif -#endif - -static const GLenum _cube_side_enum[6] = { - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, -}; - -/* SHADOW ATLAS API */ - -RID RasterizerSceneGLES2::shadow_atlas_create() { - ShadowAtlas *shadow_atlas = memnew(ShadowAtlas); - shadow_atlas->fbo = 0; - shadow_atlas->depth = 0; - shadow_atlas->color = 0; - shadow_atlas->size = 0; - shadow_atlas->smallest_subdiv = 0; - - for (int i = 0; i < 4; i++) { - shadow_atlas->size_order[i] = i; - } - - return shadow_atlas_owner.make_rid(shadow_atlas); -} - -void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_COND(p_size < 0); - - p_size = next_power_of_2(p_size); - - if (p_size == shadow_atlas->size) - return; - - // erase the old atlast - if (shadow_atlas->fbo) { - if (storage->config.use_rgba_3d_shadows) { - glDeleteRenderbuffers(1, &shadow_atlas->depth); - } else { - glDeleteTextures(1, &shadow_atlas->depth); - } - glDeleteFramebuffers(1, &shadow_atlas->fbo); - if (shadow_atlas->color) { - glDeleteTextures(1, &shadow_atlas->color); - } - - shadow_atlas->fbo = 0; - shadow_atlas->depth = 0; - shadow_atlas->color = 0; - } - - // erase shadow atlast references from lights - for (Map<RID, uint32_t>::Element *E = shadow_atlas->shadow_owners.front(); E; E = E->next()) { - LightInstance *li = light_instance_owner.getornull(E->key()); - ERR_CONTINUE(!li); - li->shadow_atlases.erase(p_atlas); - } - - shadow_atlas->shadow_owners.clear(); - - shadow_atlas->size = p_size; - - if (shadow_atlas->size) { - glGenFramebuffers(1, &shadow_atlas->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo); - - // create a depth texture - glActiveTexture(GL_TEXTURE0); - - if (storage->config.use_rgba_3d_shadows) { - //maximum compatibility, renderbuffer and RGBA shadow - glGenRenderbuffers(1, &shadow_atlas->depth); - glBindRenderbuffer(GL_RENDERBUFFER, shadow_atlas->depth); - glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadow_atlas->depth); - - glGenTextures(1, &shadow_atlas->color); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shadow_atlas->size, shadow_atlas->size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_atlas->color, 0); - } else { - //just depth texture - glGenTextures(1, &shadow_atlas->depth); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0); - } - glViewport(0, 0, shadow_atlas->size, shadow_atlas->size); - - glDepthMask(GL_TRUE); - - glClearDepth(0.0f); - glClear(GL_DEPTH_BUFFER_BIT); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } -} - -void RasterizerSceneGLES2::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_INDEX(p_quadrant, 4); - ERR_FAIL_INDEX(p_subdivision, 16384); - - uint32_t subdiv = next_power_of_2(p_subdivision); - if (subdiv & 0xaaaaaaaa) { // sqrt(subdiv) must be integer - subdiv <<= 1; - } - - subdiv = int(Math::sqrt((float)subdiv)); - - if (shadow_atlas->quadrants[p_quadrant].shadows.size() == (int)subdiv) - return; - - // erase all data from the quadrant - for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) { - if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) { - shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); - - LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); - ERR_CONTINUE(!li); - li->shadow_atlases.erase(p_atlas); - } - } - - shadow_atlas->quadrants[p_quadrant].shadows.resize(0); - shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv); - shadow_atlas->quadrants[p_quadrant].subdivision = subdiv; - - // cache the smallest subdivision for faster allocations - - shadow_atlas->smallest_subdiv = 1 << 30; - - for (int i = 0; i < 4; i++) { - if (shadow_atlas->quadrants[i].subdivision) { - shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision); - } - } - - if (shadow_atlas->smallest_subdiv == 1 << 30) { - shadow_atlas->smallest_subdiv = 0; - } - - // re-sort the quadrants - - int swaps = 0; - do { - swaps = 0; - - for (int i = 0; i < 3; i++) { - if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) { - SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]); - swaps++; - } - } - - } while (swaps > 0); -} - -bool RasterizerSceneGLES2::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { - for (int i = p_quadrant_count - 1; i >= 0; i--) { - int qidx = p_in_quadrants[i]; - - if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { - return false; - } - - // look for an empty space - - int sc = shadow_atlas->quadrants[qidx].shadows.size(); - - ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptrw(); - - int found_free_idx = -1; // found a free one - int found_used_idx = -1; // found an existing one, must steal it - uint64_t min_pass = 0; // pass of the existing one, try to use the least recently - - for (int j = 0; j < sc; j++) { - if (!sarr[j].owner.is_valid()) { - found_free_idx = j; - break; - } - - LightInstance *sli = light_instance_owner.getornull(sarr[j].owner); - ERR_CONTINUE(!sli); - - if (sli->last_scene_pass != scene_pass) { - // was just allocated, don't kill it so soon, wait a bit... - - if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) { - continue; - } - - if (found_used_idx == -1 || sli->last_scene_pass < min_pass) { - found_used_idx = j; - min_pass = sli->last_scene_pass; - } - } - } - - if (found_free_idx == -1 && found_used_idx == -1) { - continue; // nothing found - } - - if (found_free_idx == -1 && found_used_idx != -1) { - found_free_idx = found_used_idx; - } - - r_quadrant = qidx; - r_shadow = found_free_idx; - - return true; - } - - return false; -} - -bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND_V(!shadow_atlas, false); - - LightInstance *li = light_instance_owner.getornull(p_light_intance); - ERR_FAIL_COND_V(!li, false); - - if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { - return false; - } - - uint32_t quad_size = shadow_atlas->size >> 1; - int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage)); - - int valid_quadrants[4]; - int valid_quadrant_count = 0; - int best_size = -1; - int best_subdiv = -1; - - for (int i = 0; i < 4; i++) { - int q = shadow_atlas->size_order[i]; - int sd = shadow_atlas->quadrants[q].subdivision; - - if (sd == 0) { - continue; - } - - int max_fit = quad_size / sd; - - if (best_size != -1 && max_fit > best_size) { - break; // what we asked for is bigger than this. - } - - valid_quadrants[valid_quadrant_count] = q; - valid_quadrant_count++; - - best_subdiv = sd; - - if (max_fit >= desired_fit) { - best_size = max_fit; - } - } - - ERR_FAIL_COND_V(valid_quadrant_count == 0, false); // no suitable block available - - uint64_t tick = OS::get_singleton()->get_ticks_msec(); - - if (shadow_atlas->shadow_owners.has(p_light_intance)) { - // light was already known! - - uint32_t key = shadow_atlas->shadow_owners[p_light_intance]; - uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; - - bool should_realloc = shadow_atlas->quadrants[q].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec); - - bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version; - - if (!should_realloc) { - shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; - return should_redraw; - } - - int new_quadrant; - int new_shadow; - - // find a better place - - if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) { - // found a better place - - ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; - if (sh->owner.is_valid()) { - // it is take but invalid, so we can take it - - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.get(sh->owner); - sli->shadow_atlases.erase(p_atlas); - } - - // erase previous - shadow_atlas->quadrants[q].shadows.write[s].version = 0; - shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); - - sh->owner = p_light_intance; - sh->alloc_tick = tick; - sh->version = p_light_version; - li->shadow_atlases.insert(p_atlas); - - // make a new key - key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; - - // update it in the map - shadow_atlas->shadow_owners[p_light_intance] = key; - - // make it dirty, so we redraw - return true; - } - - // no better place found, so we keep the current place - - shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; - - return should_redraw; - } - - int new_quadrant; - int new_shadow; - - if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) { - // found a better place - - ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; - if (sh->owner.is_valid()) { - // it is take but invalid, so we can take it - - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.get(sh->owner); - sli->shadow_atlases.erase(p_atlas); - } - - sh->owner = p_light_intance; - sh->alloc_tick = tick; - sh->version = p_light_version; - li->shadow_atlases.insert(p_atlas); - - // make a new key - uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; - - // update it in the map - shadow_atlas->shadow_owners[p_light_intance] = key; - - // make it dirty, so we redraw - return true; - } - - return false; -} - -void RasterizerSceneGLES2::set_directional_shadow_count(int p_count) { - directional_shadow.light_count = p_count; - directional_shadow.current_light = 0; -} - -int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance) { - ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0); - - int shadow_size; - - if (directional_shadow.light_count == 1) { - shadow_size = directional_shadow.size; - } else { - shadow_size = directional_shadow.size / 2; //more than 4 not supported anyway - } - - LightInstance *light_instance = light_instance_owner.getornull(p_light_intance); - ERR_FAIL_COND_V(!light_instance, 0); - - switch (light_instance->light_ptr->directional_shadow_mode) { - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: - break; //none - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: - shadow_size /= 2; - break; - } - - return shadow_size; -} -////////////////////////////////////////////////////// - -RID RasterizerSceneGLES2::reflection_atlas_create() { - return RID(); -} - -void RasterizerSceneGLES2::reflection_atlas_set_size(RID p_ref_atlas, int p_size) { -} - -void RasterizerSceneGLES2::reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) { -} - -//////////////////////////////////////////////////// - -RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) { - RasterizerStorageGLES2::ReflectionProbe *probe = storage->reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!probe, RID()); - - ReflectionProbeInstance *rpi = memnew(ReflectionProbeInstance); - - rpi->probe_ptr = probe; - rpi->self = reflection_probe_instance_owner.make_rid(rpi); - rpi->probe = p_probe; - rpi->reflection_atlas_index = -1; - rpi->render_step = -1; - rpi->last_pass = 0; - rpi->current_resolution = 0; - rpi->dirty = true; - - rpi->index = 0; - - for (int i = 0; i < 6; i++) { - glGenFramebuffers(1, &rpi->fbo[i]); - glGenTextures(1, &rpi->color[i]); - } - - glGenRenderbuffers(1, &rpi->depth); - - rpi->cubemap = 0; - //glGenTextures(1, &rpi->cubemap); - - return rpi->self; -} - -void RasterizerSceneGLES2::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!rpi); - rpi->transform = p_transform; -} - -void RasterizerSceneGLES2::reflection_probe_release_atlas_index(RID p_instance) { -} - -bool RasterizerSceneGLES2::reflection_probe_instance_needs_redraw(RID p_instance) { - const ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - bool need_redraw = rpi->probe_ptr->resolution != rpi->current_resolution || rpi->dirty || rpi->probe_ptr->update_mode == GD_VS::REFLECTION_PROBE_UPDATE_ALWAYS; - rpi->dirty = false; - return need_redraw; -} - -bool RasterizerSceneGLES2::reflection_probe_instance_has_reflection(RID p_instance) { - return true; -} - -bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - rpi->render_step = 0; - - if (rpi->probe_ptr->resolution != rpi->current_resolution) { - //update cubemap if resolution changed - int size = rpi->probe_ptr->resolution; - rpi->current_resolution = size; - - GLenum internal_format = GL_RGB; - GLenum format = GL_RGB; - GLenum type = GL_UNSIGNED_BYTE; - - glActiveTexture(GL_TEXTURE0); - - glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); - glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, size, size); - - if (rpi->cubemap != 0) { - glDeleteTextures(1, &rpi->cubemap); - } - - glGenTextures(1, &rpi->cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap); - - // Mobile hardware (PowerVR specially) prefers this approach, - // the previous approach with manual lod levels kills the game. - for (int i = 0; i < 6; i++) { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format, size, size, 0, format, type, NULL); - } - - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - - // Generate framebuffers for rendering - for (int i = 0; i < 6; i++) { - glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]); - glBindTexture(GL_TEXTURE_2D, rpi->color[i]); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size, 0, format, type, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rpi->color[i], 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); - } - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); - } - - return true; -} - -bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - ERR_FAIL_COND_V(rpi->current_resolution == 0, false); - - int size = rpi->probe_ptr->resolution; - - { - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - glDepthMask(GL_FALSE); - - for (int i = 0; i < GD_VS::ARRAY_MAX - 1; i++) { - glDisableVertexAttribArray(i); - } - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to - - //first of all, copy rendered textures to cubemap - for (int i = 0; i < 6; i++) { - glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]); - glViewport(0, 0, size, size); - glCopyTexSubImage2D(_cube_side_enum[i], 0, 0, 0, 0, 0, size, size); - } - //do filtering - //vdc cache - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->resources.radical_inverse_vdc_cache_tex); - - // now render to the framebuffer, mipmap level for mipmap level - int lod = 1; - - size >>= 1; - int mipmaps = 6; - - storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false); - storage->shaders.cubemap_filter.bind(); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->resources.mipmap_blur_fbo); - - //blur - while (size >= 1) { - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, storage->resources.mipmap_blur_color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, storage->resources.mipmap_blur_color, 0); - glViewport(0, 0, size, size); - glActiveTexture(GL_TEXTURE0); - - for (int i = 0; i < 6; i++) { - storage->bind_quad_array(); - storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i); - float roughness = CLAMP(lod / (float)(mipmaps - 1), 0, 1); - storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::ROUGHNESS, roughness); - storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glCopyTexSubImage2D(_cube_side_enum[i], lod, 0, 0, 0, 0, size, size); - } - - size >>= 1; - - lod++; - } - - // restore ranges - glActiveTexture(GL_TEXTURE0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE3); //back to panorama - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); - - return true; -} - -/* ENVIRONMENT API */ - -RID RasterizerSceneGLES2::environment_create() { - Environment *env = memnew(Environment); - - return environment_owner.make_rid(env); -} - -void RasterizerSceneGLES2::environment_set_background(RID p_env, GD_VS::EnvironmentBG p_bg) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->bg_mode = p_bg; -} - -void RasterizerSceneGLES2::environment_set_sky(RID p_env, RID p_sky) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->sky = p_sky; -} - -void RasterizerSceneGLES2::environment_set_sky_custom_fov(RID p_env, float p_scale) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->sky_custom_fov = p_scale; -} - -void RasterizerSceneGLES2::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->sky_orientation = p_orientation; -} - -void RasterizerSceneGLES2::environment_set_bg_color(RID p_env, const Color &p_color) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->bg_color = p_color; -} - -void RasterizerSceneGLES2::environment_set_bg_energy(RID p_env, float p_energy) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->bg_energy = p_energy; -} - -void RasterizerSceneGLES2::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->canvas_max_layer = p_max_layer; -} - -void RasterizerSceneGLES2::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_sky_contribution) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->ambient_color = p_color; - env->ambient_energy = p_energy; - env->ambient_sky_contribution = p_sky_contribution; -} - -void RasterizerSceneGLES2::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->camera_feed_id = p_camera_feed_id; -} - -void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, GD_VS::EnvironmentDOFBlurQuality p_quality) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->dof_blur_far_enabled = p_enable; - env->dof_blur_far_distance = p_distance; - env->dof_blur_far_transition = p_transition; - env->dof_blur_far_amount = p_amount; - env->dof_blur_far_quality = p_quality; -} - -void RasterizerSceneGLES2::environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, GD_VS::EnvironmentDOFBlurQuality p_quality) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->dof_blur_near_enabled = p_enable; - env->dof_blur_near_distance = p_distance; - env->dof_blur_near_transition = p_transition; - env->dof_blur_near_amount = p_amount; - env->dof_blur_near_quality = p_quality; -} - -void RasterizerSceneGLES2::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, GD_VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->glow_enabled = p_enable; - env->glow_levels = p_level_flags; - env->glow_intensity = p_intensity; - env->glow_strength = p_strength; - env->glow_bloom = p_bloom_threshold; - env->glow_blend_mode = p_blend_mode; - env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; - env->glow_hdr_bleed_scale = p_hdr_bleed_scale; - env->glow_hdr_luminance_cap = p_hdr_luminance_cap; - env->glow_bicubic_upscale = p_bicubic_upscale; -} - -void RasterizerSceneGLES2::environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); -} - -void RasterizerSceneGLES2::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); -} - -void RasterizerSceneGLES2::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, GD_VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); -} - -void RasterizerSceneGLES2::environment_set_tonemap(RID p_env, GD_VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); -} - -void RasterizerSceneGLES2::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->adjustments_enabled = p_enable; - env->adjustments_brightness = p_brightness; - env->adjustments_contrast = p_contrast; - env->adjustments_saturation = p_saturation; - env->color_correction = p_ramp; -} - -void RasterizerSceneGLES2::environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->fog_enabled = p_enable; - env->fog_color = p_color; - env->fog_sun_color = p_sun_color; - env->fog_sun_amount = p_sun_amount; -} - -void RasterizerSceneGLES2::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->fog_depth_enabled = p_enable; - env->fog_depth_begin = p_depth_begin; - env->fog_depth_end = p_depth_end; - env->fog_depth_curve = p_depth_curve; - env->fog_transmit_enabled = p_transmit; - env->fog_transmit_curve = p_transmit_curve; -} - -void RasterizerSceneGLES2::environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) { - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->fog_height_enabled = p_enable; - env->fog_height_min = p_min_height; - env->fog_height_max = p_max_height; - env->fog_height_curve = p_height_curve; -} -bool RasterizerSceneGLES2::is_environment(RID p_env) { - return environment_owner.owns(p_env); -} - -VS::EnvironmentBG RasterizerSceneGLES2::environment_get_background(RID p_env) { - const Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, GD_VS::ENV_BG_MAX); - - return env->bg_mode; -} - -int RasterizerSceneGLES2::environment_get_canvas_max_layer(RID p_env) { - const Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, -1); - - return env->canvas_max_layer; -} - -RID RasterizerSceneGLES2::light_instance_create(RID p_light) { - LightInstance *light_instance = memnew(LightInstance); - - light_instance->last_scene_pass = 0; - - light_instance->light = p_light; - light_instance->light_ptr = storage->light_owner.getornull(p_light); - - light_instance->light_index = 0xFFFF; - - if (!light_instance->light_ptr) { - memdelete(light_instance); - ERR_FAIL_V_MSG(RID(), "Condition ' !light_instance->light_ptr ' is true."); - } - - light_instance->self = light_instance_owner.make_rid(light_instance); - - return light_instance->self; -} - -void RasterizerSceneGLES2::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) { - LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->transform = p_transform; -} - -void RasterizerSceneGLES2::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) { - LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); - ERR_FAIL_COND(!light_instance); - - if (light_instance->light_ptr->type != GD_VS::LIGHT_DIRECTIONAL) { - p_pass = 0; - } - - ERR_FAIL_INDEX(p_pass, 4); - - light_instance->shadow_transform[p_pass].camera = p_projection; - light_instance->shadow_transform[p_pass].transform = p_transform; - light_instance->shadow_transform[p_pass].farplane = p_far; - light_instance->shadow_transform[p_pass].split = p_split; - light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale; -} - -void RasterizerSceneGLES2::light_instance_mark_visible(RID p_light_instance) { - LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->last_scene_pass = scene_pass; -} - -////////////////////// - -RID RasterizerSceneGLES2::gi_probe_instance_create() { - return RID(); -} - -void RasterizerSceneGLES2::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) { -} -void RasterizerSceneGLES2::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { -} - -void RasterizerSceneGLES2::gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) { -} - -//////////////////////////// -//////////////////////////// -//////////////////////////// - -void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass) { - RasterizerStorageGLES2::Material *material = NULL; - RID material_src; - - if (p_instance->material_override.is_valid()) { - material_src = p_instance->material_override; - } else if (p_material >= 0) { - material_src = p_instance->materials[p_material]; - } else { - material_src = p_geometry->material; - } - - if (material_src.is_valid()) { - material = storage->material_owner.getornull(material_src); - - if (!material->shader || !material->shader->valid) { - material = NULL; - } - } - - if (!material) { - material = storage->material_owner.getptr(default_material); - } - - ERR_FAIL_COND(!material); - - _add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass); - - while (material->next_pass.is_valid()) { - material = storage->material_owner.getornull(material->next_pass); - - if (!material || !material->shader || !material->shader->valid) { - break; - } - - _add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass); - } -} -void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass) { - bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture || p_material->shader->spatial.uses_depth_texture; - bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MIX; - bool has_alpha = has_base_alpha || has_blend_alpha; - - bool mirror = p_instance->mirror; - - if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED) { - mirror = false; - } else if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_FRONT) { - mirror = !mirror; - } - - //if (p_material->shader->spatial.uses_sss) { - // state.used_sss = true; - //} - - if (p_material->shader->spatial.uses_screen_texture) { - state.used_screen_texture = true; - } - - if (p_depth_pass) { - if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) - return; //bye - - if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { - //shader does not use discard and does not write a vertex position, use generic material - if (p_instance->cast_shadows == GD_VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { - p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material_twosided : default_material_twosided); - mirror = false; - } else { - p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material : default_material); - } - } - - has_alpha = false; - } - - RenderList::Element *e = (has_alpha || p_material->shader->spatial.no_depth_test) ? render_list.add_alpha_element() : render_list.add_element(); - - if (!e) { - return; - } - - e->geometry = p_geometry; - e->material = p_material; - e->instance = p_instance; - e->owner = p_owner; - e->sort_key = 0; - e->depth_key = 0; - e->use_accum = false; - e->light_index = RenderList::MAX_LIGHTS; - e->use_accum_ptr = &e->use_accum; - e->instancing = (e->instance->base_type == GD_VS::INSTANCE_MULTIMESH) ? 1 : 0; - e->front_facing = false; - - if (e->geometry->last_pass != render_pass) { - e->geometry->last_pass = render_pass; - e->geometry->index = current_geometry_index++; - } - - e->geometry_index = e->geometry->index; - - if (e->material->last_pass != render_pass) { - e->material->last_pass = render_pass; - e->material->index = current_material_index++; - - if (e->material->shader->last_pass != render_pass) { - e->material->shader->index = current_shader_index++; - } - } - - e->material_index = e->material->index; - - if (mirror) { - e->front_facing = true; - } - - e->refprobe_0_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default - e->refprobe_1_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default - - if (!p_depth_pass) { - e->depth_layer = e->instance->depth_layer; - e->priority = p_material->render_priority; - - if (has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { - //add element to opaque - RenderList::Element *eo = render_list.add_element(); - *eo = *e; - eo->use_accum_ptr = &eo->use_accum; - } - - int rpsize = e->instance->reflection_probe_instances.size(); - if (rpsize > 0) { - bool first = true; - rpsize = MIN(rpsize, 2); //more than 2 per object are not supported, this keeps it stable - - for (int i = 0; i < rpsize; i++) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(e->instance->reflection_probe_instances[i]); - if (rpi->last_pass != render_pass) { - continue; - } - if (first) { - e->refprobe_0_index = rpi->index; - first = false; - } else { - e->refprobe_1_index = rpi->index; - break; - } - } - - /* if (e->refprobe_0_index > e->refprobe_1_index) { //if both are valid, swap them to keep order as best as possible - uint64_t tmp = e->refprobe_0_index; - e->refprobe_0_index = e->refprobe_1_index; - e->refprobe_1_index = tmp; - }*/ - } - - //add directional lights - - if (p_material->shader->spatial.unshaded) { - e->light_mode = LIGHTMODE_UNSHADED; - } else { - bool copy = false; - - for (int i = 0; i < render_directional_lights; i++) { - if (copy) { - RenderList::Element *e2 = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); - if (!e2) { - break; - } - *e2 = *e; //this includes accum ptr :) - e = e2; - } - - //directional sort key - e->light_type1 = 0; - e->light_type2 = 1; - e->light_index = i; - - copy = true; - } - - //add omni / spots - - for (int i = 0; i < e->instance->light_instances.size(); i++) { - LightInstance *li = light_instance_owner.getornull(e->instance->light_instances[i]); - - if (!li || li->light_index >= render_light_instance_count || render_light_instances[li->light_index] != li) { - continue; // too many or light_index did not correspond to the light instances to be rendered - } - - if (copy) { - RenderList::Element *e2 = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); - if (!e2) { - break; - } - *e2 = *e; //this includes accum ptr :) - e = e2; - } - - //directional sort key - e->light_type1 = 1; - e->light_type2 = li->light_ptr->type == VisualServer::LIGHT_OMNI ? 0 : 1; - e->light_index = li->light_index; - - copy = true; - } - - if (e->instance->lightmap.is_valid()) { - e->light_mode = LIGHTMODE_LIGHTMAP; - } else if (!e->instance->lightmap_capture_data.empty()) { - e->light_mode = LIGHTMODE_LIGHTMAP_CAPTURE; - } else { - e->light_mode = LIGHTMODE_NORMAL; - } - } - } - - // do not add anything here, as lights are duplicated elements.. - - if (p_material->shader->spatial.uses_time) { - VisualServerRaster::redraw_request(); - } -} - -void RasterizerSceneGLES2::_copy_texture_to_buffer(GLuint p_texture, GLuint p_buffer) { - //copy to front buffer - glBindFramebuffer(GL_FRAMEBUFFER, p_buffer); - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, p_texture); - - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - - storage->shaders.copy.bind(); - - storage->bind_quad_array(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) { - render_pass++; - current_material_index = 0; - current_geometry_index = 0; - current_light_index = 0; - current_refprobe_index = 0; - current_shader_index = 0; - - for (int i = 0; i < p_cull_count; i++) { - InstanceBase *instance = p_cull_result[i]; - - switch (instance->base_type) { - case GD_VS::INSTANCE_MESH: { - RasterizerStorageGLES2::Mesh *mesh = storage->mesh_owner.getornull(instance->base); - ERR_CONTINUE(!mesh); - - int num_surfaces = mesh->surfaces.size(); - - for (int j = 0; j < num_surfaces; j++) { - int material_index = instance->materials[j].is_valid() ? j : -1; - - RasterizerStorageGLES2::Surface *surface = mesh->surfaces[j]; - - _add_geometry(surface, instance, NULL, material_index, p_depth_pass, p_shadow_pass); - } - - } break; - - case GD_VS::INSTANCE_MULTIMESH: { - RasterizerStorageGLES2::MultiMesh *multi_mesh = storage->multimesh_owner.getptr(instance->base); - ERR_CONTINUE(!multi_mesh); - - if (multi_mesh->size == 0 || multi_mesh->visible_instances == 0) - continue; - - RasterizerStorageGLES2::Mesh *mesh = storage->mesh_owner.getptr(multi_mesh->mesh); - if (!mesh) - continue; - - int ssize = mesh->surfaces.size(); - - for (int j = 0; j < ssize; j++) { - RasterizerStorageGLES2::Surface *s = mesh->surfaces[j]; - _add_geometry(s, instance, multi_mesh, -1, p_depth_pass, p_shadow_pass); - } - } break; - - case GD_VS::INSTANCE_IMMEDIATE: { - RasterizerStorageGLES2::Immediate *im = storage->immediate_owner.getptr(instance->base); - ERR_CONTINUE(!im); - - _add_geometry(im, instance, NULL, -1, p_depth_pass, p_shadow_pass); - - } break; - - default: { - } - } - } -} - -static const GLenum gl_primitive[] = { - GL_POINTS, - GL_LINES, - GL_LINE_STRIP, - GL_LINE_LOOP, - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN -}; - -void RasterizerSceneGLES2::_set_cull(bool p_front, bool p_disabled, bool p_reverse_cull) { - bool front = p_front; - if (p_reverse_cull) - front = !front; - - if (p_disabled != state.cull_disabled) { - if (p_disabled) - glDisable(GL_CULL_FACE); - else - glEnable(GL_CULL_FACE); - - state.cull_disabled = p_disabled; - } - - if (front != state.cull_front) { - glCullFace(front ? GL_FRONT : GL_BACK); - state.cull_front = front; - } -} - -bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_alpha_pass, Size2i p_skeleton_tex_size) { - // material parameters - - state.scene_shader.set_custom_shader(p_material->shader->custom_code_id); - - if (p_material->shader->spatial.uses_screen_texture && storage->frame.current_rt) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); - } - - if (p_material->shader->spatial.uses_depth_texture && storage->frame.current_rt) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - } - - bool shader_rebind = state.scene_shader.bind(); - - if (p_material->shader->spatial.no_depth_test || p_material->shader->spatial.uses_depth_texture) { - glDisable(GL_DEPTH_TEST); - } else { - glEnable(GL_DEPTH_TEST); - } - - switch (p_material->shader->spatial.depth_draw_mode) { - case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: - case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_OPAQUE: { - glDepthMask(!p_alpha_pass && !p_material->shader->spatial.uses_depth_texture); - } break; - case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALWAYS: { - glDepthMask(GL_TRUE && !p_material->shader->spatial.uses_depth_texture); - } break; - case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_NEVER: { - glDepthMask(GL_FALSE); - } break; - } - - int tc = p_material->textures.size(); - const Pair<StringName, RID> *textures = p_material->textures.ptr(); - - const ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptr(); - - state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size); - - state.current_main_tex = 0; - - for (int i = 0; i < tc; i++) { - glActiveTexture(GL_TEXTURE0 + i); - - RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second); - - if (!t) { - switch (texture_hints[i]) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); - } break; - default: { - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - } break; - } - - continue; - } - - if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies - VisualServerRaster::redraw_request(); - } - - t = t->get_ptr(); - -#ifdef TOOLS_ENABLED - if (t->detect_3d) { - t->detect_3d(t->detect_3d_ud); - } -#endif - -#ifdef TOOLS_ENABLED - if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) { - t->detect_normal(t->detect_normal_ud); - } -#endif - if (t->render_target) - t->render_target->used_in_frame = true; - - glBindTexture(t->target, t->tex_id); - if (i == 0) { - state.current_main_tex = t->tex_id; - } - } - state.scene_shader.use_material((void *)p_material); - - return shader_rebind; -} - -void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton) { - switch (p_element->instance->base_type) { - case GD_VS::INSTANCE_MESH: { - RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry); - - 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 < GD_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, CAST_INT_TO_UCHAR_PTR(s->attribs[i].offset)); - } else { - glDisableVertexAttribArray(i); - switch (i) { - case GD_VS::ARRAY_NORMAL: { - glVertexAttrib4f(GD_VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); - } break; - case GD_VS::ARRAY_COLOR: { - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - - } break; - default: { - } - } - } - } - - bool clear_skeleton_buffer = storage->config.use_skeleton_software; - - if (p_skeleton) { - if (!storage->config.use_skeleton_software) { - //use float texture workflow - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id); - } else { - //use transform buffer workflow - ERR_FAIL_COND(p_skeleton->use_2d); - - PoolVector<float> &transform_buffer = storage->resources.skeleton_transform_cpu_buffer; - - if (!s->attribs[VS::ARRAY_BONES].enabled || !s->attribs[VS::ARRAY_WEIGHTS].enabled) { - break; // the whole instance has a skeleton, but this surface is not affected by it. - } - - // 3 * vec4 per vertex - if (transform_buffer.size() < s->array_len * 12) { - transform_buffer.resize(s->array_len * 12); - } - - const size_t bones_offset = s->attribs[VS::ARRAY_BONES].offset; - const size_t bones_stride = s->attribs[VS::ARRAY_BONES].stride; - const size_t bone_weight_offset = s->attribs[VS::ARRAY_WEIGHTS].offset; - const size_t bone_weight_stride = s->attribs[VS::ARRAY_WEIGHTS].stride; - - { - PoolVector<float>::Write write = transform_buffer.write(); - float *buffer = write.ptr(); - - PoolVector<uint8_t>::Read vertex_array_read = s->data.read(); - const uint8_t *vertex_data = vertex_array_read.ptr(); - - for (int i = 0; i < s->array_len; i++) { - // do magic - - size_t bones[4]; - float bone_weight[4]; - - if (s->attribs[VS::ARRAY_BONES].type == GL_UNSIGNED_BYTE) { - // read as byte - const uint8_t *bones_ptr = vertex_data + bones_offset + (i * bones_stride); - bones[0] = bones_ptr[0]; - bones[1] = bones_ptr[1]; - bones[2] = bones_ptr[2]; - bones[3] = bones_ptr[3]; - } else { - // read as short - const uint16_t *bones_ptr = (const uint16_t *)(vertex_data + bones_offset + (i * bones_stride)); - bones[0] = bones_ptr[0]; - bones[1] = bones_ptr[1]; - bones[2] = bones_ptr[2]; - bones[3] = bones_ptr[3]; - } - - if (s->attribs[VS::ARRAY_WEIGHTS].type == GL_FLOAT) { - // read as float - const float *weight_ptr = (const float *)(vertex_data + bone_weight_offset + (i * bone_weight_stride)); - bone_weight[0] = weight_ptr[0]; - bone_weight[1] = weight_ptr[1]; - bone_weight[2] = weight_ptr[2]; - bone_weight[3] = weight_ptr[3]; - } else { - // read as half - const uint16_t *weight_ptr = (const uint16_t *)(vertex_data + bone_weight_offset + (i * bone_weight_stride)); - bone_weight[0] = (weight_ptr[0] / (float)0xFFFF); - bone_weight[1] = (weight_ptr[1] / (float)0xFFFF); - bone_weight[2] = (weight_ptr[2] / (float)0xFFFF); - bone_weight[3] = (weight_ptr[3] / (float)0xFFFF); - } - - Transform3D transform; - - Transform3D bone_transforms[4] = { - storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[0]), - storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[1]), - storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[2]), - storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[3]), - }; - - transform.origin = - bone_weight[0] * bone_transforms[0].origin + - bone_weight[1] * bone_transforms[1].origin + - bone_weight[2] * bone_transforms[2].origin + - bone_weight[3] * bone_transforms[3].origin; - - transform.basis = - bone_transforms[0].basis * bone_weight[0] + - bone_transforms[1].basis * bone_weight[1] + - bone_transforms[2].basis * bone_weight[2] + - bone_transforms[3].basis * bone_weight[3]; - - float row[3][4] = { - { transform.basis[0][0], transform.basis[0][1], transform.basis[0][2], transform.origin[0] }, - { transform.basis[1][0], transform.basis[1][1], transform.basis[1][2], transform.origin[1] }, - { transform.basis[2][0], transform.basis[2][1], transform.basis[2][2], transform.origin[2] }, - }; - - size_t transform_buffer_offset = i * 12; - - copymem(&buffer[transform_buffer_offset], row, sizeof(row)); - } - } - - storage->_update_skeleton_transform_buffer(transform_buffer, s->array_len * 12); - - //enable transform buffer and bind it - glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer); - - glEnableVertexAttribArray(INSTANCE_BONE_BASE + 0); - glEnableVertexAttribArray(INSTANCE_BONE_BASE + 1); - glEnableVertexAttribArray(INSTANCE_BONE_BASE + 2); - - glVertexAttribPointer(INSTANCE_BONE_BASE + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 0)); - glVertexAttribPointer(INSTANCE_BONE_BASE + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 1)); - glVertexAttribPointer(INSTANCE_BONE_BASE + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 2)); - - clear_skeleton_buffer = false; - } - } - - if (clear_skeleton_buffer) { - glDisableVertexAttribArray(INSTANCE_BONE_BASE + 0); - glDisableVertexAttribArray(INSTANCE_BONE_BASE + 1); - glDisableVertexAttribArray(INSTANCE_BONE_BASE + 2); - } - - } break; - - case GD_VS::INSTANCE_MULTIMESH: { - RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry); - - 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 < GD_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, CAST_INT_TO_UCHAR_PTR(s->attribs[i].offset)); - } else { - glDisableVertexAttribArray(i); - switch (i) { - case GD_VS::ARRAY_NORMAL: { - glVertexAttrib4f(GD_VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); - } break; - case GD_VS::ARRAY_COLOR: { - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - - } break; - default: { - } - } - } - } - - // prepare multimesh (disable) - glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 0); - glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 1); - glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 2); - glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 3); - glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 4); - glDisableVertexAttribArray(INSTANCE_BONE_BASE + 0); - glDisableVertexAttribArray(INSTANCE_BONE_BASE + 1); - glDisableVertexAttribArray(INSTANCE_BONE_BASE + 2); - - } break; - - case GD_VS::INSTANCE_IMMEDIATE: { - } break; - - default: { - } - } -} - -void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { - switch (p_element->instance->base_type) { - case GD_VS::INSTANCE_MESH: { - RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry); - - // drawing - - 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); - storage->info.render.vertices_count += s->index_array_len; - } else { - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - storage->info.render.vertices_count += s->array_len; - } - /* - if (p_element->instance->skeleton.is_valid() && s->attribs[VS::ARRAY_BONES].enabled && s->attribs[VS::ARRAY_WEIGHTS].enabled) { - //clean up after skeleton - glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer); - - glDisableVertexAttribArray(GD_VS::ARRAY_MAX + 0); - glDisableVertexAttribArray(GD_VS::ARRAY_MAX + 1); - glDisableVertexAttribArray(GD_VS::ARRAY_MAX + 2); - - glVertexAttrib4f(GD_VS::ARRAY_MAX + 0, 1, 0, 0, 0); - glVertexAttrib4f(GD_VS::ARRAY_MAX + 1, 0, 1, 0, 0); - glVertexAttrib4f(GD_VS::ARRAY_MAX + 2, 0, 0, 1, 0); - } -*/ - } break; - - case GD_VS::INSTANCE_MULTIMESH: { - RasterizerStorageGLES2::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES2::MultiMesh *>(p_element->owner); - RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry); - - 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 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]); - glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 2, &buffer[8]); - } - - if (multi_mesh->color_floats) { - if (multi_mesh->color_format == GD_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); - } - } else { - glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0); - } - - if (multi_mesh->custom_data_floats) { - if (multi_mesh->custom_data_format == GD_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); - storage->info.render.vertices_count += s->index_array_len; - } else { - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - storage->info.render.vertices_count += s->array_len; - } - } - - } break; - - case GD_VS::INSTANCE_IMMEDIATE: { - const RasterizerStorageGLES2::Immediate *im = static_cast<const RasterizerStorageGLES2::Immediate *>(p_element->geometry); - - if (im->building) { - return; - } - - bool restore_tex = false; - - glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer); - - for (const List<RasterizerStorageGLES2::Immediate::Chunk>::Element *E = im->chunks.front(); E; E = E->next()) { - const RasterizerStorageGLES2::Immediate::Chunk &c = E->get(); - - if (c.vertices.empty()) { - continue; - } - - int vertices = c.vertices.size(); - - uint32_t buf_ofs = 0; - - storage->info.render.vertices_count += vertices; - - if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) { - RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(c.texture); - - if (t->redraw_if_visible) { - VisualServerRaster::redraw_request(); - } - t = t->get_ptr(); - -#ifdef TOOLS_ENABLED - if (t->detect_3d) { - t->detect_3d(t->detect_3d_ud); - } -#endif - if (t->render_target) { - t->render_target->used_in_frame = true; - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(t->target, t->tex_id); - restore_tex = true; - } else if (restore_tex) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, state.current_main_tex); - restore_tex = false; - } - - if (!c.normals.empty()) { - glEnableVertexAttribArray(GD_VS::ARRAY_NORMAL); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr()); - glVertexAttribPointer(GD_VS::ARRAY_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Vector3) * vertices; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_NORMAL); - } - - if (!c.tangents.empty()) { - glEnableVertexAttribArray(GD_VS::ARRAY_TANGENT); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr()); - glVertexAttribPointer(GD_VS::ARRAY_TANGENT, 4, GL_FLOAT, GL_FALSE, sizeof(Plane), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Plane) * vertices; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_TANGENT); - } - - if (!c.colors.empty()) { - glEnableVertexAttribArray(GD_VS::ARRAY_COLOR); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr()); - glVertexAttribPointer(GD_VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Color) * vertices; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_COLOR); - } - - if (!c.uvs.empty()) { - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs.ptr()); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Vector2) * vertices; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - } - - if (!c.uv2s.empty()) { - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV2); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uv2s.ptr()); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV2, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Vector2) * vertices; - } else { - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV2); - } - - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr()); - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - - glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size()); - } - - if (restore_tex) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, state.current_main_tex); - restore_tex = false; - } - - } break; - default: { - } - } -} - -void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas *shadow_atlas) { - //turn off all by default - state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, false); - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, false); - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_DIRECTIONAL, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false); - - if (!p_light) { //no light, return off - return; - } - - //turn on lighting - state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, true); - - switch (p_light->light_ptr->type) { - case GD_VS::LIGHT_DIRECTIONAL: { - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_DIRECTIONAL, true); - switch (p_light->light_ptr->directional_shadow_mode) { - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { - //no need - } break; - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true); - - } break; - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true); - } break; - } - - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, p_light->light_ptr->directional_blend_splits); - if (!state.render_no_shadows && p_light->light_ptr->shadow) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - if (storage->config.use_rgba_3d_shadows) { - glBindTexture(GL_TEXTURE_2D, directional_shadow.color); - } else { - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - } - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); - } - - } break; - case GD_VS::LIGHT_OMNI: { - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, true); - if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - if (storage->config.use_rgba_3d_shadows) { - glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); - } else { - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - } - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); - } - } break; - case GD_VS::LIGHT_SPOT: { - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, true); - if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - if (storage->config.use_rgba_3d_shadows) { - glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); - } else { - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - } - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); - state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); - } - } break; - } -} - -void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shadow_atlas, const Transform3D &p_view_transform, bool accum_pass) { - RasterizerStorageGLES2::Light *light_ptr = light->light_ptr; - - //common parameters - float energy = light_ptr->param[VS::LIGHT_PARAM_ENERGY]; - float specular = light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - float sign = (light_ptr->negative && !accum_pass) ? -1 : 1; //inverse color for base pass lights only - - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPECULAR, specular); - Color color = light_ptr->color * sign * energy * Math_PI; - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_COLOR, color); - - state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_COLOR, light_ptr->shadow_color); - - //specific parameters - - switch (light_ptr->type) { - case GD_VS::LIGHT_DIRECTIONAL: { - //not using inverse for performance, view should be normalized anyway - Vector3 direction = p_view_transform.basis.xform_inv(light->transform.basis.xform(Vector3(0, 0, -1))).normalized(); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction); - - CameraMatrix matrices[4]; - - if (!state.render_no_shadows && light_ptr->shadow && directional_shadow.depth) { - int shadow_count = 0; - Color split_offsets; - - switch (light_ptr->directional_shadow_mode) { - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { - shadow_count = 1; - } break; - - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { - shadow_count = 2; - } break; - - case GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { - shadow_count = 4; - } break; - } - - for (int k = 0; k < shadow_count; k++) { - uint32_t x = light->directional_rect.position.x; - uint32_t y = light->directional_rect.position.y; - uint32_t width = light->directional_rect.size.x; - uint32_t height = light->directional_rect.size.y; - - if (light_ptr->directional_shadow_mode == GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - width /= 2; - height /= 2; - - if (k == 1) { - x += width; - } else if (k == 2) { - y += height; - } else if (k == 3) { - x += width; - y += height; - } - - } else if (light_ptr->directional_shadow_mode == GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - height /= 2; - - if (k != 0) { - y += height; - } - } - - split_offsets[k] = light->shadow_transform[k].split; - - Transform3D modelview = (p_view_transform.inverse() * light->shadow_transform[k].transform).affine_inverse(); - - CameraMatrix bias; - bias.set_light_bias(); - CameraMatrix rectm; - Rect2 atlas_rect = Rect2(float(x) / directional_shadow.size, float(y) / directional_shadow.size, float(width) / directional_shadow.size, float(height) / directional_shadow.size); - rectm.set_light_atlas_rect(atlas_rect); - - CameraMatrix shadow_mtx = rectm * bias * light->shadow_transform[k].camera * modelview; - matrices[k] = shadow_mtx; - - /*Color light_clamp; - light_clamp[0] = atlas_rect.position.x; - light_clamp[1] = atlas_rect.position.y; - light_clamp[2] = atlas_rect.size.x; - light_clamp[3] = atlas_rect.size.y;*/ - } - - // state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp); - state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / directional_shadow.size, 1.0 / directional_shadow.size)); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPLIT_OFFSETS, split_offsets); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, matrices[0]); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX2, matrices[1]); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX3, matrices[2]); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX4, matrices[3]); - } - } break; - case GD_VS::LIGHT_OMNI: { - Vector3 position = p_view_transform.xform_inv(light->transform.origin); - - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position); - - float range = light_ptr->param[VS::LIGHT_PARAM_RANGE]; - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range); - - float attenuation = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation); - - if (!state.render_no_shadows && light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) { - uint32_t key = shadow_atlas->shadow_owners[light->self]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_BREAK(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size()); - - uint32_t atlas_size = shadow_atlas->size; - uint32_t quadrant_size = atlas_size >> 1; - - uint32_t x = (quadrant & 1) * quadrant_size; - uint32_t y = (quadrant >> 1) * quadrant_size; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - - uint32_t width = shadow_size; - uint32_t height = shadow_size; - - if (light->light_ptr->omni_shadow_detail == GD_VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { - height /= 2; - } else { - width /= 2; - } - - Transform3D proj = (p_view_transform.inverse() * light->transform).inverse(); - - Color light_clamp; - light_clamp[0] = float(x) / atlas_size; - light_clamp[1] = float(y) / atlas_size; - light_clamp[2] = float(width) / atlas_size; - light_clamp[3] = float(height) / atlas_size; - - state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / shadow_atlas->size, 1.0 / shadow_atlas->size)); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, proj); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp); - } - } break; - - case GD_VS::LIGHT_SPOT: { - Vector3 position = p_view_transform.xform_inv(light->transform.origin); - - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position); - - Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized(); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction); - float attenuation = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - float range = light_ptr->param[VS::LIGHT_PARAM_RANGE]; - float spot_attenuation = light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; - float angle = light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE]; - angle = Math::cos(Math::deg2rad(angle)); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_RANGE, spot_attenuation); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ANGLE, angle); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range); - - if (!state.render_no_shadows && light->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) { - uint32_t key = shadow_atlas->shadow_owners[light->self]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_BREAK(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size()); - - uint32_t atlas_size = shadow_atlas->size; - uint32_t quadrant_size = atlas_size >> 1; - - uint32_t x = (quadrant & 1) * quadrant_size; - uint32_t y = (quadrant >> 1) * quadrant_size; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - - uint32_t width = shadow_size; - uint32_t height = shadow_size; - - Rect2 rect(float(x) / atlas_size, float(y) / atlas_size, float(width) / atlas_size, float(height) / atlas_size); - - Color light_clamp; - light_clamp[0] = rect.position.x; - light_clamp[1] = rect.position.y; - light_clamp[2] = rect.size.x; - light_clamp[3] = rect.size.y; - - Transform3D modelview = (p_view_transform.inverse() * light->transform).inverse(); - - CameraMatrix bias; - bias.set_light_bias(); - - CameraMatrix rectm; - rectm.set_light_atlas_rect(rect); - - CameraMatrix shadow_matrix = rectm * bias * light->shadow_transform[0].camera * modelview; - - state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / shadow_atlas->size, 1.0 / shadow_atlas->size)); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, shadow_matrix); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp); - } - - } break; - default: { - } - } -} - -void RasterizerSceneGLES2::_setup_refprobes(ReflectionProbeInstance *p_refprobe1, ReflectionProbeInstance *p_refprobe2, const Transform3D &p_view_transform, Environment *p_env) { - if (p_refprobe1) { - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_USE_BOX_PROJECT, p_refprobe1->probe_ptr->box_projection); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_BOX_EXTENTS, p_refprobe1->probe_ptr->extents); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_BOX_OFFSET, p_refprobe1->probe_ptr->origin_offset); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_EXTERIOR, !p_refprobe1->probe_ptr->interior); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_INTENSITY, p_refprobe1->probe_ptr->intensity); - - Color ambient; - if (p_refprobe1->probe_ptr->interior) { - ambient = p_refprobe1->probe_ptr->interior_ambient * p_refprobe1->probe_ptr->interior_ambient_energy; - ambient.a = p_refprobe1->probe_ptr->interior_ambient_probe_contrib; - } else if (p_env) { - ambient = p_env->ambient_color * p_env->ambient_energy; - ambient.a = p_env->ambient_sky_contribution; - } - - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_AMBIENT, ambient); - - Transform3D proj = (p_view_transform.inverse() * p_refprobe1->transform).affine_inverse(); - - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_LOCAL_MATRIX, proj); - } - - if (p_refprobe2) { - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_USE_BOX_PROJECT, p_refprobe2->probe_ptr->box_projection); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_EXTENTS, p_refprobe2->probe_ptr->extents); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_OFFSET, p_refprobe2->probe_ptr->origin_offset); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_EXTERIOR, p_refprobe2->probe_ptr->interior); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_INTENSITY, p_refprobe2->probe_ptr->intensity); - - Color ambient; - if (p_refprobe2->probe_ptr->interior) { - ambient = p_refprobe2->probe_ptr->interior_ambient * p_refprobe2->probe_ptr->interior_ambient_energy; - ambient.a = p_refprobe2->probe_ptr->interior_ambient_probe_contrib; - } else if (p_env) { - ambient = p_env->ambient_color * p_env->ambient_energy; - ambient.a = p_env->ambient_sky_contribution; - } - - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_AMBIENT, ambient); - - Transform3D proj = (p_view_transform.inverse() * p_refprobe2->transform).affine_inverse(); - - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_LOCAL_MATRIX, proj); - } -} - -void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const Transform3D &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - - Vector2 viewport_size = state.viewport_size; - - Vector2 screen_pixel_size = state.screen_pixel_size; - - bool use_radiance_map = false; - if (!p_shadow && p_base_env) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); - glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env); - use_radiance_map = true; - state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, true); //since prev unshaded is false, this needs to be true if exists - } - - bool prev_unshaded = false; - bool prev_instancing = false; - bool prev_depth_prepass = false; - state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false); - RasterizerStorageGLES2::Material *prev_material = NULL; - RasterizerStorageGLES2::Geometry *prev_geometry = NULL; - RasterizerStorageGLES2::Skeleton *prev_skeleton = NULL; - RasterizerStorageGLES2::GeometryOwner *prev_owner = NULL; - - Transform3D view_transform_inverse = p_view_transform.inverse(); - CameraMatrix projection_inverse = p_projection.inverse(); - - bool prev_base_pass = false; - LightInstance *prev_light = NULL; - bool prev_vertex_lit = false; - ReflectionProbeInstance *prev_refprobe_1 = NULL; - ReflectionProbeInstance *prev_refprobe_2 = NULL; - - int prev_blend_mode = -2; //will always catch the first go - - state.cull_front = false; - state.cull_disabled = false; - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - - if (p_alpha_pass) { - glEnable(GL_BLEND); - } else { - glDisable(GL_BLEND); - } - - float fog_max_distance = 0; - bool using_fog = false; - if (p_env && !p_shadow && p_env->fog_enabled && (p_env->fog_depth_enabled || p_env->fog_height_enabled)) { - state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, p_env->fog_depth_enabled); - state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, p_env->fog_height_enabled); - if (p_env->fog_depth_end > 0) { - fog_max_distance = p_env->fog_depth_end; - } else { - fog_max_distance = p_projection.get_z_far(); - } - using_fog = true; - } - - RasterizerStorageGLES2::Texture *prev_lightmap = NULL; - float lightmap_energy = 1.0; - bool prev_use_lightmap_capture = false; - - storage->info.render.draw_call_count += p_element_count; - - for (int i = 0; i < p_element_count; i++) { - RenderList::Element *e = p_elements[i]; - - RasterizerStorageGLES2::Material *material = e->material; - - bool rebind = false; - bool accum_pass = *e->use_accum_ptr; - *e->use_accum_ptr = true; //set to accum for next time this is found - LightInstance *light = NULL; - ReflectionProbeInstance *refprobe_1 = NULL; - ReflectionProbeInstance *refprobe_2 = NULL; - RasterizerStorageGLES2::Texture *lightmap = NULL; - bool use_lightmap_capture = false; - bool rebind_light = false; - bool rebind_reflection = false; - bool rebind_lightmap = false; - - if (!p_shadow && material->shader) { - bool unshaded = material->shader->spatial.unshaded; - - if (unshaded != prev_unshaded) { - rebind = true; - if (unshaded) { - state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, true); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, false); - } else { - state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, use_radiance_map); - } - - prev_unshaded = unshaded; - } - - bool base_pass = !accum_pass && !unshaded; //conditions for a base pass - - if (base_pass != prev_base_pass) { - state.scene_shader.set_conditional(SceneShaderGLES2::BASE_PASS, base_pass); - rebind = true; - prev_base_pass = base_pass; - } - - if (!unshaded && e->light_index < RenderList::MAX_LIGHTS) { - light = render_light_instances[e->light_index]; - if (e->light_mode == LightMode::LIGHTMODE_LIGHTMAP && light->light_ptr->bake_mode == GD_VS::LIGHT_BAKE_ALL) { - light = NULL; // Don't use this light, it is already included in the lightmap - } - } - - if (light != prev_light) { - _setup_light_type(light, shadow_atlas); - rebind = true; - rebind_light = true; - } - - int blend_mode = p_alpha_pass ? material->shader->spatial.blend_mode : -1; // -1 no blend, no mix - - if (accum_pass) { //accum pass force pass - blend_mode = RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_ADD; - if (light && light->light_ptr->negative) { - blend_mode = RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_SUB; - } - } - - if (prev_blend_mode != blend_mode) { - if (prev_blend_mode == -1 && blend_mode != -1) { - //does blend - glEnable(GL_BLEND); - } else if (blend_mode == -1 && prev_blend_mode != -1) { - //do not blend - glDisable(GL_BLEND); - } - - switch (blend_mode) { - //-1 not handled because not blend is enabled anyway - case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - } break; - case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_ADD: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(p_alpha_pass ? GL_SRC_ALPHA : GL_ONE, GL_ONE); - - } break; - case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO); - } else { - glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE); - } - - } break; - } - - prev_blend_mode = blend_mode; - } - - //condition to enable vertex lighting on this object - bool vertex_lit = (material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading) && ((!unshaded && light) || using_fog); //fog forces vertex lighting because it still applies even if unshaded or no fog - - if (vertex_lit != prev_vertex_lit) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, vertex_lit); - prev_vertex_lit = vertex_lit; - rebind = true; - } - - if (!unshaded && !accum_pass && e->refprobe_0_index != RenderList::MAX_REFLECTION_PROBES) { - ERR_FAIL_INDEX(e->refprobe_0_index, reflection_probe_count); - refprobe_1 = reflection_probe_instances[e->refprobe_0_index]; - } - if (!unshaded && !accum_pass && e->refprobe_1_index != RenderList::MAX_REFLECTION_PROBES) { - ERR_FAIL_INDEX(e->refprobe_1_index, reflection_probe_count); - refprobe_2 = reflection_probe_instances[e->refprobe_1_index]; - } - - if (refprobe_1 != prev_refprobe_1 || refprobe_2 != prev_refprobe_2) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != NULL); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != NULL); - if (refprobe_1 != NULL && refprobe_1 != prev_refprobe_1) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); - glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap); - } - if (refprobe_2 != NULL && refprobe_2 != prev_refprobe_2) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); - glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap); - } - rebind = true; - rebind_reflection = true; - } - - use_lightmap_capture = !unshaded && !accum_pass && !e->instance->lightmap_capture_data.empty(); - - if (use_lightmap_capture != prev_use_lightmap_capture) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, use_lightmap_capture); - rebind = true; - } - - if (!unshaded && !accum_pass && e->instance->lightmap.is_valid()) { - lightmap = storage->texture_owner.getornull(e->instance->lightmap); - lightmap_energy = 1.0; - if (lightmap) { - RasterizerStorageGLES2::LightmapCapture *capture = storage->lightmap_capture_data_owner.getornull(e->instance->lightmap_capture->base); - if (capture) { - lightmap_energy = capture->energy; - } - } - } - - if (lightmap != prev_lightmap) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, lightmap != NULL); - if (lightmap != NULL) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, lightmap->tex_id); - } - rebind = true; - rebind_lightmap = true; - } - } - - bool depth_prepass = false; - - if (!p_alpha_pass && material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { - depth_prepass = true; - } - - if (depth_prepass != prev_depth_prepass) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, depth_prepass); - prev_depth_prepass = depth_prepass; - rebind = true; - } - - bool instancing = e->instance->base_type == GD_VS::INSTANCE_MULTIMESH; - - if (instancing != prev_instancing) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, instancing); - rebind = true; - } - - RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton); - - if (skeleton != prev_skeleton) { - if ((prev_skeleton == NULL) != (skeleton == NULL)) { - if (skeleton) { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, true); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, storage->config.use_skeleton_software); - } else { - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, false); - } - } - rebind = true; - } - - if (e->owner != prev_owner || e->geometry != prev_geometry || skeleton != prev_skeleton) { - _setup_geometry(e, skeleton); - storage->info.render.surface_switch_count++; - } - - bool shader_rebind = false; - if (rebind || material != prev_material) { - storage->info.render.material_switch_count++; - shader_rebind = _setup_material(material, p_alpha_pass, Size2i(skeleton ? skeleton->size * 3 : 0, 0)); - if (shader_rebind) { - storage->info.render.shader_rebind_count++; - } - } - - _set_cull(e->front_facing, material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED, p_reverse_cull); - - if (i == 0 || shader_rebind) { //first time must rebind - - if (p_shadow) { - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_BIAS, p_shadow_bias); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_NORMAL_BIAS, p_shadow_normal_bias); - if (state.shadow_is_dual_parabolloid) { - state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_DUAL_PARABOLOID_RENDER_SIDE, state.dual_parbolloid_direction); - state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_DUAL_PARABOLOID_RENDER_ZFAR, state.dual_parbolloid_zfar); - } - } else { - if (use_radiance_map) { - if (p_env) { - Transform3D sky_orientation(p_env->sky_orientation, Vector3(0.0, 0.0, 0.0)); - state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, sky_orientation.affine_inverse() * p_view_transform); - } else { - // would be a bit weird if we don't have this... - state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform); - } - } - - if (p_env) { - state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, p_env->bg_energy); - state.scene_shader.set_uniform(SceneShaderGLES2::BG_COLOR, p_env->bg_color); - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, p_env->ambient_sky_contribution); - - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, p_env->ambient_color); - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, p_env->ambient_energy); - - } else { - state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0); - state.scene_shader.set_uniform(SceneShaderGLES2::BG_COLOR, state.default_bg); - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0); - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, state.default_ambient); - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0); - } - - //rebind all these - rebind_light = true; - rebind_reflection = true; - rebind_lightmap = true; - - if (using_fog) { - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_COLOR_BASE, p_env->fog_color); - Color sun_color_amount = p_env->fog_sun_color; - sun_color_amount.a = p_env->fog_sun_amount; - - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_SUN_COLOR_AMOUNT, sun_color_amount); - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_TRANSMIT_ENABLED, p_env->fog_transmit_enabled); - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_TRANSMIT_CURVE, p_env->fog_transmit_curve); - - if (p_env->fog_depth_enabled) { - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_DEPTH_BEGIN, p_env->fog_depth_begin); - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_DEPTH_CURVE, p_env->fog_depth_curve); - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_MAX_DISTANCE, fog_max_distance); - } - - if (p_env->fog_height_enabled) { - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_MIN, p_env->fog_height_min); - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_MAX, p_env->fog_height_max); - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_MAX, p_env->fog_height_max); - state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_CURVE, p_env->fog_height_curve); - } - } - } - - state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform); - state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, view_transform_inverse); - state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection); - state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, projection_inverse); - - state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]); - - state.scene_shader.set_uniform(SceneShaderGLES2::VIEWPORT_SIZE, viewport_size); - - state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size); - } - - if (rebind_light && light) { - _setup_light(light, shadow_atlas, p_view_transform, accum_pass); - } - - if (rebind_reflection && (refprobe_1 || refprobe_2)) { - _setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env); - } - - if (rebind_lightmap && lightmap) { - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_ENERGY, lightmap_energy); - } - - state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform); - - if (use_lightmap_capture) { //this is per instance, must be set always if present - glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr()); - state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false); - } - - _render_geometry(e); - - prev_geometry = e->geometry; - prev_owner = e->owner; - prev_material = material; - prev_skeleton = skeleton; - prev_instancing = instancing; - prev_light = light; - prev_refprobe_1 = refprobe_1; - prev_refprobe_2 = refprobe_2; - prev_lightmap = lightmap; - prev_use_lightmap_capture = use_lightmap_capture; - } - - _setup_light_type(NULL, NULL); //clear light stuff - state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, false); - state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false); - state.scene_shader.set_conditional(SceneShaderGLES2::BASE_PASS, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false); - state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, false); - state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false); - state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false); - state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, false); -} - -void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation) { - ERR_FAIL_COND(!p_sky); - - RasterizerStorageGLES2::Texture *tex = storage->texture_owner.getornull(p_sky->panorama); - ERR_FAIL_COND(!tex); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(tex->target, tex->tex_id); - - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - - // Camera - CameraMatrix camera; - - if (p_custom_fov) { - float near_plane = p_projection.get_z_near(); - float far_plane = p_projection.get_z_far(); - float aspect = p_projection.get_aspect(); - - camera.set_perspective(p_custom_fov, aspect, near_plane, far_plane); - } else { - camera = p_projection; - } - - float flip_sign = p_vflip ? -1 : 1; - - // If matrix[2][0] or matrix[2][1] we're dealing with an asymmetrical projection matrix. This is the case for stereoscopic rendering (i.e. VR). - // To ensure the image rendered is perspective correct we need to move some logic into the shader. For this the USE_ASYM_PANO option is introduced. - // It also means the uv coordinates are ignored in this mode and we don't need our loop. - bool asymmetrical = ((camera.matrix[2][0] != 0.0) || (camera.matrix[2][1] != 0.0)); - - Vector3 vertices[8] = { - Vector3(-1, -1 * flip_sign, 1), - Vector3(0, 1, 0), - Vector3(1, -1 * flip_sign, 1), - Vector3(1, 1, 0), - Vector3(1, 1 * flip_sign, 1), - Vector3(1, 0, 0), - Vector3(-1, 1 * flip_sign, 1), - Vector3(0, 0, 0), - }; - - if (!asymmetrical) { - Vector2 vp_he = camera.get_viewport_half_extents(); - float zn; - zn = p_projection.get_z_near(); - - for (int i = 0; i < 4; i++) { - Vector3 uv = vertices[i * 2 + 1]; - uv.x = (uv.x * 2.0 - 1.0) * vp_he.x; - uv.y = -(uv.y * 2.0 - 1.0) * vp_he.y; - uv.z = -zn; - vertices[i * 2 + 1] = p_transform.basis.xform(uv).normalized(); - vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z; - } - } - - glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); - glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, vertices, GL_DYNAMIC_DRAW); - - // bind sky vertex array.... - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, CAST_INT_TO_UCHAR_PTR(sizeof(Vector3))); - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_ASYM_PANO, asymmetrical); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, !asymmetrical); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, true); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false); - storage->shaders.copy.bind(); - storage->shaders.copy.set_uniform(CopyShaderGLES2::MULTIPLIER, p_energy); - - // don't know why but I always have problems setting a uniform mat3, so we're using a transform - storage->shaders.copy.set_uniform(CopyShaderGLES2::SKY_TRANSFORM, Transform3D(p_sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse()); - - if (asymmetrical) { - // pack the bits we need from our projection matrix - storage->shaders.copy.set_uniform(CopyShaderGLES2::ASYM_PROJ, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1]); - ///@TODO I couldn't get mat3 + p_transform.basis to work, that would be better here. - storage->shaders.copy.set_uniform(CopyShaderGLES2::PANO_TRANSFORM, p_transform); - } - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glDisableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_ASYM_PANO, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false); -} - -void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p_cam_projection) { - //copy to front buffer - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - - //no post process on small, transparent or render targets without an env - bool use_post_process = env && !storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]; - use_post_process = use_post_process && storage->frame.current_rt->width >= 4 && storage->frame.current_rt->height >= 4; - use_post_process = use_post_process && storage->frame.current_rt->mip_maps_allocated; - - if (env) { - use_post_process = use_post_process && (env->adjustments_enabled || env->glow_enabled || env->dof_blur_far_enabled || env->dof_blur_near_enabled); - } - use_post_process = use_post_process || storage->frame.current_rt->use_fxaa; - - GLuint next_buffer; - - if (use_post_process) { - next_buffer = storage->frame.current_rt->mip_maps[0].sizes[0].fbo; - } else if (storage->frame.current_rt->external.fbo != 0) { - next_buffer = storage->frame.current_rt->external.fbo; - } else { - // set next_buffer to front buffer so multisample blit can happen if needed - next_buffer = storage->frame.current_rt->fbo; - } - - // If using multisample buffer, resolve to post_process_effect buffer or to front buffer - if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) { -#ifdef GLES_OVER_GL - - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, next_buffer); - glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); -#elif IPHONE_ENABLED - - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, next_buffer); - glResolveMultisampleFramebufferAPPLE(); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); -#elif ANDROID_ENABLED - - // In GLES2 Android Blit is not available, so just copy color texture manually - _copy_texture_to_buffer(storage->frame.current_rt->multisample_color, next_buffer); -#else - // TODO: any other platform not supported? this will fail.. maybe we should just call _copy_texture_to_buffer here as well? -#endif - } else if (use_post_process) { - if (storage->frame.current_rt->external.fbo != 0) { - _copy_texture_to_buffer(storage->frame.current_rt->external.color, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); - } else { - _copy_texture_to_buffer(storage->frame.current_rt->color, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); - } - } - - if (!use_post_process) { - return; - } - - // Order of operation - //1) DOF Blur (first blur, then copy to buffer applying the blur) //only on desktop - //2) FXAA - //3) Bloom (Glow) //only on desktop - //4) Adjustments - - // DOF Blur - - if (env && env->dof_blur_far_enabled) { - int vp_h = storage->frame.current_rt->height; - int vp_w = storage->frame.current_rt->width; - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_FAR_BLUR, true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_far_quality == GD_VS::ENV_DOF_BLUR_QUALITY_LOW); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == GD_VS::ENV_DOF_BLUR_QUALITY_MEDIUM); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_far_quality == GD_VS::ENV_DOF_BLUR_QUALITY_HIGH); - - state.effect_blur_shader.bind(); - int qsteps[3] = { 4, 10, 20 }; - - float radius = (env->dof_blur_far_amount * env->dof_blur_far_amount) / qsteps[env->dof_blur_far_quality]; - - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_BEGIN, env->dof_blur_far_distance); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_END, env->dof_blur_far_distance + env->dof_blur_far_transition); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(1, 0)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_RADIUS, radius); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - - glActiveTexture(GL_TEXTURE0); - - if (storage->frame.current_rt->mip_maps[0].color) { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first - - storage->_copy_screen(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(0, 1)); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); // copy to base level - storage->_copy_screen(); - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_FAR_BLUR, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, false); - } - - if (env && env->dof_blur_near_enabled) { - //convert texture to RGBA format if not already - if (!storage->frame.current_rt->used_dof_blur_near) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } - - int vp_h = storage->frame.current_rt->height; - int vp_w = storage->frame.current_rt->width; - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_BLUR, true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_FIRST_TAP, true); - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_near_quality == GD_VS::ENV_DOF_BLUR_QUALITY_LOW); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_near_quality == GD_VS::ENV_DOF_BLUR_QUALITY_MEDIUM); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_near_quality == GD_VS::ENV_DOF_BLUR_QUALITY_HIGH); - - state.effect_blur_shader.bind(); - int qsteps[3] = { 4, 10, 20 }; - - float radius = (env->dof_blur_near_amount * env->dof_blur_near_amount) / qsteps[env->dof_blur_near_quality]; - - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_BEGIN, env->dof_blur_near_distance); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(1, 0)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_RADIUS, radius); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - - glActiveTexture(GL_TEXTURE0); - if (storage->frame.current_rt->mip_maps[0].color) { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first - - storage->_copy_screen(); - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_FIRST_TAP, false); - state.effect_blur_shader.bind(); - - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_BEGIN, env->dof_blur_near_distance); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(0, 1)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_RADIUS, radius); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); // copy to base level - - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - storage->_copy_screen(); - - glDisable(GL_BLEND); - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_BLUR, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_FIRST_TAP, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, false); - storage->frame.current_rt->used_dof_blur_near = true; - } - - if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) { - //these needed to disable filtering, reenamble - glActiveTexture(GL_TEXTURE0); - if (storage->frame.current_rt->mip_maps[0].color) { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - - //glow - - int max_glow_level = -1; - int glow_mask = 0; - - if (env && env->glow_enabled) { - for (int i = 0; i < GD_VS::MAX_GLOW_LEVELS; i++) { - if (env->glow_levels & (1 << i)) { - if (i >= storage->frame.current_rt->mip_maps[1].sizes.size()) { - max_glow_level = storage->frame.current_rt->mip_maps[1].sizes.size() - 1; - glow_mask |= 1 << max_glow_level; - - } else { - max_glow_level = i; - glow_mask |= (1 << i); - } - } - } - - // If max_texture_image_units is 8, our max glow level is 5, which allows 6 layers of glow - max_glow_level = MIN(max_glow_level, storage->config.max_texture_image_units - 3); - - for (int i = 0; i < (max_glow_level + 1); i++) { - int vp_w = storage->frame.current_rt->mip_maps[1].sizes[i].width; - int vp_h = storage->frame.current_rt->mip_maps[1].sizes[i].height; - glViewport(0, 0, vp_w, vp_h); - //horizontal pass - if (i == 0) { - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::GLOW_FIRST_PASS, true); - } - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::GLOW_GAUSSIAN_HORIZONTAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::LOD, storage->frame.current_rt->mip_maps[0].color ? float(i) : 0.0); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_STRENGTH, env->glow_strength); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::LUMINANCE_CAP, env->glow_hdr_luminance_cap); - - glActiveTexture(GL_TEXTURE0); - - if (storage->frame.current_rt->mip_maps[0].color) { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[i].color); - } - - if (i == 0) { - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_BLOOM, env->glow_bloom); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_HDR_THRESHOLD, env->glow_hdr_bleed_threshold); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_HDR_SCALE, env->glow_hdr_bleed_scale); - } - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[1].sizes[i].fbo); - storage->_copy_screen(); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::GLOW_GAUSSIAN_HORIZONTAL, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::GLOW_FIRST_PASS, false); - - //vertical pass - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::GLOW_GAUSSIAN_VERTICAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::LOD, storage->frame.current_rt->mip_maps[0].color ? float(i) : 0.0); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::GLOW_STRENGTH, env->glow_strength); - glActiveTexture(GL_TEXTURE0); - - if (storage->frame.current_rt->mip_maps[0].color) { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[1].color); - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[1].sizes[i].color); - } - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger - storage->_copy_screen(); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::GLOW_GAUSSIAN_VERTICAL, false); - } - - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - } - - if (storage->frame.current_rt->external.fbo != 0) { - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->external.fbo); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); - } - - glActiveTexture(GL_TEXTURE0); - if (storage->frame.current_rt->mip_maps[0].color) { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color); - } - - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_FXAA, storage->frame.current_rt->use_fxaa); - - if (env) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_FILTER_BICUBIC, env->glow_bicubic_upscale); - - if (max_glow_level >= 0) { - if (storage->frame.current_rt->mip_maps[0].color) { - for (int i = 0; i < (max_glow_level + 1); i++) { - if (glow_mask & (1 << i)) { - if (i == 0) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL1, true); - } - if (i == 1) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL2, true); - } - if (i == 2) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL3, true); - } - if (i == 3) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL4, true); - } - if (i == 4) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL5, true); - } - if (i == 5) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL6, true); - } - if (i == 6) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL7, true); - } - } - } - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color); - } else { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_MULTI_TEXTURE_GLOW, true); - int active_glow_level = 0; - for (int i = 0; i < (max_glow_level + 1); i++) { - if (glow_mask & (1 << i)) { - active_glow_level++; - glActiveTexture(GL_TEXTURE1 + active_glow_level); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[i + 1].color); - if (active_glow_level == 1) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL1, true); - } - if (active_glow_level == 2) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL2, true); - } - if (active_glow_level == 3) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL3, true); - } - if (active_glow_level == 4) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL4, true); - } - if (active_glow_level == 5) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL5, true); - } - if (active_glow_level == 6) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL6, true); - } - if (active_glow_level == 7) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL7, true); - } - } - } - } - - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SCREEN, env->glow_blend_mode == GD_VS::GLOW_BLEND_MODE_SCREEN); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SOFTLIGHT, env->glow_blend_mode == GD_VS::GLOW_BLEND_MODE_SOFTLIGHT); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_REPLACE, env->glow_blend_mode == GD_VS::GLOW_BLEND_MODE_REPLACE); - } - } - - //Adjustments - if (env && env->adjustments_enabled) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_BCS, true); - RasterizerStorageGLES2::Texture *tex = storage->texture_owner.getornull(env->color_correction); - if (tex) { - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_COLOR_CORRECTION, true); - glActiveTexture(GL_TEXTURE1); - glBindTexture(tex->target, tex->tex_id); - } - } - - state.tonemap_shader.bind(); - if (env) { - if (max_glow_level >= 0) { - state.tonemap_shader.set_uniform(TonemapShaderGLES2::GLOW_INTENSITY, env->glow_intensity); - int ss[2] = { - storage->frame.current_rt->width, - storage->frame.current_rt->height, - }; - glUniform2iv(state.tonemap_shader.get_uniform(TonemapShaderGLES2::GLOW_TEXTURE_SIZE), 1, ss); - } - - if (env->adjustments_enabled) { - state.tonemap_shader.set_uniform(TonemapShaderGLES2::BCS, Vector3(env->adjustments_brightness, env->adjustments_contrast, env->adjustments_saturation)); - } - } - - if (storage->frame.current_rt->use_fxaa) { - state.tonemap_shader.set_uniform(TonemapShaderGLES2::PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); - } - - storage->_copy_screen(); - - //turn off everything used - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_FXAA, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL1, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL2, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL3, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL4, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL5, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL6, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_LEVEL7, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_REPLACE, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SCREEN, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SOFTLIGHT, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_FILTER_BICUBIC, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_MULTI_TEXTURE_GLOW, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_BCS, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_COLOR_CORRECTION, false); -} - -void RasterizerSceneGLES2::render_scene(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { - Transform3D cam_transform = p_cam_transform; - - storage->info.render.object_count += p_cull_count; - - GLuint current_fb = 0; - Environment *env = NULL; - - int viewport_width, viewport_height; - int viewport_x = 0; - int viewport_y = 0; - bool probe_interior = false; - bool reverse_cull = false; - - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_VFLIP]) { - cam_transform.basis.set_axis(1, -cam_transform.basis.get_axis(1)); - reverse_cull = true; - } - - if (p_reflection_probe.is_valid()) { - ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe); - ERR_FAIL_COND(!probe); - state.render_no_shadows = !probe->probe_ptr->enable_shadows; - - if (!probe->probe_ptr->interior) { //use env only if not interior - env = environment_owner.getornull(p_environment); - } - - current_fb = probe->fbo[p_reflection_probe_pass]; - - viewport_width = probe->probe_ptr->resolution; - viewport_height = probe->probe_ptr->resolution; - - probe_interior = probe->probe_ptr->interior; - - } else { - state.render_no_shadows = false; - if (storage->frame.current_rt->multisample_active) { - current_fb = storage->frame.current_rt->multisample_fbo; - } else if (storage->frame.current_rt->external.fbo != 0) { - current_fb = storage->frame.current_rt->external.fbo; - } else { - current_fb = storage->frame.current_rt->fbo; - } - env = environment_owner.getornull(p_environment); - - viewport_width = storage->frame.current_rt->width; - viewport_height = storage->frame.current_rt->height; - viewport_x = storage->frame.current_rt->x; - - if (storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { - viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y; - } else { - viewport_y = storage->frame.current_rt->y; - } - } - - state.used_screen_texture = false; - state.viewport_size.x = viewport_width; - state.viewport_size.y = viewport_height; - state.screen_pixel_size.x = 1.0 / viewport_width; - state.screen_pixel_size.y = 1.0 / viewport_height; - - //push back the directional lights - - if (p_light_cull_count) { - //hardcoded limit of 256 lights - render_light_instance_count = MIN(RenderList::MAX_LIGHTS, p_light_cull_count); - render_light_instances = (LightInstance **)alloca(sizeof(LightInstance *) * render_light_instance_count); - render_directional_lights = 0; - - //doing this because directional lights are at the end, put them at the beginning - int index = 0; - for (int i = render_light_instance_count - 1; i >= 0; i--) { - RID light_rid = p_light_cull_result[i]; - - LightInstance *light = light_instance_owner.getornull(light_rid); - - if (light->light_ptr->type == GD_VS::LIGHT_DIRECTIONAL) { - render_directional_lights++; - //as going in reverse, directional lights are always first anyway - } - - light->light_index = index; - render_light_instances[index] = light; - - index++; - } - - } else { - render_light_instances = NULL; - render_directional_lights = 0; - render_light_instance_count = 0; - } - - if (p_reflection_probe_cull_count) { - reflection_probe_instances = (ReflectionProbeInstance **)alloca(sizeof(ReflectionProbeInstance *) * p_reflection_probe_cull_count); - reflection_probe_count = p_reflection_probe_cull_count; - for (int i = 0; i < p_reflection_probe_cull_count; i++) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe_cull_result[i]); - ERR_CONTINUE(!rpi); - rpi->last_pass = render_pass + 1; //will be incremented later - rpi->index = i; - reflection_probe_instances[i] = rpi; - } - - } else { - reflection_probe_instances = NULL; - reflection_probe_count = 0; - } - - if (env && env->bg_mode == GD_VS::ENV_BG_CANVAS) { - // If using canvas background, copy 2d to screen copy texture - // TODO: When GLES2 renders to current_rt->mip_maps[], this copy will no longer be needed - _copy_texture_to_buffer(storage->frame.current_rt->color, storage->frame.current_rt->copy_screen_effect.fbo); - } - - // render list stuff - - render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, false, false); - - // other stuff - - glBindFramebuffer(GL_FRAMEBUFFER, current_fb); - glViewport(viewport_x, viewport_y, viewport_width, viewport_height); - - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { - glScissor(viewport_x, viewport_y, viewport_width, viewport_height); - glEnable(GL_SCISSOR_TEST); - } - - glDepthFunc(GL_LEQUAL); - glDepthMask(GL_TRUE); - glClearDepth(1.0f); - glEnable(GL_DEPTH_TEST); - glClear(GL_DEPTH_BUFFER_BIT); - - // clear color - - Color clear_color(0, 0, 0, 1); - Ref<CameraFeed> feed; - - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - clear_color = Color(0, 0, 0, 0); - storage->frame.clear_request = false; - } else if (!env || env->bg_mode == GD_VS::ENV_BG_CLEAR_COLOR || env->bg_mode == GD_VS::ENV_BG_SKY) { - if (storage->frame.clear_request) { - clear_color = storage->frame.clear_request_color; - storage->frame.clear_request = false; - } - } else if (env->bg_mode == GD_VS::ENV_BG_CANVAS || env->bg_mode == GD_VS::ENV_BG_COLOR || env->bg_mode == GD_VS::ENV_BG_COLOR_SKY) { - clear_color = env->bg_color; - storage->frame.clear_request = false; - } else if (env->bg_mode == GD_VS::ENV_BG_CAMERA_FEED) { - feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id); - storage->frame.clear_request = false; - } else { - storage->frame.clear_request = false; - } - - if (!env || env->bg_mode != GD_VS::ENV_BG_KEEP) { - glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a); - glClear(GL_COLOR_BUFFER_BIT); - } - - state.default_ambient = Color(clear_color.r, clear_color.g, clear_color.b, 1.0); - state.default_bg = Color(clear_color.r, clear_color.g, clear_color.b, 1.0); - - if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { - glDisable(GL_SCISSOR_TEST); - } - - glVertexAttrib4f(GD_VS::ARRAY_COLOR, 1, 1, 1, 1); - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // render sky - RasterizerStorageGLES2::Sky *sky = NULL; - GLuint env_radiance_tex = 0; - if (env) { - switch (env->bg_mode) { - case GD_VS::ENV_BG_COLOR_SKY: - case GD_VS::ENV_BG_SKY: { - sky = storage->sky_owner.getornull(env->sky); - - if (sky) { - env_radiance_tex = sky->radiance; - } - } break; - case GD_VS::ENV_BG_CAMERA_FEED: { - if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) { - // copy our camera feed to our background - - glDisable(GL_BLEND); - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, true); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_DISPLAY_TRANSFORM, true); - - if (feed->get_datatype() == CameraFeed::FEED_RGB) { - RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE); - - VS::get_singleton()->texture_bind(camera_RGBA, 0); - - } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR) { - RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCBCR_IMAGE); - - VS::get_singleton()->texture_bind(camera_YCbCr, 0); - - storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); - - } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR_SEP) { - RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE); - RID camera_CbCr = feed->get_texture(CameraServer::FEED_CBCR_IMAGE); - - VS::get_singleton()->texture_bind(camera_Y, 0); - VS::get_singleton()->texture_bind(camera_CbCr, 1); - - storage->shaders.copy.set_conditional(CopyShaderGLES2::SEP_CBCR_TEXTURE, true); - storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); - }; - - storage->shaders.copy.bind(); - storage->shaders.copy.set_uniform(CopyShaderGLES2::DISPLAY_TRANSFORM, feed->get_transform()); - - storage->bind_quad_array(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glDisableVertexAttribArray(GD_VS::ARRAY_TEX_UV); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // turn off everything used - storage->shaders.copy.set_conditional(CopyShaderGLES2::SEP_CBCR_TEXTURE, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_DISPLAY_TRANSFORM, false); - - //restore - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - } else { - // don't have a feed, just show greenscreen :) - clear_color = Color(0.0, 1.0, 0.0, 1.0); - } - } break; - case GD_VS::ENV_BG_CANVAS: { - // use screen copy as background - _copy_texture_to_buffer(storage->frame.current_rt->copy_screen_effect.color, current_fb); - } break; - default: { - } break; - } - } - - if (probe_interior) { - env_radiance_tex = 0; //do not use radiance texture on interiors - state.default_ambient = Color(0, 0, 0, 1); //black as default ambient for interior - state.default_bg = Color(0, 0, 0, 1); //black as default background for interior - } - - // render opaque things first - render_list.sort_by_key(false); - _render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, false, false); - - // then draw the sky after - if (env && env->bg_mode == GD_VS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT])) { - if (sky && sky->panorama.is_valid()) { - _draw_sky(sky, p_cam_projection, cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); - } - } - - if (storage->frame.current_rt && state.used_screen_texture) { - //copy screen texture - - if (storage->frame.current_rt->multisample_active) { - // Resolve framebuffer to front buffer before copying -#ifdef GLES_OVER_GL - - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); - glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); -#elif IPHONE_ENABLED - - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); - glResolveMultisampleFramebufferAPPLE(); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); -#elif ANDROID_ENABLED - - // In GLES2 AndroidBlit is not available, so just copy color texture manually - _copy_texture_to_buffer(storage->frame.current_rt->multisample_color, storage->frame.current_rt->fbo); -#endif - } - - storage->canvas->_copy_screen(Rect2()); - - if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) { - // Rebind the current framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, current_fb); - glViewport(0, 0, viewport_width, viewport_height); - } - } - // alpha pass - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - render_list.sort_by_reverse_depth_and_priority(true); - - _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, true, false); - - if (p_reflection_probe.is_valid()) { - // Rendering to a probe so no need for post_processing - return; - } - - //post process - _post_process(env, p_cam_projection); - - //#define GLES2_SHADOW_ATLAS_DEBUG_VIEW - -#ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - if (shadow_atlas) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - - glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, false); - storage->shaders.copy.bind(); - - storage->_copy_screen(); - } -#endif - - //#define GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW - -#ifdef GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW - if (true) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - - glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, false); - storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, false); - storage->shaders.copy.bind(); - - storage->_copy_screen(); - } -#endif -} - -void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { - state.render_no_shadows = false; - - LightInstance *light_instance = light_instance_owner.getornull(p_light); - ERR_FAIL_COND(!light_instance); - - RasterizerStorageGLES2::Light *light = light_instance->light_ptr; - ERR_FAIL_COND(!light); - - uint32_t x; - uint32_t y; - uint32_t width; - uint32_t height; - - float zfar = 0; - bool flip_facing = false; - int custom_vp_size = 0; - GLuint fbo = 0; - state.shadow_is_dual_parabolloid = false; - state.dual_parbolloid_direction = 0.0; - - int current_cubemap = -1; - float bias = 0; - float normal_bias = 0; - - CameraMatrix light_projection; - Transform3D light_transform; - - // TODO directional light - - if (light->type == GD_VS::LIGHT_DIRECTIONAL) { - // set pssm stuff - - // TODO set this only when changed - - light_instance->light_directional_index = directional_shadow.current_light; - light_instance->last_scene_shadow_pass = scene_pass; - - directional_shadow.current_light++; - - if (directional_shadow.light_count == 1) { - light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size); - } else if (directional_shadow.light_count == 2) { - light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size / 2); - if (light_instance->light_directional_index == 1) { - light_instance->directional_rect.position.x += light_instance->directional_rect.size.x; - } - } else { //3 and 4 - light_instance->directional_rect = Rect2(0, 0, directional_shadow.size / 2, directional_shadow.size / 2); - if (light_instance->light_directional_index & 1) { - light_instance->directional_rect.position.x += light_instance->directional_rect.size.x; - } - if (light_instance->light_directional_index / 2) { - light_instance->directional_rect.position.y += light_instance->directional_rect.size.y; - } - } - - light_projection = light_instance->shadow_transform[p_pass].camera; - light_transform = light_instance->shadow_transform[p_pass].transform; - - x = light_instance->directional_rect.position.x; - y = light_instance->directional_rect.position.y; - width = light_instance->directional_rect.size.width; - height = light_instance->directional_rect.size.height; - - if (light->directional_shadow_mode == GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - width /= 2; - height /= 2; - - if (p_pass == 1) { - x += width; - } else if (p_pass == 2) { - y += height; - } else if (p_pass == 3) { - x += width; - y += height; - } - - } else if (light->directional_shadow_mode == GD_VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - height /= 2; - - if (p_pass == 0) { - } else { - y += height; - } - } - - float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]); - zfar = light->param[VS::LIGHT_PARAM_RANGE]; - bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS] * bias_mult; - normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult; - - fbo = directional_shadow.fbo; - } else { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light)); - - fbo = shadow_atlas->fbo; - - uint32_t key = shadow_atlas->shadow_owners[p_light]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_FAIL_INDEX((int)shadow, shadow_atlas->quadrants[quadrant].shadows.size()); - - uint32_t quadrant_size = shadow_atlas->size >> 1; - - x = (quadrant & 1) * quadrant_size; - y = (quadrant >> 1) * quadrant_size; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - - width = shadow_size; - height = shadow_size; - - if (light->type == GD_VS::LIGHT_OMNI) { - // cubemap only - if (light->omni_shadow_mode == GD_VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) { - int cubemap_index = shadow_cubemaps.size() - 1; - - // find an appropriate cubemap to render to - for (int i = shadow_cubemaps.size() - 1; i >= 0; i--) { - if (shadow_cubemaps[i].size > shadow_size * 2) { - break; - } - - cubemap_index = i; - } - - fbo = shadow_cubemaps[cubemap_index].fbo[p_pass]; - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - custom_vp_size = shadow_cubemaps[cubemap_index].size; - zfar = light->param[VS::LIGHT_PARAM_RANGE]; - - current_cubemap = cubemap_index; - } else { - //dual parabolloid - state.shadow_is_dual_parabolloid = true; - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - if (light->omni_shadow_detail == GD_VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { - height /= 2; - y += p_pass * height; - } else { - width /= 2; - x += p_pass * width; - } - - state.dual_parbolloid_direction = p_pass == 0 ? 1.0 : -1.0; - flip_facing = (p_pass == 1); - zfar = light->param[VS::LIGHT_PARAM_RANGE]; - bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; - - state.dual_parbolloid_zfar = zfar; - - state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, true); - } - - } else if (light->type == GD_VS::LIGHT_SPOT) { - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - flip_facing = false; - zfar = light->param[VS::LIGHT_PARAM_RANGE]; - bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; - normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]; - } - } - - render_list.clear(); - - _fill_render_list(p_cull_result, p_cull_count, true, true); - - render_list.sort_by_depth(false); - - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glEnable(GL_DEPTH_TEST); - - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - glDepthMask(GL_TRUE); - if (!storage->config.use_rgba_3d_shadows) { - glColorMask(0, 0, 0, 0); - } - - if (custom_vp_size) { - glViewport(0, 0, custom_vp_size, custom_vp_size); - glScissor(0, 0, custom_vp_size, custom_vp_size); - } else { - glViewport(x, y, width, height); - glScissor(x, y, width, height); - } - - glEnable(GL_SCISSOR_TEST); - glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); - if (storage->config.use_rgba_3d_shadows) { - glClearColor(1.0, 1.0, 1.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - } - glDisable(GL_SCISSOR_TEST); - - if (light->reverse_cull) { - flip_facing = !flip_facing; - } - - state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true); - - _render_render_list(render_list.elements, render_list.element_count, light_transform, light_projection, RID(), NULL, 0, bias, normal_bias, flip_facing, false, true); - - state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, false); - state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false); - - // convert cubemap to dual paraboloid if needed - if (light->type == GD_VS::LIGHT_OMNI && (light->omni_shadow_mode == GD_VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) && p_pass == 5) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - - glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo); - state.cube_to_dp_shader.bind(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, shadow_cubemaps[current_cubemap].cubemap); - - glDisable(GL_CULL_FACE); - - for (int i = 0; i < 2; i++) { - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_FLIP, i == 1); - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_NEAR, light_projection.get_z_near()); - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_FAR, light_projection.get_z_far()); - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::BIAS, light->param[VS::LIGHT_PARAM_SHADOW_BIAS]); - - uint32_t local_width = width; - uint32_t local_height = height; - uint32_t local_x = x; - uint32_t local_y = y; - - if (light->omni_shadow_detail == GD_VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { - local_height /= 2; - local_y += i * local_height; - } else { - local_width /= 2; - local_x += i * local_width; - } - - glViewport(local_x, local_y, local_width, local_height); - glScissor(local_x, local_y, local_width, local_height); - - glEnable(GL_SCISSOR_TEST); - - glClearDepth(1.0f); - - glClear(GL_DEPTH_BUFFER_BIT); - glDisable(GL_SCISSOR_TEST); - - glDisable(GL_BLEND); - - storage->_copy_screen(); - } - } - - if (storage->frame.current_rt) { - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - } - if (!storage->config.use_rgba_3d_shadows) { - glColorMask(1, 1, 1, 1); - } -} - -void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) { - scene_pass = p_pass; -} - -bool RasterizerSceneGLES2::free(RID p_rid) { - if (light_instance_owner.owns(p_rid)) { - LightInstance *light_instance = light_instance_owner.getptr(p_rid); - - //remove from shadow atlases.. - for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(E->get()); - ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); - uint32_t key = shadow_atlas->shadow_owners[p_rid]; - uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; - - shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); - shadow_atlas->shadow_owners.erase(p_rid); - } - - light_instance_owner.free(p_rid); - memdelete(light_instance); - - } else if (shadow_atlas_owner.owns(p_rid)) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(p_rid); - shadow_atlas_set_size(p_rid, 0); - shadow_atlas_owner.free(p_rid); - memdelete(shadow_atlas); - } else if (reflection_probe_instance_owner.owns(p_rid)) { - ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid); - - for (int i = 0; i < 6; i++) { - glDeleteFramebuffers(1, &reflection_instance->fbo[i]); - glDeleteTextures(1, &reflection_instance->color[i]); - } - - if (reflection_instance->cubemap != 0) { - glDeleteTextures(1, &reflection_instance->cubemap); - } - glDeleteRenderbuffers(1, &reflection_instance->depth); - - reflection_probe_release_atlas_index(p_rid); - reflection_probe_instance_owner.free(p_rid); - memdelete(reflection_instance); - - } else { - return false; - } - - return true; -} - -void RasterizerSceneGLES2::set_debug_draw_mode(GD_VS::ViewportDebugDraw p_debug_draw) { -} - -void RasterizerSceneGLES2::initialize() { - state.scene_shader.init(); - - state.scene_shader.set_conditional(SceneShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_3d_shadows); - state.cube_to_dp_shader.init(); - state.effect_blur_shader.init(); - state.tonemap_shader.init(); - - render_list.init(); - - render_pass = 1; - - shadow_atlas_realloc_tolerance_msec = 500; - - { - //default material and shader - - default_shader = storage->shader_create(); - storage->shader_set_code(default_shader, "shader_type spatial;\n"); - default_material = storage->material_create(); - storage->material_set_shader(default_material, default_shader); - - default_shader_twosided = storage->shader_create(); - default_material_twosided = storage->material_create(); - storage->shader_set_code(default_shader_twosided, "shader_type spatial; render_mode cull_disabled;\n"); - storage->material_set_shader(default_material_twosided, default_shader_twosided); - } - - { - default_worldcoord_shader = storage->shader_create(); - storage->shader_set_code(default_worldcoord_shader, "shader_type spatial; render_mode world_vertex_coords;\n"); - default_worldcoord_material = storage->material_create(); - storage->material_set_shader(default_worldcoord_material, default_worldcoord_shader); - - default_worldcoord_shader_twosided = storage->shader_create(); - default_worldcoord_material_twosided = storage->material_create(); - storage->shader_set_code(default_worldcoord_shader_twosided, "shader_type spatial; render_mode cull_disabled,world_vertex_coords;\n"); - storage->material_set_shader(default_worldcoord_material_twosided, default_worldcoord_shader_twosided); - } - - { - //default material and shader - - default_overdraw_shader = storage->shader_create(); - storage->shader_set_code(default_overdraw_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }"); - default_overdraw_material = storage->material_create(); - storage->material_set_shader(default_overdraw_material, default_overdraw_shader); - } - - { - glGenBuffers(1, &state.sky_verts); - glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); - glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - { - uint32_t immediate_buffer_size = GLOBAL_DEF("rendering/limits/buffers/immediate_buffer_size_kb", 2048); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/immediate_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/immediate_buffer_size_kb", PROPERTY_HINT_RANGE, "0,8192,1,or_greater")); - - glGenBuffers(1, &state.immediate_buffer); - glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer); - glBufferData(GL_ARRAY_BUFFER, immediate_buffer_size * 1024, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - // cubemaps for shadows - if (storage->config.support_shadow_cubemaps) { //not going to be used - int max_shadow_cubemap_sampler_size = 512; - - int cube_size = max_shadow_cubemap_sampler_size; - - glActiveTexture(GL_TEXTURE0); - - while (cube_size >= 32) { - ShadowCubeMap cube; - - cube.size = cube_size; - - glGenTextures(1, &cube.cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap); - - for (int i = 0; i < 6; i++) { - glTexImage2D(_cube_side_enum[i], 0, storage->config.depth_internalformat, cube_size, cube_size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL); - } - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glGenFramebuffers(6, cube.fbo); - for (int i = 0; i < 6; i++) { - glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _cube_side_enum[i], cube.cubemap, 0); - } - - shadow_cubemaps.push_back(cube); - - cube_size >>= 1; - } - } - - { - // directional shadows - - directional_shadow.light_count = 0; - directional_shadow.size = next_power_of_2(GLOBAL_GET("rendering/quality/directional_shadow/size")); - - glGenFramebuffers(1, &directional_shadow.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo); - - if (storage->config.use_rgba_3d_shadows) { - //maximum compatibility, renderbuffer and RGBA shadow - glGenRenderbuffers(1, &directional_shadow.depth); - glBindRenderbuffer(GL_RENDERBUFFER, directional_shadow.depth); - glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_buffer_internalformat, directional_shadow.size, directional_shadow.size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, directional_shadow.depth); - - glGenTextures(1, &directional_shadow.color); - glBindTexture(GL_TEXTURE_2D, directional_shadow.color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, directional_shadow.size, directional_shadow.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, directional_shadow.color, 0); - } else { - //just a depth buffer - glGenTextures(1, &directional_shadow.depth); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - - glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0); - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - ERR_PRINT("Directional shadow framebuffer status invalid"); - } - } - - shadow_filter_mode = SHADOW_FILTER_NEAREST; - - glFrontFace(GL_CW); -} - -void RasterizerSceneGLES2::iteration() { - shadow_filter_mode = ShadowFilterMode(int(GLOBAL_GET("rendering/quality/shadows/filter_mode"))); -} - -void RasterizerSceneGLES2::finalize() { -} - -RasterizerSceneGLES2::RasterizerSceneGLES2() { -} - -#endif // godot 3 - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h deleted file mode 100644 index 2181186e71..0000000000 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ /dev/null @@ -1,793 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once -// dummy - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/math/camera_matrix.h" -#include "core/templates/rid_owner.h" -#include "core/templates/self_list.h" -#include "drivers/gles_common/rasterizer_common_stubs.h" -#include "scene/resources/mesh.h" -#include "servers/rendering/renderer_compositor.h" -#include "servers/rendering_server.h" -#include "shaders/scene.glsl.gen.h" - -class RasterizerSceneGLES2 : public StubsScene { -public: - struct State { - SceneShaderGLES2 scene_shader; - - } state; - -public: - RasterizerSceneGLES2() {} - ~RasterizerSceneGLES2() {} -}; - -#ifdef GODOT_3 - -/* Must come before shaders or the Windows build fails... */ -#include "drivers/gles_common/rasterizer_version.h" -#include "rasterizer_storage_gles2.h" - -#include "shaders/cube_to_dp.glsl.gen.h" -#include "shaders/effect_blur.glsl.gen.h" -#include "shaders/scene.glsl.gen.h" -#include "shaders/tonemap.glsl.gen.h" -/* - -#include "drivers/gles3/shaders/exposure.glsl.gen.h" -#include "drivers/gles3/shaders/resolve.glsl.gen.h" -#include "drivers/gles3/shaders/scene.glsl.gen.h" -#include "drivers/gles3/shaders/screen_space_reflection.glsl.gen.h" -#include "drivers/gles3/shaders/ssao.glsl.gen.h" -#include "drivers/gles3/shaders/ssao_blur.glsl.gen.h" -#include "drivers/gles3/shaders/ssao_minify.glsl.gen.h" -#include "drivers/gles3/shaders/subsurf_scattering.glsl.gen.h" - -*/ - -class RasterizerSceneGLES2 : public RasterizerScene { -public: - enum ShadowFilterMode { - SHADOW_FILTER_NEAREST, - SHADOW_FILTER_PCF5, - SHADOW_FILTER_PCF13, - }; - - enum { - INSTANCE_ATTRIB_BASE = 8, - INSTANCE_BONE_BASE = 13, - }; - - ShadowFilterMode shadow_filter_mode; - - RID default_material; - RID default_material_twosided; - RID default_shader; - RID default_shader_twosided; - - RID default_worldcoord_material; - RID default_worldcoord_material_twosided; - RID default_worldcoord_shader; - RID default_worldcoord_shader_twosided; - - RID default_overdraw_material; - RID default_overdraw_shader; - - uint64_t render_pass; - uint64_t scene_pass; - uint32_t current_material_index; - uint32_t current_geometry_index; - uint32_t current_light_index; - uint32_t current_refprobe_index; - uint32_t current_shader_index; - - RasterizerStorageGLES2 *storage; - struct State { - bool texscreen_copied; - int current_blend_mode; - float current_line_width; - int current_depth_draw; - bool current_depth_test; - GLuint current_main_tex; - - SceneShaderGLES2 scene_shader; - CubeToDpShaderGLES2 cube_to_dp_shader; - TonemapShaderGLES2 tonemap_shader; - EffectBlurShaderGLES2 effect_blur_shader; - - GLuint sky_verts; - - GLuint immediate_buffer; - Color default_ambient; - Color default_bg; - - // ResolveShaderGLES3 resolve_shader; - // ScreenSpaceReflectionShaderGLES3 ssr_shader; - // EffectBlurShaderGLES3 effect_blur_shader; - // SubsurfScatteringShaderGLES3 sss_shader; - // SsaoMinifyShaderGLES3 ssao_minify_shader; - // SsaoShaderGLES3 ssao_shader; - // SsaoBlurShaderGLES3 ssao_blur_shader; - // ExposureShaderGLES3 exposure_shader; - - /* - struct SceneDataUBO { - //this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes - float projection_matrix[16]; - float inv_projection_matrix[16]; - float camera_inverse_matrix[16]; - float camera_matrix[16]; - float ambient_light_color[4]; - float bg_color[4]; - float fog_color_enabled[4]; - float fog_sun_color_amount[4]; - - float ambient_energy; - float bg_energy; - float z_offset; - float z_slope_scale; - float shadow_dual_paraboloid_render_zfar; - float shadow_dual_paraboloid_render_side; - float viewport_size[2]; - float screen_pixel_size[2]; - float shadow_atlas_pixel_size[2]; - float shadow_directional_pixel_size[2]; - - float time; - float z_far; - float reflection_multiplier; - float subsurface_scatter_width; - float ambient_occlusion_affect_light; - - uint32_t fog_depth_enabled; - float fog_depth_begin; - float fog_depth_curve; - uint32_t fog_transmit_enabled; - float fog_transmit_curve; - uint32_t fog_height_enabled; - float fog_height_min; - float fog_height_max; - float fog_height_curve; - // make sure this struct is padded to be a multiple of 16 bytes for webgl - - } ubo_data; - - GLuint scene_ubo; - - struct EnvironmentRadianceUBO { - float transform[16]; - float ambient_contribution; - uint8_t padding[12]; - - } env_radiance_data; - - GLuint env_radiance_ubo; - - GLuint sky_array; - - GLuint directional_ubo; - - GLuint spot_array_ubo; - GLuint omni_array_ubo; - GLuint reflection_array_ubo; - - GLuint immediate_buffer; - GLuint immediate_array; - - uint32_t ubo_light_size; - uint8_t *spot_array_tmp; - uint8_t *omni_array_tmp; - uint8_t *reflection_array_tmp; - - int max_ubo_lights; - int max_forward_lights_per_object; - int max_ubo_reflections; - int max_skeleton_bones; - - bool used_contact_shadows; - - int spot_light_count; - int omni_light_count; - int directional_light_count; - int reflection_probe_count; - - bool used_sss; - bool using_contact_shadows; - - VS::ViewportDebugDraw debug_draw; - */ - - bool cull_front; - bool cull_disabled; - - bool used_screen_texture; - bool shadow_is_dual_parabolloid; - float dual_parbolloid_direction; - float dual_parbolloid_zfar; - - bool render_no_shadows; - - Vector2 viewport_size; - - Vector2 screen_pixel_size; - } state; - - /* SHADOW ATLAS API */ - - uint64_t shadow_atlas_realloc_tolerance_msec; - - struct ShadowAtlas : public RID_Data { - enum { - QUADRANT_SHIFT = 27, - SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1, - SHADOW_INVALID = 0xFFFFFFFF, - }; - - struct Quadrant { - uint32_t subdivision; - - struct Shadow { - RID owner; - uint64_t version; - uint64_t alloc_tick; - - Shadow() { - version = 0; - alloc_tick = 0; - } - }; - - Vector<Shadow> shadows; - - Quadrant() { - subdivision = 0; - } - } quadrants[4]; - - int size_order[4]; - uint32_t smallest_subdiv; - - int size; - - GLuint fbo; - GLuint depth; - GLuint color; - - Map<RID, uint32_t> shadow_owners; - }; - - struct ShadowCubeMap { - GLuint fbo[6]; - GLuint cubemap; - uint32_t size; - }; - - Vector<ShadowCubeMap> shadow_cubemaps; - - RID_Owner<ShadowAtlas> shadow_atlas_owner; - - RID shadow_atlas_create(); - void shadow_atlas_set_size(RID p_atlas, int p_size); - void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision); - bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); - bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version); - - struct DirectionalShadow { - GLuint fbo; - GLuint depth; - GLuint color; - - int light_count; - int size; - int current_light; - } directional_shadow; - - virtual int get_directional_light_shadow_size(RID p_light_intance); - virtual void set_directional_shadow_count(int p_count); - - /* REFLECTION PROBE ATLAS API */ - - virtual RID reflection_atlas_create(); - virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size); - virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv); - - /* REFLECTION CUBEMAPS */ - - /* REFLECTION PROBE INSTANCE */ - - struct ReflectionProbeInstance : public RID_Data { - RasterizerStorageGLES2::ReflectionProbe *probe_ptr; - RID probe; - RID self; - RID atlas; - - int reflection_atlas_index; - - int render_step; - int reflection_index; - - GLuint fbo[6]; - GLuint color[6]; - GLuint depth; - GLuint cubemap; - - int current_resolution; - mutable bool dirty; - - uint64_t last_pass; - uint32_t index; - - Transform3D transform; - }; - - mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner; - - ReflectionProbeInstance **reflection_probe_instances; - int reflection_probe_count; - - virtual RID reflection_probe_instance_create(RID p_probe); - virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform); - virtual void reflection_probe_release_atlas_index(RID p_instance); - virtual bool reflection_probe_instance_needs_redraw(RID p_instance); - virtual bool reflection_probe_instance_has_reflection(RID p_instance); - virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas); - virtual bool reflection_probe_instance_postprocess_step(RID p_instance); - - /* ENVIRONMENT API */ - - struct Environment : public RID_Data { - VS::EnvironmentBG bg_mode; - - RID sky; - float sky_custom_fov; - Basis sky_orientation; - - Color bg_color; - float bg_energy; - float sky_ambient; - - int camera_feed_id; - - Color ambient_color; - float ambient_energy; - float ambient_sky_contribution; - - int canvas_max_layer; - - bool glow_enabled; - int glow_levels; - float glow_intensity; - float glow_strength; - float glow_bloom; - VS::EnvironmentGlowBlendMode glow_blend_mode; - float glow_hdr_bleed_threshold; - float glow_hdr_bleed_scale; - float glow_hdr_luminance_cap; - bool glow_bicubic_upscale; - - bool dof_blur_far_enabled; - float dof_blur_far_distance; - float dof_blur_far_transition; - float dof_blur_far_amount; - VS::EnvironmentDOFBlurQuality dof_blur_far_quality; - - bool dof_blur_near_enabled; - float dof_blur_near_distance; - float dof_blur_near_transition; - float dof_blur_near_amount; - VS::EnvironmentDOFBlurQuality dof_blur_near_quality; - - bool adjustments_enabled; - float adjustments_brightness; - float adjustments_contrast; - float adjustments_saturation; - RID color_correction; - - bool fog_enabled; - Color fog_color; - Color fog_sun_color; - float fog_sun_amount; - - bool fog_depth_enabled; - float fog_depth_begin; - float fog_depth_end; - float fog_depth_curve; - bool fog_transmit_enabled; - float fog_transmit_curve; - bool fog_height_enabled; - float fog_height_min; - float fog_height_max; - float fog_height_curve; - - Environment() : - bg_mode(GD_VS::ENV_BG_CLEAR_COLOR), - sky_custom_fov(0.0), - bg_energy(1.0), - sky_ambient(0), - camera_feed_id(0), - ambient_energy(1.0), - ambient_sky_contribution(0.0), - canvas_max_layer(0), - glow_enabled(false), - glow_levels((1 << 2) | (1 << 4)), - glow_intensity(0.8), - glow_strength(1.0), - glow_bloom(0.0), - glow_blend_mode(GD_VS::GLOW_BLEND_MODE_SOFTLIGHT), - glow_hdr_bleed_threshold(1.0), - glow_hdr_bleed_scale(2.0), - glow_hdr_luminance_cap(12.0), - glow_bicubic_upscale(false), - dof_blur_far_enabled(false), - dof_blur_far_distance(10), - dof_blur_far_transition(5), - dof_blur_far_amount(0.1), - dof_blur_far_quality(GD_VS::ENV_DOF_BLUR_QUALITY_MEDIUM), - dof_blur_near_enabled(false), - dof_blur_near_distance(2), - dof_blur_near_transition(1), - dof_blur_near_amount(0.1), - dof_blur_near_quality(GD_VS::ENV_DOF_BLUR_QUALITY_MEDIUM), - adjustments_enabled(false), - adjustments_brightness(1.0), - adjustments_contrast(1.0), - adjustments_saturation(1.0), - fog_enabled(false), - fog_color(Color(0.5, 0.5, 0.5)), - fog_sun_color(Color(0.8, 0.8, 0.0)), - fog_sun_amount(0), - fog_depth_enabled(true), - fog_depth_begin(10), - fog_depth_end(0), - fog_depth_curve(1), - fog_transmit_enabled(true), - fog_transmit_curve(1), - fog_height_enabled(false), - fog_height_min(10), - fog_height_max(0), - fog_height_curve(1) { - } - }; - - mutable RID_Owner<Environment> environment_owner; - - virtual RID environment_create(); - - virtual void environment_set_background(RID p_env, GD_VS::EnvironmentBG p_bg); - virtual void environment_set_sky(RID p_env, RID p_sky); - virtual void environment_set_sky_custom_fov(RID p_env, float p_scale); - virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); - virtual void environment_set_bg_color(RID p_env, const Color &p_color); - virtual void environment_set_bg_energy(RID p_env, float p_energy); - virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); - virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); - - virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, GD_VS::EnvironmentDOFBlurQuality p_quality); - virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, GD_VS::EnvironmentDOFBlurQuality p_quality); - - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, GD_VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale); - virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture); - - virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness); - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, GD_VS::EnvironmentSSAOQuality p_quality, GD_VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); - - virtual void environment_set_tonemap(RID p_env, GD_VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); - - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp); - - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount); - virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve); - virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve); - - virtual bool is_environment(RID p_env); - - virtual GD_VS::EnvironmentBG environment_get_background(RID p_env); - virtual int environment_get_canvas_max_layer(RID p_env); - - /* LIGHT INSTANCE */ - - struct LightInstance : public RID_Data { - struct ShadowTransform { - CameraMatrix camera; - Transform3D transform; - float farplane; - float split; - float bias_scale; - }; - - ShadowTransform shadow_transform[4]; - - RID self; - RID light; - - RasterizerStorageGLES2::Light *light_ptr; - Transform3D transform; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - // TODO passes and all that stuff ? - uint64_t last_scene_pass; - uint64_t last_scene_shadow_pass; - - uint16_t light_index; - uint16_t light_directional_index; - - Rect2 directional_rect; - - Set<RID> shadow_atlases; // atlases where this light is registered - }; - - mutable RID_Owner<LightInstance> light_instance_owner; - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform); - virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0); - virtual void light_instance_mark_visible(RID p_light_instance); - virtual bool light_instances_can_render_shadow_cube() const { return storage->config.support_shadow_cubemaps; } - - LightInstance **render_light_instances; - int render_directional_lights; - int render_light_instance_count; - - /* REFLECTION INSTANCE */ - - virtual RID gi_probe_instance_create(); - virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data); - virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); - virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds); - - /* RENDER LIST */ - - enum LightMode { - LIGHTMODE_NORMAL, - LIGHTMODE_UNSHADED, - LIGHTMODE_LIGHTMAP, - LIGHTMODE_LIGHTMAP_CAPTURE, - }; - - struct RenderList { - enum { - MAX_LIGHTS = 255, - MAX_REFLECTION_PROBES = 255, - DEFAULT_MAX_ELEMENTS = 65536 - }; - - int max_elements; - - struct Element { - InstanceBaseDependency *instance; - - RasterizerStorageGLES2::Geometry *geometry; - RasterizerStorageGLES2::Material *material; - RasterizerStorageGLES2::GeometryOwner *owner; - - bool use_accum; //is this an add pass for multipass - bool *use_accum_ptr; - bool front_facing; - - union { - //TODO: should be endian swapped on big endian - struct { - int32_t depth_layer : 16; - int32_t priority : 16; - }; - - uint32_t depth_key; - }; - - union { - struct { - //from least significant to most significant in sort, TODO: should be endian swapped on big endian - - uint64_t geometry_index : 14; - uint64_t instancing : 1; - uint64_t skeleton : 1; - uint64_t shader_index : 10; - uint64_t material_index : 10; - uint64_t light_index : 8; - uint64_t light_type2 : 1; // if 1==0 : nolight/directional, else omni/spot - uint64_t refprobe_1_index : 8; - uint64_t refprobe_0_index : 8; - uint64_t light_type1 : 1; //no light, directional is 0, omni spot is 1 - uint64_t light_mode : 2; // LightMode enum - }; - - uint64_t sort_key; - }; - }; - - Element *base_elements; - Element **elements; - - int element_count; - int alpha_element_count; - - void clear() { - element_count = 0; - alpha_element_count = 0; - } - - // sorts - - struct SortByKey { - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - if (A->depth_key == B->depth_key) { - return A->sort_key < B->sort_key; - } else { - return A->depth_key < B->depth_key; - } - } - }; - - void sort_by_key(bool p_alpha) { - SortArray<Element *, SortByKey> sorter; - - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - struct SortByDepth { - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - return A->instance->depth < B->instance->depth; - } - }; - - void sort_by_depth(bool p_alpha) { //used for shadows - - SortArray<Element *, SortByDepth> sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - struct SortByReverseDepthAndPriority { - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - if (A->priority == B->priority) { - return A->instance->depth > B->instance->depth; - } else { - return A->priority < B->priority; - } - } - }; - - void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha - - SortArray<Element *, SortByReverseDepthAndPriority> sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - // element adding and stuff - - _FORCE_INLINE_ Element *add_element() { - if (element_count + alpha_element_count >= max_elements) - return NULL; - - elements[element_count] = &base_elements[element_count]; - return elements[element_count++]; - } - - _FORCE_INLINE_ Element *add_alpha_element() { - if (element_count + alpha_element_count >= max_elements) { - return NULL; - } - - int idx = max_elements - alpha_element_count - 1; - elements[idx] = &base_elements[idx]; - alpha_element_count++; - return elements[idx]; - } - - void init() { - element_count = 0; - alpha_element_count = 0; - - elements = memnew_arr(Element *, max_elements); - base_elements = memnew_arr(Element, max_elements); - - for (int i = 0; i < max_elements; i++) { - elements[i] = &base_elements[i]; - } - } - - RenderList() { - max_elements = DEFAULT_MAX_ELEMENTS; - } - - ~RenderList() { - memdelete_arr(elements); - memdelete_arr(base_elements); - } - }; - - RenderList render_list; - - void _add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass); - void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass); - - void _copy_texture_to_buffer(GLuint p_texture, GLuint p_buffer); - void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass); - void _render_render_list(RenderList::Element **p_elements, int p_element_count, - const Transform3D &p_view_transform, - const CameraMatrix &p_projection, - RID p_shadow_atlas, - Environment *p_env, - GLuint p_base_env, - float p_shadow_bias, - float p_shadow_normal_bias, - bool p_reverse_cull, - bool p_alpha_pass, - bool p_shadow); - - void _draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation); - - _FORCE_INLINE_ void _set_cull(bool p_front, bool p_disabled, bool p_reverse_cull); - _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_alpha_pass, Size2i p_skeleton_tex_size = Size2i(0, 0)); - _FORCE_INLINE_ void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton); - _FORCE_INLINE_ void _setup_light_type(LightInstance *p_light, ShadowAtlas *shadow_atlas); - _FORCE_INLINE_ void _setup_light(LightInstance *p_light, ShadowAtlas *shadow_atlas, const Transform3D &p_view_transform, bool accum_pass); - _FORCE_INLINE_ void _setup_refprobes(ReflectionProbeInstance *p_refprobe1, ReflectionProbeInstance *p_refprobe2, const Transform3D &p_view_transform, Environment *p_env); - _FORCE_INLINE_ void _render_geometry(RenderList::Element *p_element); - - void _post_process(Environment *env, const CameraMatrix &p_cam_projection); - - virtual void render_scene(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); - virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count); - virtual bool free(RID p_rid); - - virtual void set_scene_pass(uint64_t p_pass); - virtual void set_debug_draw_mode(GD_VS::ViewportDebugDraw p_debug_draw); - - void iteration(); - void initialize(); - void finalize(); - RasterizerSceneGLES2(); -}; - -#endif // godot 3 - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp deleted file mode 100644 index 046a9d5b96..0000000000 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ /dev/null @@ -1,3922 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -//#define GLES2_DISABLE_RENDER_TARGETS - -#include "rasterizer_storage_gles2.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/config/project_settings.h" -#include "core/math/transform_3d.h" -#include "drivers/gles_common/rasterizer_storage_common.h" -#include "rasterizer_canvas_gles2.h" -#include "rasterizer_scene_gles2.h" -#include "servers/rendering/shader_language.h" - -GLuint RasterizerStorageGLES2::system_fbo = 0; - -/* TEXTURE API */ - -#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - -#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB -#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC -#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE -#define _EXT_ETC1_RGB8_OES 0x8D64 - -#define _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 - -#define _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54 -#define _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55 -#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56 -#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57 - -#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C -#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D -#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E -#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F - -#define _GL_TEXTURE_EXTERNAL_OES 0x8D65 - -#ifdef GLES_OVER_GL -#define _GL_HALF_FLOAT_OES 0x140B -#else -#define _GL_HALF_FLOAT_OES 0x8D61 -#endif - -#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F - -#define _RED_OES 0x1903 - -#define _DEPTH_COMPONENT24_OES 0x81A6 - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf - -// enable extensions manually for android and ios -#ifndef UWP_ENABLED -#include <dlfcn.h> // needed to load extensions -#endif - -#ifdef IPHONE_ENABLED - -#include <OpenGLES/ES2/glext.h> -//void *glRenderbufferStorageMultisampleAPPLE; -//void *glResolveMultisampleFramebufferAPPLE; -#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE -#elif defined(ANDROID_ENABLED) - -#include <GLES2/gl2ext.h> -PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; -PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT; -#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT -#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT - -#elif defined(UWP_ENABLED) -#include <GLES2/gl2ext.h> -#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleANGLE -#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleANGLE -#endif - -#define GL_TEXTURE_3D 0x806F -#define GL_MAX_SAMPLES 0x8D57 -#endif //!GLES_OVER_GL - -void RasterizerStorageGLES2::bind_quad_array() const { - glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); - glVertexAttribPointer(GD_VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); - glVertexAttribPointer(GD_VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8)); - - glEnableVertexAttribArray(GD_VS::ARRAY_VERTEX); - glEnableVertexAttribArray(GD_VS::ARRAY_TEX_UV); -} - -Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { - r_gl_format = 0; - Ref<Image> image = p_image; - r_compressed = false; - r_real_format = p_format; - - bool need_decompress = false; - - switch (p_format) { - case Image::FORMAT_L8: { - r_gl_internal_format = GL_LUMINANCE; - r_gl_format = GL_LUMINANCE; - r_gl_type = GL_UNSIGNED_BYTE; - } break; - case Image::FORMAT_LA8: { - r_gl_internal_format = GL_LUMINANCE_ALPHA; - r_gl_format = GL_LUMINANCE_ALPHA; - r_gl_type = GL_UNSIGNED_BYTE; - } break; - case Image::FORMAT_R8: { - r_gl_internal_format = GL_ALPHA; - r_gl_format = GL_ALPHA; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RG8: { - ERR_PRINT("RG texture not supported, converting to RGB8."); - if (image.is_valid()) - image->convert(Image::FORMAT_RGB8); - r_real_format = Image::FORMAT_RGB8; - r_gl_internal_format = GL_RGB; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RGB8: { - r_gl_internal_format = GL_RGB; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RGBA8: { - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RGBA4444: { - r_gl_internal_format = GL_RGBA; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4; - - } break; - // case Image::FORMAT_RGBA5551: { - // r_gl_internal_format = GL_RGB5_A1; - // r_gl_format = GL_RGBA; - // r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1; - - // } break; - case Image::FORMAT_RF: { - if (!config.float_texture_supported) { - ERR_PRINT("R float texture not supported, converting to RGB8."); - if (image.is_valid()) - image->convert(Image::FORMAT_RGB8); - r_real_format = Image::FORMAT_RGB8; - r_gl_internal_format = GL_RGB; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - } else { - r_gl_internal_format = GL_ALPHA; - r_gl_format = GL_ALPHA; - r_gl_type = GL_FLOAT; - } - } break; - case Image::FORMAT_RGF: { - ERR_PRINT("RG float texture not supported, converting to RGB8."); - if (image.is_valid()) - image->convert(Image::FORMAT_RGB8); - r_real_format = Image::FORMAT_RGB8; - r_gl_internal_format = GL_RGB; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - } break; - case Image::FORMAT_RGBF: { - if (!config.float_texture_supported) { - ERR_PRINT("RGB float texture not supported, converting to RGB8."); - if (image.is_valid()) - image->convert(Image::FORMAT_RGB8); - r_real_format = Image::FORMAT_RGB8; - r_gl_internal_format = GL_RGB; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - } else { - r_gl_internal_format = GL_RGB; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - } - } break; - case Image::FORMAT_RGBAF: { - if (!config.float_texture_supported) { - ERR_PRINT("RGBA float texture not supported, converting to RGBA8."); - if (image.is_valid()) - image->convert(Image::FORMAT_RGBA8); - r_real_format = Image::FORMAT_RGBA8; - r_gl_internal_format = GL_RGBA; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - } else { - r_gl_internal_format = GL_RGBA; - r_gl_format = GL_RGBA; - r_gl_type = GL_FLOAT; - } - } break; - case Image::FORMAT_RH: { - need_decompress = true; - } break; - case Image::FORMAT_RGH: { - need_decompress = true; - } break; - case Image::FORMAT_RGBH: { - need_decompress = true; - } break; - case Image::FORMAT_RGBAH: { - need_decompress = true; - } break; - case Image::FORMAT_RGBE9995: { - r_gl_internal_format = GL_RGB; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - - if (image.is_valid()) - - image = image->rgbe_to_srgb(); - - return image; - - } break; - case Image::FORMAT_DXT1: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - } else { - need_decompress = true; - } - - } break; - case Image::FORMAT_DXT3: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - } else { - need_decompress = true; - } - - } break; - case Image::FORMAT_DXT5: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - } else { - need_decompress = true; - } - - } break; - case Image::FORMAT_RGTC_R: { - if (config.rgtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - - } break; - case Image::FORMAT_RGTC_RG: { - if (config.rgtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - } else { - need_decompress = true; - } - - } break; - case Image::FORMAT_BPTC_RGBA: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBF: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - r_compressed = true; - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBFU: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - r_compressed = true; - } else { - need_decompress = true; - } - } break; -#if 0 - // these have changed in the enum, no idea about PVR formats so left out for now - // FTODO - case Image::FORMAT_PVRTC2: { - if (config.pvrtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_PVRTC2A: { - if (config.pvrtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - - } break; - case Image::FORMAT_PVRTC4: { - if (config.pvrtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - - } break; - case Image::FORMAT_PVRTC4A: { - if (config.pvrtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - - } break; -#endif - case Image::FORMAT_ETC: { - if (config.etc1_supported) { - r_gl_internal_format = _EXT_ETC1_RGB8_OES; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_R11: { - need_decompress = true; - } break; - case Image::FORMAT_ETC2_R11S: { - need_decompress = true; - } break; - case Image::FORMAT_ETC2_RG11: { - need_decompress = true; - } break; - case Image::FORMAT_ETC2_RG11S: { - need_decompress = true; - } break; - case Image::FORMAT_ETC2_RGB8: { - need_decompress = true; - } break; - case Image::FORMAT_ETC2_RGBA8: { - need_decompress = true; - } break; - case Image::FORMAT_ETC2_RGB8A1: { - need_decompress = true; - } break; - default: { - ERR_FAIL_V(Ref<Image>()); - } - } - - if (need_decompress || p_force_decompress) { - if (!image.is_null()) { - image = image->duplicate(); - image->decompress(); - ERR_FAIL_COND_V(image->is_compressed(), image); - switch (image->get_format()) { - case Image::FORMAT_RGB8: { - r_gl_format = GL_RGB; - r_gl_internal_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGB8; - r_compressed = false; - } break; - case Image::FORMAT_RGBA8: { - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGBA8; - r_compressed = false; - } break; - default: { - image->convert(Image::FORMAT_RGBA8); - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGBA8; - r_compressed = false; - - } break; - } - } - - return image; - } - - return p_image; -} - -static const GLenum _cube_side_enum[6] = { - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, -}; - -RID RasterizerStorageGLES2::texture_allocate() { - RID id = texture_create(); - ERR_FAIL_COND_V(id == RID(), id); - return id; -} - -void RasterizerStorageGLES2::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { - // Texture *tex = texture_owner.getornull(p_texture); - // ERR_FAIL_COND(!tex); - - int w = p_image->get_width(); - int h = p_image->get_height(); - - _texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), GD_RD::TEXTURE_TYPE_2D, 0); - texture_set_data(p_texture, p_image); -} - -//RID RasterizerStorageGLES2::texture_2d_create(const Ref<Image> &p_image) { -// RID id = texture_create(); -// ERR_FAIL_COND_V(id == RID(), id); - -// int w = p_image->get_width(); -// int h = p_image->get_height(); - -// texture_allocate(id, w, h, 1, p_image->get_format(), GD_RD::TEXTURE_TYPE_2D, 0); - -// texture_set_data(id, p_image); - -// return id; -//} - -//RID RasterizerStorageGLES2::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { -// return RID(); -//} - -//RID RasterizerStorageGLES2::texture_proxy_create(RID p_base) { -// RID link = texture_create(); -// texture_set_proxy(link, p_base); -// return link; -//} - -//void RasterizerStorageGLES2::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) { -// // only 1 layer so far -// texture_set_data(p_texture, p_image); -//} -void RasterizerStorageGLES2::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { - // only 1 layer so far - texture_set_data(p_texture, p_image); -} - -//RID RasterizerStorageGLES2::texture_2d_placeholder_create() { -// return RID(); -//} - -Ref<Image> RasterizerStorageGLES2::texture_2d_get(RID p_texture) const { - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - - /* -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid()) { - return tex->image_cache_2d; - } -#endif - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instance(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - tex->image_cache_2d = image; - } -#endif -*/ - ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>()); - - return tex->images[0]; - - // return image; - - // return Ref<Image>(); -} - -void RasterizerStorageGLES2::texture_replace(RID p_texture, RID p_by_texture) { - Texture *tex_to = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex_to); - Texture *tex_from = texture_owner.getornull(p_by_texture); - ERR_FAIL_COND(!tex_from); - - tex_to->destroy(); - tex_to->copy_from(*tex_from); - - // copy image data and upload to GL - tex_to->images.resize(tex_from->images.size()); - - for (int n = 0; n < tex_from->images.size(); n++) { - texture_set_data(p_texture, tex_from->images[n], n); - } -} - -bool RasterizerStorageGLES2::_is_main_thread() { - //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED - // must be called from main thread in OpenGL - bool is_main_thread = _main_thread_id == Thread::get_caller_id(); - //#endif - return is_main_thread; -} - -RID RasterizerStorageGLES2::texture_create() { - ERR_FAIL_COND_V(!_is_main_thread(), RID()); - - Texture *texture = memnew(Texture); - ERR_FAIL_COND_V(!texture, RID()); - glGenTextures(1, &texture->tex_id); - texture->active = false; - texture->total_data_size = 0; - - return texture_owner.make_rid(texture); -} - -void RasterizerStorageGLES2::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, GD_RD::TextureType p_type, uint32_t p_flags) { - // GLenum format; - // GLenum internal_format; - // GLenum type; - - // bool compressed = false; - - if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video - } - - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - texture->width = p_width; - texture->height = p_height; - texture->format = p_format; - texture->flags = p_flags; - texture->stored_cube_sides = 0; - texture->type = p_type; - - switch (p_type) { - case GD_RD::TEXTURE_TYPE_2D: { - texture->target = GL_TEXTURE_2D; - texture->images.resize(1); - } break; - // case GD_RD::TEXTURE_TYPE_EXTERNAL: { - //#ifdef ANDROID_ENABLED - // texture->target = _GL_TEXTURE_EXTERNAL_OES; - //#else - // texture->target = GL_TEXTURE_2D; - //#endif - // texture->images.resize(0); - // } break; - case GD_RD::TEXTURE_TYPE_CUBE: { - texture->target = GL_TEXTURE_CUBE_MAP; - texture->images.resize(6); - } break; - case GD_RD::TEXTURE_TYPE_2D_ARRAY: - case GD_RD::TEXTURE_TYPE_3D: { - texture->target = GL_TEXTURE_3D; - ERR_PRINT("3D textures and Texture Arrays are not supported in GLES2. Please switch to the GLES3 backend."); - return; - } break; - default: { - ERR_PRINT("Unknown texture type!"); - return; - } - } - -#if 0 - // if (p_type != GD_VS::TEXTURE_TYPE_EXTERNAL) { - if (p_type == GD_RD::TEXTURE_TYPE_2D) { - texture->alloc_width = texture->width; - texture->alloc_height = texture->height; - texture->resize_to_po2 = false; - if (!config.support_npot_repeat_mipmap) { - int po2_width = next_power_of_2(p_width); - int po2_height = next_power_of_2(p_height); - - bool is_po2 = p_width == po2_width && p_height == po2_height; - - if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) { - if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - //not supported - ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled."); - texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS); - } else { - texture->alloc_height = po2_height; - texture->alloc_width = po2_width; - texture->resize_to_po2 = true; - } - } - } - - GLenum format; - GLenum internal_format; - GLenum type; - bool compressed = false; - - Image::Format real_format; - _get_gl_image_and_format(Ref<Image>(), - texture->format, - texture->flags, - real_format, - format, - internal_format, - type, - compressed, - texture->resize_to_po2); - - texture->gl_format_cache = format; - texture->gl_type_cache = type; - texture->gl_internal_format_cache = internal_format; - texture->data_size = 0; - texture->mipmaps = 1; - - texture->compressed = compressed; - } -#endif - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - // if (p_type == GD_VS::TEXTURE_TYPE_EXTERNAL) { - // glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - // glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // } else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - // //prealloc if video - // glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); - // } - - texture->active = true; -} - -void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND(!_is_main_thread()); - - ERR_FAIL_COND(!texture); - if (texture->target == GL_TEXTURE_3D) { - // Target is set to a 3D texture or array texture, exit early to avoid spamming errors - return; - } - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(texture->format != p_image->get_format()); - - ERR_FAIL_COND(!p_image->get_width()); - ERR_FAIL_COND(!p_image->get_height()); - - // ERR_FAIL_COND(texture->type == GD_VS::TEXTURE_TYPE_EXTERNAL); - - GLenum type; - GLenum format; - GLenum internal_format; - bool compressed = false; - - if (config.keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->images.write[p_layer] = p_image; - } - - // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height())); - - Image::Format real_format; - Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2); - - if (texture->resize_to_po2) { - if (p_image->is_compressed()) { - ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); - } - - if (img == p_image) { - img = img->duplicate(); - } - img->resize_to_po2(false); - } - - if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->alloc_height = MAX(1, texture->alloc_height / 2); - texture->alloc_width = MAX(1, texture->alloc_width / 2); - - if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) { - img->shrink_x2(); - } else if (img->get_format() <= Image::FORMAT_RGBA8) { - img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); - } - } - - GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D; - - texture->data_size = img->get_data().size(); - Vector<uint8_t> read = img->get_data(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - texture->ignore_mipmaps = compressed && !img->has_mipmaps(); - - // set filtering and repeat state - _texture_set_state_from_flags(texture); - - int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; - - int w = img->get_width(); - int h = img->get_height(); - - int tsize = 0; - - for (int i = 0; i < mipmaps; i++) { - int size, ofs; - img->get_mipmap_offset_and_size(i, ofs, size); - - if (compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - - int bw = w; - int bh = h; - - glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); - } else { - glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); - } - } - - tsize += size; - - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); - } - - info.texture_mem -= texture->total_data_size; - texture->total_data_size = tsize; - info.texture_mem += texture->total_data_size; - - // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); - - texture->stored_cube_sides |= (1 << p_layer); - - if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != GD_RD::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) { - //generate mipmaps if they were requested and the image does not contain them - glGenerateMipmap(texture->target); - } - - texture->mipmaps = mipmaps; -} - -void RasterizerStorageGLES2::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) { - // TODO - ERR_PRINT("Not implemented (ask Karroffel to do it :p)"); -} - -/* -Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, Ref<Image>()); - ERR_FAIL_COND_V(!texture->active, Ref<Image>()); - ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>()); - - if (texture->type == GD_VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) { - return texture->images[p_layer]; - } - -#ifdef GLES_OVER_GL - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - glActiveTexture(GL_TEXTURE0); - - glBindTexture(texture->target, texture->tex_id); - - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - for (int i = 0; i < texture->mipmaps; i++) { - int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i); - - if (texture->compressed) { - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetCompressedTexImage(texture->target, i, &wb[ofs]); - } else { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]); - } - } - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data)); - - return Ref<Image>(img); -#else - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - GLuint temp_framebuffer; - glGenFramebuffers(1, &temp_framebuffer); - - GLuint temp_color_texture; - glGenTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); - - glBindTexture(GL_TEXTURE_2D, temp_color_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - - glViewport(0, 0, texture->alloc_width, texture->alloc_height); - - shaders.copy.bind(); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - bind_quad_array(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); - - glDeleteTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &temp_framebuffer); - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); - if (!texture->compressed) { - img->convert(real_format); - } - - return Ref<Image>(img); - -#endif -} -*/ - -void RasterizerStorageGLES2::_texture_set_state_from_flags(Texture *p_tex) { - if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) - if (p_tex->flags & TEXTURE_FLAG_FILTER) { - // these do not exactly correspond ... - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); - //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); - } else { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); - //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR); - } - else { - if (p_tex->flags & TEXTURE_FLAG_FILTER) { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR); - //texture->glTexParam_MinFilter(texture->target, GL_LINEAR); - } else { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); - // texture->glTexParam_MinFilter(texture->target, GL_NEAREST); - } - } - - if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) { - if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) { - p_tex->GLSetRepeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); - } else { - p_tex->GLSetRepeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - } - } else { - p_tex->GLSetRepeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } -} - -void RasterizerStorageGLES2::texture_set_flags(RID p_texture, uint32_t p_flags) { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - - bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS; - - texture->flags = p_flags; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - // set filtering and repeat state - _texture_set_state_from_flags(texture); - - if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { - if (!had_mipmaps && texture->mipmaps == 1) { - glGenerateMipmap(texture->target); - } - } -} - -uint32_t RasterizerStorageGLES2::texture_get_flags(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->flags; -} - -Image::Format RasterizerStorageGLES2::texture_get_format(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, Image::FORMAT_L8); - - return texture->format; -} - -GD_RD::TextureType RasterizerStorageGLES2::texture_get_type(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, GD_RD::TEXTURE_TYPE_2D); - - return texture->type; -} - -uint32_t RasterizerStorageGLES2::texture_get_texid(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->tex_id; -} - -void RasterizerStorageGLES2::texture_bind(RID p_texture, uint32_t p_texture_no) { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND(!texture); - - glActiveTexture(GL_TEXTURE0 + p_texture_no); - glBindTexture(texture->target, texture->tex_id); -} - -uint32_t RasterizerStorageGLES2::texture_get_width(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->width; -} - -uint32_t RasterizerStorageGLES2::texture_get_height(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->height; -} - -uint32_t RasterizerStorageGLES2::texture_get_depth(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->depth; -} - -void RasterizerStorageGLES2::texture_set_size_override(RID p_texture, int p_width, int p_height) { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->render_target); - - ERR_FAIL_COND(p_width <= 0 || p_width > 16384); - ERR_FAIL_COND(p_height <= 0 || p_height > 16384); - //real texture size is in alloc width and height - texture->width = p_width; - texture->height = p_height; -} - -void RasterizerStorageGLES2::texture_set_path(RID p_texture, const String &p_path) { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - - texture->path = p_path; -} - -String RasterizerStorageGLES2::texture_get_path(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND_V(!texture, ""); - - return texture->path; -} - -void RasterizerStorageGLES2::texture_debug_usage(List<GD_VS::TextureInfo> *r_info) { - List<RID> textures; - texture_owner.get_owned_list(&textures); - - for (List<RID>::Element *E = textures.front(); E; E = E->next()) { - Texture *t = texture_owner.getornull(E->get()); - if (!t) - continue; - GD_VS::TextureInfo tinfo; - tinfo.path = t->path; - tinfo.format = t->format; - tinfo.width = t->alloc_width; - tinfo.height = t->alloc_height; - tinfo.depth = 0; - tinfo.bytes = t->total_data_size; - r_info->push_back(tinfo); - } -} - -void RasterizerStorageGLES2::texture_set_shrink_all_x2_on_set_data(bool p_enable) { - config.shrink_textures_x2 = p_enable; -} - -void RasterizerStorageGLES2::textures_keep_original(bool p_enable) { - config.keep_original_textures = p_enable; -} - -Size2 RasterizerStorageGLES2::texture_size_with_proxy(RID p_texture) { - const Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND_V(!texture, Size2()); - if (texture->proxy) { - return Size2(texture->proxy->width, texture->proxy->height); - } else { - return Size2(texture->width, texture->height); - } -} - -// example use in 3.2 -// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid); - -// p_proxy is the source (pre-existing) texture? -// and p_texture is the one that is being made into a proxy? -//This naming is confusing. Comments!!! - -// The naming of the parameters seemed to be reversed? -// The p_proxy is the source texture -// and p_texture is actually the proxy???? - -void RasterizerStorageGLES2::texture_set_proxy(RID p_texture, RID p_proxy) { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - - if (texture->proxy) { - texture->proxy->proxy_owners.erase(texture); - texture->proxy = NULL; - } - - if (p_proxy.is_valid()) { - Texture *proxy = texture_owner.getornull(p_proxy); - ERR_FAIL_COND(!proxy); - ERR_FAIL_COND(proxy == texture); - proxy->proxy_owners.insert(texture); - texture->proxy = proxy; - } -} - -void RasterizerStorageGLES2::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - - texture->redraw_if_visible = p_enable; -} - -void RasterizerStorageGLES2::texture_set_detect_3d_callback(RID p_texture, GD_VS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_3d = p_callback; - texture->detect_3d_ud = p_userdata; -} - -void RasterizerStorageGLES2::texture_set_detect_srgb_callback(RID p_texture, GD_VS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_srgb = p_callback; - texture->detect_srgb_ud = p_userdata; -} - -void RasterizerStorageGLES2::texture_set_detect_normal_callback(RID p_texture, GD_VS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_normal = p_callback; - texture->detect_normal_ud = p_userdata; -} - -RID RasterizerStorageGLES2::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { - return RID(); -} - -RID RasterizerStorageGLES2::sky_create() { - Sky *sky = memnew(Sky); - sky->radiance = 0; - return sky_owner.make_rid(sky); -} - -void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) { - Sky *sky = sky_owner.getornull(p_sky); - ERR_FAIL_COND(!sky); - - if (sky->panorama.is_valid()) { - sky->panorama = RID(); - glDeleteTextures(1, &sky->radiance); - sky->radiance = 0; - } - - sky->panorama = p_panorama; - if (!sky->panorama.is_valid()) { - return; // the panorama was cleared - } - - Texture *texture = texture_owner.getornull(sky->panorama); - if (!texture) { - sky->panorama = RID(); - ERR_FAIL_COND(!texture); - } - - // glBindVertexArray(0) and more - { - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - - for (int i = 0; i < GD_VS::ARRAY_MAX - 1; i++) { - glDisableVertexAttribArray(i); - } - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //need this for proper sampling - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - // New cubemap that will hold the mipmaps with different roughness values - glActiveTexture(GL_TEXTURE2); - glGenTextures(1, &sky->radiance); - glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance); - - int size = p_radiance_size / 2; //divide by two because its a cubemap (this is an approximation because GLES3 uses a dual paraboloid) - - GLenum internal_format = GL_RGB; - GLenum format = GL_RGB; - GLenum type = GL_UNSIGNED_BYTE; - - // Set the initial (empty) mipmaps - // Mobile hardware (PowerVR specially) prefers this approach, - // the previous approach with manual lod levels kills the game. - for (int i = 0; i < 6; i++) { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format, size, size, 0, format, type, NULL); - } - - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - - // No filters for now - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // Framebuffer - - bind_framebuffer(resources.mipmap_blur_fbo); - - int mipmaps = 6; - int lod = 0; - int mm_level = mipmaps; - size = p_radiance_size / 2; - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, true); - shaders.cubemap_filter.bind(); - - // third, render to the framebuffer using separate textures, then copy to mipmaps - while (size >= 1) { - //make framebuffer size the texture size, need to use a separate texture for compatibility - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, resources.mipmap_blur_color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resources.mipmap_blur_color, 0); - - if (lod == 1) { - //bind panorama for smaller lods - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false); - shaders.cubemap_filter.bind(); - } - glViewport(0, 0, size, size); - bind_quad_array(); - - glActiveTexture(GL_TEXTURE2); //back to panorama - - for (int i = 0; i < 6; i++) { - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i); - - float roughness = mm_level >= 0 ? lod / (float)(mipmaps - 1) : 1; - roughness = MIN(1.0, roughness); //keep max at 1 - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::ROUGHNESS, roughness); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glCopyTexSubImage2D(_cube_side_enum[i], lod, 0, 0, 0, 0, size, size); - } - - size >>= 1; - - mm_level--; - - lod++; - } - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false); - - // restore ranges - glActiveTexture(GL_TEXTURE2); //back to panorama - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE3); //back to panorama - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, 0); - - //reset flags on Sky Texture that may have changed - texture_set_flags(sky->panorama, texture->flags); - - // Framebuffer did its job. thank mr framebuffer - glActiveTexture(GL_TEXTURE0); //back to panorama - bind_framebuffer_system(); -} - -/* SHADER API */ - -RID RasterizerStorageGLES2::shader_allocate() { - Shader *shader = memnew(Shader); - shader->mode = GD_VS::SHADER_SPATIAL; - shader->shader = &scene->state.scene_shader; - RID rid = shader_owner.make_rid(shader); - _shader_make_dirty(shader); - shader->self = rid; - - return rid; -} - -void RasterizerStorageGLES2::shader_initialize(RID p_rid) { - // noop -} - -//RID RasterizerStorageGLES2::shader_create() { -// Shader *shader = memnew(Shader); -// shader->mode = GD_VS::SHADER_SPATIAL; -// shader->shader = &scene->state.scene_shader; -// RID rid = shader_owner.make_rid(shader); -// _shader_make_dirty(shader); -// shader->self = rid; - -// return rid; -//} - -void RasterizerStorageGLES2::_shader_make_dirty(Shader *p_shader) { - if (p_shader->dirty_list.in_list()) - return; - - _shader_dirty_list.add(&p_shader->dirty_list); -} - -void RasterizerStorageGLES2::shader_set_code(RID p_shader, const String &p_code) { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - - shader->code = p_code; - - String mode_string = ShaderLanguage::get_shader_type(p_code); - GD_VS::ShaderMode mode; - - if (mode_string == "canvas_item") - mode = GD_VS::SHADER_CANVAS_ITEM; - else if (mode_string == "particles") - mode = GD_VS::SHADER_PARTICLES; - else - mode = GD_VS::SHADER_SPATIAL; - - if (shader->custom_code_id && mode != shader->mode) { - shader->shader->free_custom_shader(shader->custom_code_id); - shader->custom_code_id = 0; - } - - shader->mode = mode; - - // TODO handle all shader types - if (mode == GD_VS::SHADER_CANVAS_ITEM) { - shader->shader = &canvas->state.canvas_shader; - - } else if (mode == GD_VS::SHADER_SPATIAL) { - shader->shader = &scene->state.scene_shader; - } else { - return; - } - - if (shader->custom_code_id == 0) { - shader->custom_code_id = shader->shader->create_custom_shader(); - } - - _shader_make_dirty(shader); -} - -String RasterizerStorageGLES2::shader_get_code(RID p_shader) const { - const Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND_V(!shader, ""); - - return shader->code; -} - -void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { - _shader_dirty_list.remove(&p_shader->dirty_list); - - p_shader->valid = false; - - p_shader->uniforms.clear(); - - if (p_shader->code == String()) { - return; //just invalid, but no error - } - - ShaderCompilerGLES2::GeneratedCode gen_code; - ShaderCompilerGLES2::IdentifierActions *actions = NULL; - - switch (p_shader->mode) { - case GD_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; - p_shader->canvas_item.uses_screen_uv = false; - p_shader->canvas_item.uses_time = false; - p_shader->canvas_item.uses_modulate = false; - p_shader->canvas_item.uses_color = false; - p_shader->canvas_item.uses_vertex = false; - p_shader->canvas_item.batch_flags = 0; - - p_shader->canvas_item.uses_world_matrix = false; - p_shader->canvas_item.uses_extra_matrix = false; - p_shader->canvas_item.uses_projection_matrix = false; - p_shader->canvas_item.uses_instance_custom = false; - - shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD); - shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX); - shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB); - 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.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; - shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture; - shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time; - shaders.actions_canvas.usage_flag_pointers["MODULATE"] = &p_shader->canvas_item.uses_modulate; - shaders.actions_canvas.usage_flag_pointers["COLOR"] = &p_shader->canvas_item.uses_color; - - shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex; - - shaders.actions_canvas.usage_flag_pointers["WORLD_MATRIX"] = &p_shader->canvas_item.uses_world_matrix; - shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix; - shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix; - shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom; - - actions = &shaders.actions_canvas; - actions->uniforms = &p_shader->uniforms; - } break; - - case GD_VS::SHADER_SPATIAL: { - p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX; - p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE; - p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK; - p_shader->spatial.uses_alpha = false; - p_shader->spatial.uses_alpha_scissor = false; - p_shader->spatial.uses_discard = false; - p_shader->spatial.unshaded = false; - p_shader->spatial.no_depth_test = false; - p_shader->spatial.uses_sss = false; - p_shader->spatial.uses_time = false; - p_shader->spatial.uses_vertex_lighting = false; - p_shader->spatial.uses_screen_texture = false; - p_shader->spatial.uses_depth_texture = false; - p_shader->spatial.uses_vertex = false; - p_shader->spatial.uses_tangent = false; - p_shader->spatial.uses_ensure_correct_normals = false; - p_shader->spatial.writes_modelview_or_projection = false; - p_shader->spatial.uses_world_coordinates = false; - - shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD); - shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX); - shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB); - shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL); - - shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE); - shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS); - shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER); - shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS); - - shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT); - shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK); - shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED); - - shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded; - shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test; - - shaders.actions_scene.render_mode_flags["vertex_lighting"] = &p_shader->spatial.uses_vertex_lighting; - - shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates; - - shaders.actions_scene.render_mode_flags["ensure_correct_normals"] = &p_shader->spatial.uses_ensure_correct_normals; - - shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha; - shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor; - - shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss; - shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard; - shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture; - shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture; - shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time; - - // Use of any of these BUILTINS indicate the need for transformed tangents. - // This is needed to know when to transform tangents in software skinning. - shaders.actions_scene.usage_flag_pointers["TANGENT"] = &p_shader->spatial.uses_tangent; - shaders.actions_scene.usage_flag_pointers["NORMALMAP"] = &p_shader->spatial.uses_tangent; - - shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; - shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; - shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex; - - actions = &shaders.actions_scene; - actions->uniforms = &p_shader->uniforms; - - if (p_shader->spatial.uses_screen_texture && p_shader->spatial.uses_depth_texture) { - ERR_PRINT_ONCE("Using both SCREEN_TEXTURE and DEPTH_TEXTURE is not supported in GLES2"); - } - - if (p_shader->spatial.uses_depth_texture && !config.support_depth_texture) { - ERR_PRINT_ONCE("Using DEPTH_TEXTURE is not permitted on this hardware, operation will fail."); - } - } break; - - default: { - return; - } break; - } - - Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code); - if (err != OK) { - return; - } - - p_shader->shader->set_custom_shader_code(p_shader->custom_code_id, gen_code.vertex, gen_code.vertex_global, gen_code.fragment, gen_code.light, gen_code.fragment_global, gen_code.uniforms, gen_code.texture_uniforms, gen_code.custom_defines); - - p_shader->texture_count = gen_code.texture_uniforms.size(); - p_shader->texture_hints = gen_code.texture_hints; - - p_shader->uses_vertex_time = gen_code.uses_vertex_time; - p_shader->uses_fragment_time = gen_code.uses_fragment_time; - - // some logic for batching - if (p_shader->mode == GD_VS::SHADER_CANVAS_ITEM) { - if (p_shader->canvas_item.uses_modulate | p_shader->canvas_item.uses_color) { - p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_COLOR_BAKING; - } - if (p_shader->canvas_item.uses_vertex) { - p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_VERTEX_BAKING; - } - if (p_shader->canvas_item.uses_world_matrix | p_shader->canvas_item.uses_extra_matrix | p_shader->canvas_item.uses_projection_matrix | p_shader->canvas_item.uses_instance_custom) { - p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_ITEM_JOINING; - } - } - - p_shader->shader->set_custom_shader(p_shader->custom_code_id); - p_shader->shader->bind(); - - // cache uniform locations - - for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) { - _material_make_dirty(E->self()); - } - - p_shader->valid = true; - p_shader->version++; -} - -void RasterizerStorageGLES2::update_dirty_shaders() { - while (_shader_dirty_list.first()) { - _update_shader(_shader_dirty_list.first()->self()); - } -} - -void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - - if (shader->dirty_list.in_list()) { - _update_shader(shader); - } - - Map<int, StringName> order; - - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); - } else { - order[E->get().order] = E->key(); - } - } - - for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { - PropertyInfo pi; - ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()]; - - pi.name = E->get(); - - switch (u.type) { - case ShaderLanguage::TYPE_VOID: { - pi.type = Variant::NIL; - } break; - - case ShaderLanguage::TYPE_BOOL: { - pi.type = Variant::BOOL; - } break; - - // bool vectors - case ShaderLanguage::TYPE_BVEC2: { - pi.type = Variant::INT; - pi.hint = PROPERTY_HINT_FLAGS; - pi.hint_string = "x,y"; - } break; - case ShaderLanguage::TYPE_BVEC3: { - pi.type = Variant::INT; - pi.hint = PROPERTY_HINT_FLAGS; - pi.hint_string = "x,y,z"; - } break; - case ShaderLanguage::TYPE_BVEC4: { - pi.type = Variant::INT; - pi.hint = PROPERTY_HINT_FLAGS; - pi.hint_string = "x,y,z,w"; - } break; - - // int stuff - case ShaderLanguage::TYPE_UINT: - case ShaderLanguage::TYPE_INT: { - pi.type = Variant::INT; - - if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { - pi.hint = PROPERTY_HINT_RANGE; - pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]); - } - } break; - - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_UVEC2: - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC4: { - // not sure what this should be in godot 4 - // pi.type = Variant::POOL_INT_ARRAY; - pi.type = Variant::PACKED_INT32_ARRAY; - } break; - - case ShaderLanguage::TYPE_FLOAT: { - pi.type = Variant::FLOAT; - if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { - pi.hint = PROPERTY_HINT_RANGE; - pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]); - } - } break; - - case ShaderLanguage::TYPE_VEC2: { - pi.type = Variant::VECTOR2; - } break; - case ShaderLanguage::TYPE_VEC3: { - pi.type = Variant::VECTOR3; - } break; - - case ShaderLanguage::TYPE_VEC4: { - if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { - pi.type = Variant::COLOR; - } else { - pi.type = Variant::PLANE; - } - } break; - - case ShaderLanguage::TYPE_MAT2: { - pi.type = Variant::TRANSFORM2D; - } break; - - case ShaderLanguage::TYPE_MAT3: { - pi.type = Variant::BASIS; - } break; - - case ShaderLanguage::TYPE_MAT4: { - pi.type = Variant::TRANSFORM3D; - } break; - - case ShaderLanguage::TYPE_SAMPLER2D: - // case ShaderLanguage::TYPE_SAMPLEREXT: - case ShaderLanguage::TYPE_ISAMPLER2D: - case ShaderLanguage::TYPE_USAMPLER2D: { - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture"; - } break; - - case ShaderLanguage::TYPE_SAMPLERCUBE: { - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "CubeMap"; - } break; - - case ShaderLanguage::TYPE_SAMPLER2DARRAY: - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: - case ShaderLanguage::TYPE_SAMPLER3D: - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: { - // Not implemented in GLES2 - } break; - // new for godot 4 - case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: - case ShaderLanguage::TYPE_STRUCT: - case ShaderLanguage::TYPE_MAX: { - } break; - } - - p_param_list->push_back(pi); - } -} - -void RasterizerStorageGLES2::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); - - if (p_texture.is_valid()) { - shader->default_textures[p_name] = p_texture; - } else { - shader->default_textures.erase(p_name); - } - - _shader_make_dirty(shader); -} - -RID RasterizerStorageGLES2::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { - const Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND_V(!shader, RID()); - - const Map<StringName, RID>::Element *E = shader->default_textures.find(p_name); - - if (!E) { - return RID(); - } - - return E->get(); -} - -void RasterizerStorageGLES2::shader_add_custom_define(RID p_shader, const String &p_define) { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - - shader->shader->add_custom_define(p_define); - - _shader_make_dirty(shader); -} - -void RasterizerStorageGLES2::shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - - shader->shader->get_custom_defines(p_defines); -} - -void RasterizerStorageGLES2::shader_remove_custom_define(RID p_shader, const String &p_define) { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - - shader->shader->remove_custom_define(p_define); - - _shader_make_dirty(shader); -} - -/* COMMON MATERIAL API */ - -void RasterizerStorageGLES2::_material_make_dirty(Material *p_material) const { - if (p_material->dirty_list.in_list()) - return; - - _material_dirty_list.add(&p_material->dirty_list); -} - -RID RasterizerStorageGLES2::material_allocate() { - Material *material = memnew(Material); - return material_owner.make_rid(material); -} - -void RasterizerStorageGLES2::material_initialize(RID p_rid) { -} - -//RID RasterizerStorageGLES2::material_create() { -// Material *material = memnew(Material); - -// return material_owner.make_rid(material); -//} - -void RasterizerStorageGLES2::material_set_shader(RID p_material, RID p_shader) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - Shader *shader = shader_owner.getornull(p_shader); - - if (material->shader) { - // if a shader is present, remove the old shader - material->shader->materials.remove(&material->list); - } - - material->shader = shader; - - if (shader) { - shader->materials.add(&material->list); - } - - _material_make_dirty(material); -} - -RID RasterizerStorageGLES2::material_get_shader(RID p_material) const { - const Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, RID()); - - if (material->shader) { - return material->shader->self; - } - - return RID(); -} - -void RasterizerStorageGLES2::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type() == Variant::NIL) { - material->params.erase(p_param); - } else { - material->params[p_param] = p_value; - } - - _material_make_dirty(material); -} - -Variant RasterizerStorageGLES2::material_get_param(RID p_material, const StringName &p_param) const { - const Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, RID()); - - if (material->params.has(p_param)) { - return material->params[p_param]; - } - - return material_get_param_default(p_material, p_param); -} - -Variant RasterizerStorageGLES2::material_get_param_default(RID p_material, const StringName &p_param) const { - const Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, Variant()); - - if (material->shader) { - if (material->shader->uniforms.has(p_param)) { - ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); - } - } - return Variant(); -} - -void RasterizerStorageGLES2::material_set_line_width(RID p_material, float p_width) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - material->line_width = p_width; -} - -void RasterizerStorageGLES2::material_set_next_pass(RID p_material, RID p_next_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - material->next_pass = p_next_material; -} - -bool RasterizerStorageGLES2::material_is_animated(RID p_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, false); - if (material->dirty_list.in_list()) { - _update_material(material); - } - - bool animated = material->is_animated_cache; - if (!animated && material->next_pass.is_valid()) { - animated = material_is_animated(material->next_pass); - } - return animated; -} - -bool RasterizerStorageGLES2::material_casts_shadows(RID p_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, false); - if (material->dirty_list.in_list()) { - _update_material(material); - } - - bool casts_shadows = material->can_cast_shadow_cache; - - if (!casts_shadows && material->next_pass.is_valid()) { - casts_shadows = material_casts_shadows(material->next_pass); - } - - return casts_shadows; -} - -bool RasterizerStorageGLES2::material_uses_tangents(RID p_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, false); - - if (!material->shader) { - return false; - } - - if (material->shader->dirty_list.in_list()) { - _update_shader(material->shader); - } - - return material->shader->spatial.uses_tangent; -} - -bool RasterizerStorageGLES2::material_uses_ensure_correct_normals(RID p_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, false); - - if (!material->shader) { - return false; - } - - if (material->shader->dirty_list.in_list()) { - _update_shader(material->shader); - } - - return material->shader->spatial.uses_ensure_correct_normals; -} - -void RasterizerStorageGLES2::material_add_instance_owner(RID p_material, DependencyTracker *p_instance) { - /* - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance); - if (E) { - E->get()++; - } else { - material->instance_owners[p_instance] = 1; - } -*/ -} - -void RasterizerStorageGLES2::material_remove_instance_owner(RID p_material, DependencyTracker *p_instance) { - /* - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance); - ERR_FAIL_COND(!E); - - E->get()--; - - if (E->get() == 0) { - material->instance_owners.erase(E); - } -*/ -} - -void RasterizerStorageGLES2::material_set_render_priority(RID p_material, int priority) { - ERR_FAIL_COND(priority < GD_VS::MATERIAL_RENDER_PRIORITY_MIN); - ERR_FAIL_COND(priority > GD_VS::MATERIAL_RENDER_PRIORITY_MAX); - - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - material->render_priority = priority; -} - -void RasterizerStorageGLES2::_update_material(Material *p_material) { - if (p_material->dirty_list.in_list()) { - _material_dirty_list.remove(&p_material->dirty_list); - } - - if (p_material->shader && p_material->shader->dirty_list.in_list()) { - _update_shader(p_material->shader); - } - - if (p_material->shader && !p_material->shader->valid) { - return; - } - - { - bool can_cast_shadow = false; - bool is_animated = false; - - if (p_material->shader && p_material->shader->mode == GD_VS::SHADER_SPATIAL) { - if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX && - (!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) { - can_cast_shadow = true; - } - - if (p_material->shader->spatial.uses_discard && p_material->shader->uses_fragment_time) { - is_animated = true; - } - - if (p_material->shader->spatial.uses_vertex && p_material->shader->uses_vertex_time) { - is_animated = true; - } - - if (can_cast_shadow != p_material->can_cast_shadow_cache || is_animated != p_material->is_animated_cache) { - p_material->can_cast_shadow_cache = can_cast_shadow; - p_material->is_animated_cache = is_animated; - - /* - for (Map<Geometry *, int>::Element *E = p_material->geometry_owners.front(); E; E = E->next()) { - E->key()->material_changed_notify(); - } - - for (Map<InstanceBaseDependency *, int>::Element *E = p_material->instance_owners.front(); E; E = E->next()) { - E->key()->base_changed(false, true); - } - */ - } - } - } - - // uniforms and other things will be set in the use_material method in ShaderGLES2 - - if (p_material->shader && p_material->shader->texture_count > 0) { - p_material->textures.resize(p_material->shader->texture_count); - - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_material->shader->uniforms.front(); E; E = E->next()) { - if (E->get().texture_order < 0) - continue; // not a texture, does not go here - - RID texture; - - Map<StringName, Variant>::Element *V = p_material->params.find(E->key()); - - if (V) { - texture = V->get(); - } - - if (!texture.is_valid()) { - Map<StringName, RID>::Element *W = p_material->shader->default_textures.find(E->key()); - - if (W) { - texture = W->get(); - } - } - - p_material->textures.write[E->get().texture_order] = Pair<StringName, RID>(E->key(), texture); - } - } else { - p_material->textures.clear(); - } -} -/* -void RasterizerStorageGLES2::_material_add_geometry(RID p_material, Geometry *p_geometry) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry); - - if (I) { - I->get()++; - } else { - material->geometry_owners[p_geometry] = 1; - } -} - -void RasterizerStorageGLES2::_material_remove_geometry(RID p_material, Geometry *p_geometry) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry); - ERR_FAIL_COND(!I); - - I->get()--; - - if (I->get() == 0) { - material->geometry_owners.erase(I); - } -} -*/ -void RasterizerStorageGLES2::update_dirty_materials() { - while (_material_dirty_list.first()) { - Material *material = _material_dirty_list.first()->self(); - _update_material(material); - } -} - -/* RENDER TARGET */ - -void RasterizerStorageGLES2::_set_current_render_target(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - - // FTODO - // if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { - // // pending clear request. Do that first. - // glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); - // glClearColor(storage->frame.clear_request_color.r, - // storage->frame.clear_request_color.g, - // storage->frame.clear_request_color.b, - // storage->frame.clear_request_color.a); - // glClear(GL_COLOR_BUFFER_BIT); - // } - - if (rt) { - if (rt->allocate_is_dirty) { - rt->allocate_is_dirty = false; - _render_target_allocate(rt); - } - - // if (p_render_target.is_valid()) { - // RasterizerStorageGLES2::RenderTarget *rt = storage.render_target_owner.getornull(p_render_target); - frame.current_rt = rt; - ERR_FAIL_COND(!rt); - frame.clear_request = false; - - glViewport(0, 0, rt->width, rt->height); - - // print_line("_set_current_render_target w " + itos(rt->width) + " h " + itos(rt->height)); - - _dims.rt_width = rt->width; - _dims.rt_height = rt->height; - _dims.win_width = rt->width; - _dims.win_height = rt->height; - - } else { - frame.current_rt = NULL; - frame.clear_request = false; - // FTODO - // glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - bind_framebuffer_system(); - } -} - -void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - // do not allocate a render target with no size - if (rt->width <= 0 || rt->height <= 0) - return; - - // do not allocate a render target that is attached to the screen - if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { - rt->fbo = RasterizerStorageGLES2::system_fbo; - return; - } - - GLuint color_internal_format; - GLuint color_format; - GLuint color_type = GL_UNSIGNED_BYTE; - Image::Format image_format; - - if (rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { -#ifdef GLES_OVER_GL - color_internal_format = GL_RGBA8; -#else - color_internal_format = GL_RGBA; -#endif - color_format = GL_RGBA; - image_format = Image::FORMAT_RGBA8; - } else { -#ifdef GLES_OVER_GL - color_internal_format = GL_RGB8; -#else - color_internal_format = GL_RGB; -#endif - color_format = GL_RGB; - image_format = Image::FORMAT_RGB8; - } - - rt->used_dof_blur_near = false; - rt->mip_maps_allocated = false; - - { - /* Front FBO */ - - Texture *texture = texture_owner.getornull(rt->texture); - ERR_FAIL_COND(!texture); - - // framebuffer - glGenFramebuffers(1, &rt->fbo); - bind_framebuffer(rt->fbo); - - // color - glGenTextures(1, &rt->color); - glBindTexture(GL_TEXTURE_2D, rt->color); - - glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); - - if (texture->flags & TEXTURE_FLAG_FILTER) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); - - // depth - - if (config.support_depth_texture) { - glGenTextures(1, &rt->depth); - glBindTexture(GL_TEXTURE_2D, rt->depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); - } else { - glGenRenderbuffers(1, &rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); - - glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - glDeleteFramebuffers(1, &rt->fbo); - if (config.support_depth_texture) { - glDeleteTextures(1, &rt->depth); - } else { - glDeleteRenderbuffers(1, &rt->depth); - } - - glDeleteTextures(1, &rt->color); - rt->fbo = 0; - rt->width = 0; - rt->height = 0; - rt->color = 0; - rt->depth = 0; - texture->tex_id = 0; - texture->active = false; - WARN_PRINT("Could not create framebuffer!!"); - return; - } - - texture->format = image_format; - texture->gl_format_cache = color_format; - texture->gl_type_cache = GL_UNSIGNED_BYTE; - texture->gl_internal_format_cache = color_internal_format; - texture->tex_id = rt->color; - texture->width = rt->width; - texture->alloc_width = rt->width; - texture->height = rt->height; - texture->alloc_height = rt->height; - texture->active = true; - - texture_set_flags(rt->texture, texture->flags); - } - - /* BACK FBO */ - /* For MSAA */ - -#ifndef JAVASCRIPT_ENABLED - if (rt->msaa >= GD_VS::VIEWPORT_MSAA_2X && rt->msaa <= GD_VS::VIEWPORT_MSAA_8X && config.multisample_supported) { - rt->multisample_active = true; - - static const int msaa_value[] = { 0, 2, 4, 8, 16 }; - int msaa = msaa_value[rt->msaa]; - - int max_samples = 0; - glGetIntegerv(GL_MAX_SAMPLES, &max_samples); - if (msaa > max_samples) { - WARN_PRINT("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples)); - msaa = max_samples; - } - - //regular fbo - glGenFramebuffers(1, &rt->multisample_fbo); - bind_framebuffer(rt->multisample_fbo); - - glGenRenderbuffers(1, &rt->multisample_depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth); - -#if defined(GLES_OVER_GL) || defined(IPHONE_ENABLED) - - glGenRenderbuffers(1, &rt->multisample_color); - glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_color); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color); -#elif ANDROID_ENABLED - // Render to a texture in android - glGenTextures(1, &rt->multisample_color); - glBindTexture(GL_TEXTURE_2D, rt->multisample_color); - - glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); - - // multisample buffer is same size as front buffer, so just use nearest - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glFramebufferTexture2DMultisample(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->multisample_color, 0, msaa); -#endif - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - // Delete allocated resources and default to no MSAA - WARN_PRINT_ONCE("Cannot allocate back framebuffer for MSAA"); - printf("err status: %x\n", status); - config.multisample_supported = false; - rt->multisample_active = false; - - glDeleteFramebuffers(1, &rt->multisample_fbo); - rt->multisample_fbo = 0; - - glDeleteRenderbuffers(1, &rt->multisample_depth); - rt->multisample_depth = 0; -#ifdef ANDROID_ENABLED - glDeleteTextures(1, &rt->multisample_color); -#else - glDeleteRenderbuffers(1, &rt->multisample_color); -#endif - rt->multisample_color = 0; - } - - glBindRenderbuffer(GL_RENDERBUFFER, 0); - bind_framebuffer(0); -#ifdef ANDROID_ENABLED - glBindTexture(GL_TEXTURE_2D, 0); -#endif - - } else -#endif // JAVASCRIPT_ENABLED - { - rt->multisample_active = false; - } - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // copy texscreen buffers - // if (!(rt->flags[RendererStorage::RENDER_TARGET_NO_SAMPLING])) { - if (true) { - glGenTextures(1, &rt->copy_screen_effect.color); - glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color); - - if (rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glGenFramebuffers(1, &rt->copy_screen_effect.fbo); - bind_framebuffer(rt->copy_screen_effect.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0); - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - _render_target_clear(rt); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } - } - - // Allocate mipmap chains for post_process effects - // if (!rt->flags[RendererStorage::RENDER_TARGET_NO_3D] && rt->width >= 2 && rt->height >= 2) { - if (rt->width >= 2 && rt->height >= 2) { - for (int i = 0; i < 2; i++) { - ERR_FAIL_COND(rt->mip_maps[i].sizes.size()); - int w = rt->width; - int h = rt->height; - - if (i > 0) { - w >>= 1; - h >>= 1; - } - - int level = 0; - int fb_w = w; - int fb_h = h; - - while (true) { - RenderTarget::MipMaps::Size mm; - mm.width = w; - mm.height = h; - rt->mip_maps[i].sizes.push_back(mm); - - w >>= 1; - h >>= 1; - - if (w < 2 || h < 2) - break; - - level++; - } - - GLsizei width = fb_w; - GLsizei height = fb_h; - - if (config.render_to_mipmap_supported) { - glGenTextures(1, &rt->mip_maps[i].color); - glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color); - - for (int l = 0; l < level + 1; l++) { - glTexImage2D(GL_TEXTURE_2D, l, color_internal_format, width, height, 0, color_format, color_type, NULL); - width = MAX(1, (width / 2)); - height = MAX(1, (height / 2)); - } -#ifdef GLES_OVER_GL - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); -#endif - } else { - // Can't render to specific levels of a mipmap in ES 2.0 or Webgl so create a texture for each level - for (int l = 0; l < level + 1; l++) { - glGenTextures(1, &rt->mip_maps[i].sizes.write[l].color); - glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[l].color); - glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, width, height, 0, color_format, color_type, NULL); - width = MAX(1, (width / 2)); - height = MAX(1, (height / 2)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - } - - glDisable(GL_SCISSOR_TEST); - glColorMask(1, 1, 1, 1); - glDepthMask(GL_TRUE); - - for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j]; - - glGenFramebuffers(1, &mm.fbo); - bind_framebuffer(mm.fbo); - - if (config.render_to_mipmap_supported) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j); - } else { - glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color, 0); - } - - bool used_depth = false; - if (j == 0 && i == 0) { //use always - if (config.support_depth_texture) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); - } else { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - } - used_depth = true; - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - WARN_PRINT_ONCE("Cannot allocate mipmaps for 3D post processing effects"); - bind_framebuffer_system(); - return; - } - - glClearColor(1.0, 0.0, 1.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - if (used_depth) { - glClearDepth(1.0); - glClear(GL_DEPTH_BUFFER_BIT); - } - } - - rt->mip_maps[i].levels = level; - - if (config.render_to_mipmap_supported) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - } - rt->mip_maps_allocated = true; - } - - bind_framebuffer_system(); -} - -void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - // there is nothing to clear when DIRECT_TO_SCREEN is used - if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) - return; - - if (rt->fbo) { - glDeleteFramebuffers(1, &rt->fbo); - glDeleteTextures(1, &rt->color); - rt->fbo = 0; - } - - if (rt->external.fbo != 0) { - // free this - glDeleteFramebuffers(1, &rt->external.fbo); - - // clean up our texture - Texture *t = texture_owner.getornull(rt->external.texture); - t->alloc_height = 0; - t->alloc_width = 0; - t->width = 0; - t->height = 0; - t->active = false; - texture_owner.free(rt->external.texture); - memdelete(t); - - rt->external.fbo = 0; - } - - if (rt->depth) { - if (config.support_depth_texture) { - glDeleteTextures(1, &rt->depth); - } else { - glDeleteRenderbuffers(1, &rt->depth); - } - - rt->depth = 0; - } - - Texture *tex = texture_owner.getornull(rt->texture); - tex->alloc_height = 0; - tex->alloc_width = 0; - tex->width = 0; - tex->height = 0; - tex->active = false; - - if (rt->copy_screen_effect.color) { - glDeleteFramebuffers(1, &rt->copy_screen_effect.fbo); - rt->copy_screen_effect.fbo = 0; - - glDeleteTextures(1, &rt->copy_screen_effect.color); - rt->copy_screen_effect.color = 0; - } - - for (int i = 0; i < 2; i++) { - if (rt->mip_maps[i].sizes.size()) { - for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - glDeleteFramebuffers(1, &rt->mip_maps[i].sizes[j].fbo); - glDeleteTextures(1, &rt->mip_maps[i].sizes[j].color); - } - - glDeleteTextures(1, &rt->mip_maps[i].color); - rt->mip_maps[i].sizes.clear(); - rt->mip_maps[i].levels = 0; - rt->mip_maps[i].color = 0; - } - } - - if (rt->multisample_active) { - glDeleteFramebuffers(1, &rt->multisample_fbo); - rt->multisample_fbo = 0; - - glDeleteRenderbuffers(1, &rt->multisample_depth); - rt->multisample_depth = 0; -#ifdef ANDROID_ENABLED - glDeleteTextures(1, &rt->multisample_color); -#else - glDeleteRenderbuffers(1, &rt->multisample_color); -#endif - rt->multisample_color = 0; - } -} - -RID RasterizerStorageGLES2::render_target_create() { -#ifdef GLES2_DISABLE_RENDER_TARGETS -// return RID(); -#endif - - RenderTarget *rt = memnew(RenderTarget); - Texture *t = memnew(Texture); - - t->type = GD_RD::TEXTURE_TYPE_2D; - t->flags = 0; - t->width = 0; - t->height = 0; - t->alloc_height = 0; - t->alloc_width = 0; - t->format = Image::FORMAT_R8; - t->target = GL_TEXTURE_2D; - t->gl_format_cache = 0; - t->gl_internal_format_cache = 0; - t->gl_type_cache = 0; - t->data_size = 0; - t->total_data_size = 0; - t->ignore_mipmaps = false; - t->compressed = false; - t->mipmaps = 1; - t->active = true; - t->tex_id = 0; - t->render_target = rt; - - rt->texture = texture_owner.make_rid(t); - return render_target_owner.make_rid(rt); -} - -void RasterizerStorageGLES2::render_target_set_position(RID p_render_target, int p_x, int p_y) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - rt->x = p_x; - rt->y = p_y; -} - -void RasterizerStorageGLES2::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - if (p_width == rt->width && p_height == rt->height) - return; - - _render_target_clear(rt); - - rt->width = p_width; - rt->height = p_height; - - // print_line("render_target_set_size " + itos(p_render_target.get_id()) + ", w " + itos(p_width) + " h " + itos(p_height)); - - rt->allocate_is_dirty = true; - //_render_target_allocate(rt); -} - -RID RasterizerStorageGLES2::render_target_get_texture(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return RID(); -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); - - if (rt->external.fbo == 0) { - return rt->texture; - } else { - return rt->external.texture; - } -} - -void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - if (p_texture_id == 0) { - if (rt->external.fbo != 0) { - // free this - glDeleteFramebuffers(1, &rt->external.fbo); - - // and this - if (rt->external.depth != 0) { - glDeleteRenderbuffers(1, &rt->external.depth); - } - - // clean up our texture - Texture *t = texture_owner.getornull(rt->external.texture); - t->alloc_height = 0; - t->alloc_width = 0; - t->width = 0; - t->height = 0; - t->active = false; - texture_owner.free(rt->external.texture); - memdelete(t); - - rt->external.fbo = 0; - rt->external.color = 0; - rt->external.depth = 0; - } - } else { - Texture *t; - - if (rt->external.fbo == 0) { - // create our fbo - glGenFramebuffers(1, &rt->external.fbo); - bind_framebuffer(rt->external.fbo); - - // allocate a texture - t = memnew(Texture); - - t->type = GD_RD::TEXTURE_TYPE_2D; - t->flags = 0; - t->width = 0; - t->height = 0; - t->alloc_height = 0; - t->alloc_width = 0; - t->format = Image::FORMAT_RGBA8; - t->target = GL_TEXTURE_2D; - t->gl_format_cache = 0; - t->gl_internal_format_cache = 0; - t->gl_type_cache = 0; - t->data_size = 0; - t->compressed = false; - t->srgb = false; - t->total_data_size = 0; - t->ignore_mipmaps = false; - t->mipmaps = 1; - t->active = true; - t->tex_id = 0; - t->render_target = rt; - - rt->external.texture = texture_owner.make_rid(t); - - } else { - // bind our frame buffer - bind_framebuffer(rt->external.fbo); - - // find our texture - t = texture_owner.getornull(rt->external.texture); - } - - // set our texture - t->tex_id = p_texture_id; - rt->external.color = p_texture_id; - - // size shouldn't be different - t->width = rt->width; - t->height = rt->height; - t->alloc_height = rt->width; - t->alloc_width = rt->height; - - // Switch our texture on our frame buffer -#if ANDROID_ENABLED - if (rt->msaa >= GD_VS::VIEWPORT_MSAA_2X && rt->msaa <= GD_VS::VIEWPORT_MSAA_4X) { - // This code only applies to the Oculus Go and Oculus Quest. Due to the the tiled nature - // of the GPU we can do a single render pass by rendering directly into our texture chains - // texture and apply MSAA as we render. - - // On any other hardware these two modes are ignored and we do not have any MSAA, - // the normal MSAA modes need to be used to enable our two pass approach - - static const int msaa_value[] = { 2, 4 }; - int msaa = msaa_value[rt->msaa - GD_VS::VIEWPORT_MSAA_2X]; - - if (rt->external.depth == 0) { - // create a multisample depth buffer, we're not reusing Godots because Godot's didn't get created.. - glGenRenderbuffers(1, &rt->external.depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->external.depth); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->external.depth); - } - - // and set our external texture as the texture... - glFramebufferTexture2DMultisample(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0, msaa); - - } else -#endif - { - // set our texture as the destination for our framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0); - - // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :) - if (config.support_depth_texture) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); - } else { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - } - } - - // check status and unbind - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - bind_framebuffer_system(); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - printf("framebuffer fail, status: %x\n", status); - } - - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } -} - -void RasterizerStorageGLES2::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as - // those functions change how they operate depending on the value of DIRECT_TO_SCREEN - if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { - _render_target_clear(rt); - rt->flags[p_flag] = p_value; - _render_target_allocate(rt); - } - - rt->flags[p_flag] = p_value; - - switch (p_flag) { - case RENDER_TARGET_TRANSPARENT: - /* - case RENDER_TARGET_HDR: - case RENDER_TARGET_NO_3D: - case RENDER_TARGET_NO_SAMPLING: - case RENDER_TARGET_NO_3D_EFFECTS: */ - { - //must reset for these formats - _render_target_clear(rt); - _render_target_allocate(rt); - } - break; - default: { - } - } -} - -bool RasterizerStorageGLES2::render_target_was_used(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return false; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, false); - - return rt->used_in_frame; -} - -void RasterizerStorageGLES2::render_target_clear_used(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - rt->used_in_frame = false; -} - -void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, GD_VS::ViewportMSAA p_msaa) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - if (rt->msaa == p_msaa) - return; - - if (!config.multisample_supported) { - ERR_PRINT("MSAA not supported on this hardware."); - return; - } - - _render_target_clear(rt); - rt->msaa = p_msaa; - _render_target_allocate(rt); -} - -//RasterizerStorageGLES2::RenderTarget * RasterizerStorageGLES2::render_target_get(RID p_render_target) -//{ -// return render_target_owner.getornull(p_render_target); -//} - -void RasterizerStorageGLES2::render_target_set_use_fxaa(RID p_render_target, bool p_fxaa) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - rt->use_fxaa = p_fxaa; -} - -void RasterizerStorageGLES2::render_target_set_use_debanding(RID p_render_target, bool p_debanding) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - if (p_debanding) { - WARN_PRINT_ONCE("Debanding is not supported in the GLES2 backend. Switch to the GLES3 backend and make sure HDR is enabled."); - } - - rt->use_debanding = p_debanding; -} - -void RasterizerStorageGLES2::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - rt->clear_requested = true; - rt->clear_color = p_clear_color; - - // ERR_FAIL_COND(!frame.current_rt); - // frame.clear_request = true; - // frame.clear_request_color = p_color; -} - -bool RasterizerStorageGLES2::render_target_is_clear_requested(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return false; -#endif - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, false); - return rt->clear_requested; -} -Color RasterizerStorageGLES2::render_target_get_clear_request_color(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return Color(); -#endif - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, Color()); - return rt->clear_color; -} - -void RasterizerStorageGLES2::render_target_disable_clear_request(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - rt->clear_requested = false; -} - -void RasterizerStorageGLES2::render_target_do_clear_request(RID p_render_target) { -#ifdef GLES2_DISABLE_RENDER_TARGETS - return; -#endif - - // NEW for GLES... - // This is being called at the wrong time. Instead it will be performed - // at canvas begin - return; - - /* - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - if (!rt->clear_requested) { - return; - } - - const Color &c = rt->clear_color; - - glClearColor(c.r, c.g, c.b, c.a); - // more bits? - glClear(GL_COLOR_BUFFER_BIT); - */ -} - -/* CANVAS SHADOW */ - -RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) { - 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); - bind_framebuffer(cls->fbo); - - glGenRenderbuffers(1, &cls->depth); - glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); - glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, cls->size, cls->height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); - - 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); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(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); - bind_framebuffer_system(); - - 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() { - 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; - } -} -*/ - -GD_VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const { - return GD_VS::INSTANCE_NONE; - - /* - if (mesh_owner.owns(p_rid)) { - return GD_VS::INSTANCE_MESH; - } else if (light_owner.owns(p_rid)) { - return GD_VS::INSTANCE_LIGHT; - } else if (multimesh_owner.owns(p_rid)) { - return GD_VS::INSTANCE_MULTIMESH; - } else if (immediate_owner.owns(p_rid)) { - return GD_VS::INSTANCE_IMMEDIATE; - } else if (reflection_probe_owner.owns(p_rid)) { - return GD_VS::INSTANCE_REFLECTION_PROBE; - } else if (lightmap_capture_data_owner.owns(p_rid)) { - return GD_VS::INSTANCE_LIGHTMAP_CAPTURE; - } else { - return GD_VS::INSTANCE_NONE; - } -*/ -} - -bool RasterizerStorageGLES2::free(RID p_rid) { - if (render_target_owner.owns(p_rid)) { - RenderTarget *rt = render_target_owner.getornull(p_rid); - _render_target_clear(rt); - - Texture *t = texture_owner.getornull(rt->texture); - if (t) { - texture_owner.free(rt->texture); - memdelete(t); - } - render_target_owner.free(p_rid); - memdelete(rt); - - return true; - } else if (texture_owner.owns(p_rid)) { - Texture *t = texture_owner.getornull(p_rid); - // can't free a render target texture - ERR_FAIL_COND_V(t->render_target, true); - - info.texture_mem -= t->total_data_size; - texture_owner.free(p_rid); - memdelete(t); - - return true; - } else if (sky_owner.owns(p_rid)) { - Sky *sky = sky_owner.getornull(p_rid); - sky_set_texture(p_rid, RID(), 256); - sky_owner.free(p_rid); - memdelete(sky); - - return true; - } else if (shader_owner.owns(p_rid)) { - Shader *shader = shader_owner.getornull(p_rid); - - if (shader->shader && shader->custom_code_id) { - shader->shader->free_custom_shader(shader->custom_code_id); - } - - if (shader->dirty_list.in_list()) { - _shader_dirty_list.remove(&shader->dirty_list); - } - - while (shader->materials.first()) { - Material *m = shader->materials.first()->self(); - - m->shader = NULL; - _material_make_dirty(m); - - shader->materials.remove(shader->materials.first()); - } - - shader_owner.free(p_rid); - memdelete(shader); - - return true; - } else if (material_owner.owns(p_rid)) { - Material *m = material_owner.getornull(p_rid); - - if (m->shader) { - m->shader->materials.remove(&m->list); - } - - /* - for (Map<Geometry *, int>::Element *E = m->geometry_owners.front(); E; E = E->next()) { - Geometry *g = E->key(); - g->material = RID(); - } - - for (Map<InstanceBaseDependency *, int>::Element *E = m->instance_owners.front(); E; E = E->next()) { - InstanceBaseDependency *ins = E->key(); - - if (ins->material_override == p_rid) { - ins->material_override = RID(); - } - - for (int i = 0; i < ins->materials.size(); i++) { - if (ins->materials[i] == p_rid) { - ins->materials.write[i] = RID(); - } - } - } -*/ - - material_owner.free(p_rid); - memdelete(m); - - return true; - - } else { - return false; - } - /* - } else if (skeleton_owner.owns(p_rid)) { - Skeleton *s = skeleton_owner.getornull(p_rid); - - if (s->update_list.in_list()) { - skeleton_update_list.remove(&s->update_list); - } - - for (Set<InstanceBaseDependency *>::Element *E = s->instances.front(); E; E = E->next()) { - E->get()->skeleton = RID(); - } - - skeleton_allocate(p_rid, 0, false); - - if (s->tex_id) { - glDeleteTextures(1, &s->tex_id); - } - - skeleton_owner.free(p_rid); - memdelete(s); - - return true; - } else if (mesh_owner.owns(p_rid)) { - Mesh *mesh = mesh_owner.getornull(p_rid); - - mesh->instance_remove_deps(); - mesh_clear(p_rid); - - while (mesh->multimeshes.first()) { - MultiMesh *multimesh = mesh->multimeshes.first()->self(); - multimesh->mesh = RID(); - multimesh->dirty_aabb = true; - - mesh->multimeshes.remove(mesh->multimeshes.first()); - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } - } - - mesh_owner.free(p_rid); - memdelete(mesh); - - return true; - } else if (multimesh_owner.owns(p_rid)) { - MultiMesh *multimesh = multimesh_owner.getornull(p_rid); - multimesh->instance_remove_deps(); - - if (multimesh->mesh.is_valid()) { - Mesh *mesh = mesh_owner.getornull(multimesh->mesh); - if (mesh) { - mesh->multimeshes.remove(&multimesh->mesh_list); - } - } - - multimesh_allocate(p_rid, 0, GD_VS::MULTIMESH_TRANSFORM_3D, GD_VS::MULTIMESH_COLOR_NONE); - - update_dirty_multimeshes(); - - multimesh_owner.free(p_rid); - memdelete(multimesh); - - return true; - } else if (immediate_owner.owns(p_rid)) { - Immediate *im = immediate_owner.getornull(p_rid); - im->instance_remove_deps(); - - immediate_owner.free(p_rid); - memdelete(im); - - return true; - } else if (light_owner.owns(p_rid)) { - Light *light = light_owner.getornull(p_rid); - light->instance_remove_deps(); - - light_owner.free(p_rid); - memdelete(light); - - return true; - } else if (reflection_probe_owner.owns(p_rid)) { - // delete the texture - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid); - reflection_probe->instance_remove_deps(); - - reflection_probe_owner.free(p_rid); - memdelete(reflection_probe); - - return true; - } else if (lightmap_capture_data_owner.owns(p_rid)) { - // delete the texture - LightmapCapture *lightmap_capture = lightmap_capture_data_owner.getornull(p_rid); - lightmap_capture->instance_remove_deps(); - - 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.getornull(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.getornull(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; - */ -} - -bool RasterizerStorageGLES2::has_os_feature(const String &p_feature) const { - if (p_feature == "pvrtc") - return config.pvrtc_supported; - - if (p_feature == "s3tc") - return config.s3tc_supported; - - if (p_feature == "etc") - return config.etc1_supported; - - if (p_feature == "skinning_fallback") - return config.use_skeleton_software; - - return false; -} - -//////////////////////////////////////////// - -void RasterizerStorageGLES2::set_debug_generate_wireframes(bool p_generate) { -} - -//void RasterizerStorageGLES2::render_info_begin_capture() { -// info.snap = info.render; -//} - -//void RasterizerStorageGLES2::render_info_end_capture() { -// info.snap.object_count = info.render.object_count - info.snap.object_count; -// info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count; -// info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count; -// info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count; -// info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count; -// info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count; -// info.snap._2d_item_count = info.render._2d_item_count - info.snap._2d_item_count; -// info.snap._2d_draw_call_count = info.render._2d_draw_call_count - info.snap._2d_draw_call_count; -//} - -//int RasterizerStorageGLES2::get_captured_render_info(GD_VS::RenderInfo p_info) { -// switch (p_info) { -// case GD_VS::INFO_OBJECTS_IN_FRAME: { -// return info.snap.object_count; -// } break; -// case GD_VS::INFO_VERTICES_IN_FRAME: { -// return info.snap.vertices_count; -// } break; -// case GD_VS::INFO_MATERIAL_CHANGES_IN_FRAME: { -// return info.snap.material_switch_count; -// } break; -// case GD_VS::INFO_SHADER_CHANGES_IN_FRAME: { -// return info.snap.shader_rebind_count; -// } break; -// case GD_VS::INFO_SURFACE_CHANGES_IN_FRAME: { -// return info.snap.surface_switch_count; -// } break; -// case GD_VS::INFO_DRAW_CALLS_IN_FRAME: { -// return info.snap.draw_call_count; -// } break; -// /* -// case GD_VS::INFO_2D_ITEMS_IN_FRAME: { -// return info.snap._2d_item_count; -// } break; -// case GD_VS::INFO_2D_DRAW_CALLS_IN_FRAME: { -// return info.snap._2d_draw_call_count; -// } break; -// */ -// default: { -// return get_render_info(p_info); -// } -// } -//} - -//int RasterizerStorageGLES2::get_render_info(GD_VS::RenderInfo p_info) { -// switch (p_info) { -// case GD_VS::INFO_OBJECTS_IN_FRAME: -// return info.render_final.object_count; -// case GD_VS::INFO_VERTICES_IN_FRAME: -// return info.render_final.vertices_count; -// case GD_VS::INFO_MATERIAL_CHANGES_IN_FRAME: -// return info.render_final.material_switch_count; -// case GD_VS::INFO_SHADER_CHANGES_IN_FRAME: -// return info.render_final.shader_rebind_count; -// case GD_VS::INFO_SURFACE_CHANGES_IN_FRAME: -// return info.render_final.surface_switch_count; -// case GD_VS::INFO_DRAW_CALLS_IN_FRAME: -// return info.render_final.draw_call_count; -// /* -// case GD_VS::INFO_2D_ITEMS_IN_FRAME: -// return info.render_final._2d_item_count; -// case GD_VS::INFO_2D_DRAW_CALLS_IN_FRAME: -// return info.render_final._2d_draw_call_count; -//*/ -// case GD_VS::INFO_USAGE_VIDEO_MEM_TOTAL: -// return 0; //no idea -// case GD_VS::INFO_VIDEO_MEM_USED: -// return info.vertex_mem + info.texture_mem; -// case GD_VS::INFO_TEXTURE_MEM_USED: -// return info.texture_mem; -// case GD_VS::INFO_VERTEX_MEM_USED: -// return info.vertex_mem; -// default: -// return 0; //no idea either -// } -//} - -String RasterizerStorageGLES2::get_video_adapter_name() const { - return (const char *)glGetString(GL_RENDERER); -} - -String RasterizerStorageGLES2::get_video_adapter_vendor() const { - return (const char *)glGetString(GL_VENDOR); -} - -void RasterizerStorageGLES2::initialize() { - RasterizerStorageGLES2::system_fbo = 0; - - { - const GLubyte *extension_string = glGetString(GL_EXTENSIONS); - - Vector<String> extensions = String((const char *)extension_string).split(" "); - - for (int i = 0; i < extensions.size(); i++) { - config.extensions.insert(extensions[i]); - } - } - - // FTODO - config.keep_original_textures = true; // false - config.shrink_textures_x2 = false; - config.depth_internalformat = GL_DEPTH_COMPONENT; - config.depth_type = GL_UNSIGNED_INT; - -#ifdef GLES_OVER_GL - config.float_texture_supported = true; - config.s3tc_supported = true; - config.pvrtc_supported = false; - config.etc1_supported = false; - config.support_npot_repeat_mipmap = true; - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24; -#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.extensions.has("WEBGL_compressed_texture_s3tc"); - config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1"); - config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc") || config.extensions.has("WEBGL_compressed_texture_pvrtc"); - config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot"); - -#ifdef JAVASCRIPT_ENABLED - // RenderBuffer internal format must be 16 bits in WebGL, - // but depth_texture should default to 32 always - // if the implementation doesn't support 32, it should just quietly use 16 instead - // https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/ - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - config.depth_type = GL_UNSIGNED_INT; -#else - // on mobile check for 24 bit depth support for RenderBufferStorage - if (config.extensions.has("GL_OES_depth24")) { - config.depth_buffer_internalformat = _DEPTH_COMPONENT24_OES; - config.depth_type = GL_UNSIGNED_INT; - } else { - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - config.depth_type = GL_UNSIGNED_SHORT; - } -#endif -#endif - -#ifndef GLES_OVER_GL - //Manually load extensions for android and ios - -#ifdef IPHONE_ENABLED - // appears that IPhone doesn't need to dlopen TODO: test this rigorously before removing - //void *gles2_lib = dlopen(NULL, RTLD_LAZY); - //glRenderbufferStorageMultisampleAPPLE = dlsym(gles2_lib, "glRenderbufferStorageMultisampleAPPLE"); - //glResolveMultisampleFramebufferAPPLE = dlsym(gles2_lib, "glResolveMultisampleFramebufferAPPLE"); -#elif ANDROID_ENABLED - - void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY); - glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT"); - glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glFramebufferTexture2DMultisampleEXT"); -#endif -#endif - - // Check for multisample support - config.multisample_supported = config.extensions.has("GL_EXT_framebuffer_multisample") || config.extensions.has("GL_EXT_multisampled_render_to_texture") || config.extensions.has("GL_APPLE_framebuffer_multisample"); - -#ifdef GLES_OVER_GL - //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps - config.render_to_mipmap_supported = false; -#else - //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms - config.render_to_mipmap_supported = config.extensions.has("GL_OES_fbo_render_mipmap") && config.extensions.has("GL_EXT_texture_lod"); -#endif - -#ifdef GLES_OVER_GL - config.use_rgba_2d_shadows = false; - config.support_depth_texture = true; - config.use_rgba_3d_shadows = false; - config.support_depth_cubemaps = true; -#else - config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg")); - config.support_depth_texture = config.extensions.has("GL_OES_depth_texture") || config.extensions.has("WEBGL_depth_texture"); - config.use_rgba_3d_shadows = !config.support_depth_texture; - config.support_depth_cubemaps = config.extensions.has("GL_OES_depth_texture_cube_map"); -#endif - -#ifdef GLES_OVER_GL - config.support_32_bits_indices = true; -#else - config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint"); -#endif - -#ifdef GLES_OVER_GL - config.support_write_depth = true; -#elif defined(JAVASCRIPT_ENABLED) - config.support_write_depth = false; -#else - config.support_write_depth = config.extensions.has("GL_EXT_frag_depth"); -#endif - - config.support_half_float_vertices = true; -//every platform should support this except web, iOS has issues with their support, so add option to disable -#ifdef JAVASCRIPT_ENABLED - config.support_half_float_vertices = false; -#endif - bool disable_half_float = GLOBAL_GET("rendering/gles2/compatibility/disable_half_float"); - if (disable_half_float) { - config.support_half_float_vertices = false; - } - - config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc"); - config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc") || config.extensions.has("EXT_texture_compression_bptc"); - - //determine formats for depth textures (or renderbuffers) - if (config.support_depth_texture) { - // Will use texture for depth - // have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT, - // as there is no extension to test for this. - GLuint fbo; - glGenFramebuffers(1, &fbo); - bind_framebuffer(fbo); - GLuint depth; - glGenTextures(1, &depth); - glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - bind_framebuffer_system(); - glDeleteFramebuffers(1, &fbo); - glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &depth); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - // If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT - // This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT -#ifdef GLES_OVER_GL - config.depth_internalformat = GL_DEPTH_COMPONENT16; -#else - // OES_depth_texture extension only specifies GL_DEPTH_COMPONENT. - config.depth_internalformat = GL_DEPTH_COMPONENT; -#endif - config.depth_type = GL_UNSIGNED_SHORT; - - glGenFramebuffers(1, &fbo); - bind_framebuffer(fbo); - - glGenTextures(1, &depth); - glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - //if it fails again depth textures aren't supported, use rgba shadows and renderbuffer for depth - config.support_depth_texture = false; - config.use_rgba_3d_shadows = true; - } - - bind_framebuffer_system(); - glDeleteFramebuffers(1, &fbo); - glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &depth); - } - } - - //picky requirements for these - config.support_shadow_cubemaps = config.support_depth_texture && config.support_write_depth && config.support_depth_cubemaps; - - frame.count = 0; - frame.delta = 0; - frame.current_rt = NULL; - frame.clear_request = false; - - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &config.max_vertex_texture_image_units); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); - - // the use skeleton software path should be used if either float texture is not supported, - // OR max_vertex_texture_image_units is zero - config.use_skeleton_software = (config.float_texture_supported == false) || (config.max_vertex_texture_image_units == 0); - - shaders.copy.init(); - shaders.cubemap_filter.init(); - bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx"); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::LOW_QUALITY, !ggx_hq); - - { - // quad for copying stuff - - glGenBuffers(1, &resources.quadie); - glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); - { - const float qv[16] = { - -1, - -1, - 0, - 0, - -1, - 1, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - -1, - 1, - 0, - }; - - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - { - //default textures - - glGenTextures(1, &resources.white_tex); - unsigned char whitetexdata[8 * 8 * 3]; - for (int i = 0; i < 8 * 8 * 3; i++) { - whitetexdata[i] = 255; - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, resources.white_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenTextures(1, &resources.black_tex); - unsigned char blacktexdata[8 * 8 * 3]; - for (int i = 0; i < 8 * 8 * 3; i++) { - blacktexdata[i] = 0; - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, resources.black_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, blacktexdata); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenTextures(1, &resources.normal_tex); - unsigned char normaltexdata[8 * 8 * 3]; - for (int i = 0; i < 8 * 8 * 3; i += 3) { - normaltexdata[i + 0] = 128; - normaltexdata[i + 1] = 128; - normaltexdata[i + 2] = 255; - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, resources.normal_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, normaltexdata); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenTextures(1, &resources.aniso_tex); - unsigned char anisotexdata[8 * 8 * 3]; - for (int i = 0; i < 8 * 8 * 3; i += 3) { - anisotexdata[i + 0] = 255; - anisotexdata[i + 1] = 128; - anisotexdata[i + 2] = 0; - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, resources.aniso_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - } - - // skeleton buffer - { - resources.skeleton_transform_buffer_size = 0; - glGenBuffers(1, &resources.skeleton_transform_buffer); - } - - // radical inverse vdc cache texture - // used for cubemap filtering - if (true /*||config.float_texture_supported*/) { //uint8 is similar and works everywhere - glGenTextures(1, &resources.radical_inverse_vdc_cache_tex); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex); - - uint8_t radical_inverse[512]; - - for (uint32_t i = 0; i < 512; i++) { - uint32_t bits = i; - - bits = (bits << 16) | (bits >> 16); - bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1); - bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2); - bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4); - bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8); - - float value = float(bits) * 2.3283064365386963e-10; - radical_inverse[i] = uint8_t(CLAMP(value * 255.0, 0, 255)); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 512, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, radical_inverse); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling - - glBindTexture(GL_TEXTURE_2D, 0); - } - - { - glGenFramebuffers(1, &resources.mipmap_blur_fbo); - glGenTextures(1, &resources.mipmap_blur_color); - } - -#ifdef GLES_OVER_GL - //this needs to be enabled manually in OpenGL 2.1 - - if (config.extensions.has("GL_ARB_seamless_cube_map")) { - glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); - } - glEnable(GL_POINT_SPRITE); - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); -#endif - - config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); - config.use_fast_texture_filter = GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter"); - //config.should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers"); -} - -void RasterizerStorageGLES2::finalize() { -} - -void RasterizerStorageGLES2::_copy_screen() { - bind_quad_array(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -} - -void RasterizerStorageGLES2::update_dirty_resources() { - update_dirty_shaders(); - update_dirty_materials(); - // update_dirty_skeletons(); - // update_dirty_multimeshes(); -} - -RasterizerStorageGLES2::RasterizerStorageGLES2() { - RasterizerStorageGLES2::system_fbo = 0; - config.should_orphan = true; -} - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h deleted file mode 100644 index e2db7feefb..0000000000 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ /dev/null @@ -1,1093 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZERSTORAGEGLES2_H -#define RASTERIZERSTORAGEGLES2_H - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/templates/local_vector.h" -#include "core/templates/rid_owner.h" -#include "core/templates/self_list.h" -#include "drivers/gles_common/rasterizer_asserts.h" -#include "drivers/gles_common/rasterizer_common_stubs.h" -#include "drivers/gles_common/rasterizer_version.h" -#include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/shader_language.h" -#include "shader_compiler_gles2.h" -#include "shader_gles2.h" - -#include "shaders/copy.glsl.gen.h" -#include "shaders/cubemap_filter.glsl.gen.h" - -class RasterizerCanvasGLES2; -class RasterizerSceneGLES2; - -class RasterizerStorageGLES2 : public StubsStorage { - friend class RasterizerGLES2; - - Thread::ID _main_thread_id = 0; - bool _is_main_thread(); - -public: - RasterizerCanvasGLES2 *canvas; - RasterizerSceneGLES2 *scene; - - static GLuint system_fbo; - - struct Config { - bool shrink_textures_x2; - bool use_fast_texture_filter; - bool use_skeleton_software; - - int max_vertex_texture_image_units; - int max_texture_image_units; - int max_texture_size; - - // TODO implement wireframe in GLES2 - // bool generate_wireframes; - - Set<String> extensions; - - bool float_texture_supported; - bool s3tc_supported; - bool etc1_supported; - bool pvrtc_supported; - bool rgtc_supported; - bool bptc_supported; - - bool keep_original_textures; - - bool force_vertex_shading; - - bool use_rgba_2d_shadows; - bool use_rgba_3d_shadows; - - bool support_32_bits_indices; - bool support_write_depth; - bool support_half_float_vertices; - bool support_npot_repeat_mipmap; - bool support_depth_texture; - bool support_depth_cubemaps; - - bool support_shadow_cubemaps; - - bool multisample_supported; - bool render_to_mipmap_supported; - - GLuint depth_internalformat; - GLuint depth_type; - GLuint depth_buffer_internalformat; - - // in some cases the legacy render didn't orphan. We will mark these - // so the user can switch orphaning off for them. - bool should_orphan; - } config; - - struct Resources { - GLuint white_tex; - GLuint black_tex; - GLuint normal_tex; - GLuint aniso_tex; - - GLuint mipmap_blur_fbo; - GLuint mipmap_blur_color; - - GLuint radical_inverse_vdc_cache_tex; - bool use_rgba_2d_shadows; - - GLuint quadie; - - size_t skeleton_transform_buffer_size; - GLuint skeleton_transform_buffer; - LocalVector<float> skeleton_transform_cpu_buffer; - - } resources; - - mutable struct Shaders { - ShaderCompilerGLES2 compiler; - - CopyShaderGLES2 copy; - CubemapFilterShaderGLES2 cubemap_filter; - - ShaderCompilerGLES2::IdentifierActions actions_canvas; - ShaderCompilerGLES2::IdentifierActions actions_scene; - ShaderCompilerGLES2::IdentifierActions actions_particles; - - } shaders; - - struct Info { - uint64_t texture_mem; - uint64_t vertex_mem; - - struct Render { - uint32_t object_count; - uint32_t draw_call_count; - uint32_t material_switch_count; - uint32_t surface_switch_count; - uint32_t shader_rebind_count; - uint32_t vertices_count; - uint32_t _2d_item_count; - uint32_t _2d_draw_call_count; - - void reset() { - object_count = 0; - draw_call_count = 0; - material_switch_count = 0; - surface_switch_count = 0; - shader_rebind_count = 0; - vertices_count = 0; - _2d_item_count = 0; - _2d_draw_call_count = 0; - } - } render, render_final, snap; - - Info() : - texture_mem(0), - vertex_mem(0) { - render.reset(); - render_final.reset(); - } - - } info; - - void bind_quad_array() const; - - ///////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////DATA/////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////// - - /* - struct Instantiable { - RID self; - - SelfList<InstanceBaseDependency>::List instance_list; - - _FORCE_INLINE_ void instance_change_notify(bool p_aabb, bool p_materials) { - SelfList<InstanceBaseDependency> *instances = instance_list.first(); - while (instances) { - instances->self()->base_changed(p_aabb, p_materials); - instances = instances->next(); - } - } - - _FORCE_INLINE_ void instance_remove_deps() { - SelfList<InstanceBaseDependency> *instances = instance_list.first(); - - while (instances) { - instances->self()->base_removed(); - instances = instances->next(); - } - } - - Instantiable() {} - - virtual ~Instantiable() {} - }; - - struct GeometryOwner : public Instantiable { - }; - - struct Geometry : public Instantiable { - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_IMMEDIATE, - GEOMETRY_MULTISURFACE - }; - - Type type; - RID material; - uint64_t last_pass; - uint32_t index; - - virtual void material_changed_notify() {} - - Geometry() { - last_pass = 0; - index = 0; - } - }; -*/ - ///////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////API//////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////// - - // TEXTURE API - - enum GLESTextureFlags { - TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available - TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping - TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter - TEXTURE_FLAG_ANISOTROPIC_FILTER = 8, - TEXTURE_FLAG_CONVERT_TO_LINEAR = 16, - TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored - TEXTURE_FLAG_USED_FOR_STREAMING = 2048, - TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER - }; - - struct RenderTarget; - - struct Texture { - RID self; - - Texture *proxy; - Set<Texture *> proxy_owners; - - String path; - uint32_t flags; - int width, height, depth; - int alloc_width, alloc_height; - Image::Format format; - GD_RD::TextureType type; - - GLenum target; - GLenum gl_format_cache; - GLenum gl_internal_format_cache; - GLenum gl_type_cache; - - int data_size; - int total_data_size; - bool ignore_mipmaps; - - bool compressed; - - bool srgb; - - int mipmaps; - - bool resize_to_po2; - - bool active; - GLenum tex_id; - - uint16_t stored_cube_sides; - - RenderTarget *render_target; - - Vector<Ref<Image>> images; - - bool redraw_if_visible; - - GD_VS::TextureDetectCallback detect_3d; - void *detect_3d_ud; - - GD_VS::TextureDetectCallback detect_srgb; - void *detect_srgb_ud; - - GD_VS::TextureDetectCallback detect_normal; - void *detect_normal_ud; - - // some silly opengl shenanigans where - // texture coords start from bottom left, means we need to draw render target textures upside down - // to be compatible with vulkan etc. - bool is_upside_down() const { - if (proxy) - return proxy->is_upside_down(); - - return render_target != nullptr; - } - - Texture() { - create(); - } - - _ALWAYS_INLINE_ Texture *get_ptr() { - if (proxy) { - return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. - } else { - return this; - } - } - - ~Texture() { - destroy(); - - if (tex_id != 0) { - glDeleteTextures(1, &tex_id); - } - } - - void copy_from(const Texture &o) { - proxy = o.proxy; - flags = o.flags; - width = o.width; - height = o.height; - alloc_width = o.alloc_width; - alloc_height = o.alloc_height; - format = o.format; - type = o.type; - target = o.target; - data_size = o.data_size; - total_data_size = o.total_data_size; - ignore_mipmaps = o.ignore_mipmaps; - compressed = o.compressed; - mipmaps = o.mipmaps; - resize_to_po2 = o.resize_to_po2; - active = o.active; - tex_id = o.tex_id; - stored_cube_sides = o.stored_cube_sides; - render_target = o.render_target; - redraw_if_visible = o.redraw_if_visible; - detect_3d = o.detect_3d; - detect_3d_ud = o.detect_3d_ud; - detect_srgb = o.detect_srgb; - detect_srgb_ud = o.detect_srgb_ud; - detect_normal = o.detect_normal; - detect_normal_ud = o.detect_normal_ud; - - images.clear(); - } - - void create() { - proxy = nullptr; - flags = 0; - width = 0; - height = 0; - alloc_width = 0; - alloc_height = 0; - format = Image::FORMAT_L8; - type = GD_RD::TEXTURE_TYPE_2D; - target = 0; - data_size = 0; - total_data_size = 0; - ignore_mipmaps = false; - compressed = false; - mipmaps = 0; - resize_to_po2 = false; - active = false; - tex_id = 0; - stored_cube_sides = 0; - render_target = nullptr; - redraw_if_visible = false; - detect_3d = nullptr; - detect_3d_ud = nullptr; - detect_srgb = nullptr; - detect_srgb_ud = nullptr; - detect_normal = nullptr; - detect_normal_ud = nullptr; - } - void destroy() { - images.clear(); - - for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { - E->get()->proxy = NULL; - } - - if (proxy) { - proxy->proxy_owners.erase(this); - } - } - - // texture state - void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) { - if (p_filter == state_filter) - return; - state_filter = p_filter; - GLint pmin = GL_LINEAR; // param min - GLint pmag = GL_LINEAR; // param mag - switch (state_filter) { - default: { - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { - pmin = GL_LINEAR_MIPMAP_LINEAR; - pmag = GL_LINEAR; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { - pmin = GL_NEAREST; - pmag = GL_NEAREST; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { - pmin = GL_NEAREST_MIPMAP_NEAREST; - pmag = GL_NEAREST; - } break; - } - glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin); - glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag); - } - void GLSetRepeat(RS::CanvasItemTextureRepeat p_repeat) { - if (p_repeat == state_repeat) - return; - state_repeat = p_repeat; - GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat - switch (state_repeat) { - default: { - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { - prep = GL_REPEAT; - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { - prep = GL_MIRRORED_REPEAT; - } break; - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, prep); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, prep); - } - - private: - RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; - RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; - }; - - mutable RID_PtrOwner<Texture> texture_owner; - - Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; - - void _texture_set_state_from_flags(Texture *p_tex); - - // new - RID texture_allocate() override; - void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; - - // RID texture_2d_create(const Ref<Image> &p_image) override; - // RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; - // RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override { return RID(); } - //RID texture_proxy_create(RID p_base) override; - - //void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; - void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; - void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {} - void texture_proxy_update(RID p_proxy, RID p_base) override {} - - //RID texture_2d_placeholder_create() override; - //RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) override { return RID(); } - //RID texture_3d_placeholder_create() override { return RID(); } - - Ref<Image> texture_2d_get(RID p_texture) const override; - Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } - Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - - void texture_replace(RID p_texture, RID p_by_texture) override; - //void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} - - void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - - // old - virtual uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - -private: - virtual RID texture_create(); - - //virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, GD_RD::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); - void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, GD_RD::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); - - virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); - virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0); - //virtual Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const; - virtual void texture_set_flags(RID p_texture, uint32_t p_flags); - virtual uint32_t texture_get_flags(RID p_texture) const; - virtual Image::Format texture_get_format(RID p_texture) const; - virtual GD_RD::TextureType texture_get_type(RID p_texture) const; - virtual uint32_t texture_get_texid(RID p_texture) const; - virtual uint32_t texture_get_depth(RID p_texture) const; - void texture_set_size_override(RID p_texture, int p_width, int p_height) override; - - virtual void texture_bind(RID p_texture, uint32_t p_texture_no); - - virtual void texture_set_path(RID p_texture, const String &p_path) override; - virtual String texture_get_path(RID p_texture) const override; - - virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); - - virtual void texture_debug_usage(List<GD_VS::TextureInfo> *r_info) override; - - virtual RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; - - virtual void textures_keep_original(bool p_enable); - - virtual void texture_set_proxy(RID p_texture, RID p_proxy); - virtual Size2 texture_size_with_proxy(RID p_texture) override; - - virtual void texture_set_detect_3d_callback(RID p_texture, GD_VS::TextureDetectCallback p_callback, void *p_userdata) override; - virtual void texture_set_detect_srgb_callback(RID p_texture, GD_VS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_normal_callback(RID p_texture, GD_VS::TextureDetectCallback p_callback, void *p_userdata) override; - void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {} - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; - -public: - // CANVAS TEXTURE API - /* - RID canvas_texture_create() override { return RID(); } - void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {} - void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {} - - void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {} - void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {} - */ - /* SKY API */ - // not sure if used in godot 4? - struct Sky { - RID self; - RID panorama; - GLuint radiance; - int radiance_size; - }; - - mutable RID_PtrOwner<Sky> sky_owner; - - virtual RID sky_create(); - virtual void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size); - - // SHADER API - - struct Material; - - struct Shader { - RID self; - - GD_VS::ShaderMode mode; - ShaderGLES2 *shader; - String code; - SelfList<Material>::List materials; - - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; - - uint32_t texture_count; - - uint32_t custom_code_id; - uint32_t version; - - SelfList<Shader> dirty_list; - - Map<StringName, RID> default_textures; - - Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; - - bool valid; - - String path; - - uint32_t index; - uint64_t last_pass; - - struct CanvasItem { - enum BlendMode { - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - BLEND_MODE_PMALPHA, - }; - - int blend_mode; - - enum LightMode { - LIGHT_MODE_NORMAL, - LIGHT_MODE_UNSHADED, - LIGHT_MODE_LIGHT_ONLY - }; - - int light_mode; - - // these flags are specifically for batching - // some of the logic is thus in rasterizer_storage.cpp - // we could alternatively set bitflags for each 'uses' and test on the fly - // defined in RasterizerStorageCommon::BatchFlags - unsigned int batch_flags; - - bool uses_screen_texture; - bool uses_screen_uv; - bool uses_time; - bool uses_modulate; - bool uses_color; - bool uses_vertex; - - // all these should disable item joining if used in a custom shader - bool uses_world_matrix; - bool uses_extra_matrix; - bool uses_projection_matrix; - bool uses_instance_custom; - - } canvas_item; - - struct Spatial { - enum BlendMode { - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - }; - - int blend_mode; - - enum DepthDrawMode { - DEPTH_DRAW_OPAQUE, - DEPTH_DRAW_ALWAYS, - DEPTH_DRAW_NEVER, - DEPTH_DRAW_ALPHA_PREPASS, - }; - - int depth_draw_mode; - - enum CullMode { - CULL_MODE_FRONT, - CULL_MODE_BACK, - CULL_MODE_DISABLED, - }; - - int cull_mode; - - bool uses_alpha; - bool uses_alpha_scissor; - bool unshaded; - bool no_depth_test; - bool uses_vertex; - bool uses_discard; - bool uses_sss; - bool uses_screen_texture; - bool uses_depth_texture; - bool uses_time; - bool uses_tangent; - bool uses_ensure_correct_normals; - bool writes_modelview_or_projection; - bool uses_vertex_lighting; - bool uses_world_coordinates; - - } spatial; - - struct Particles { - } particles; - - bool uses_vertex_time; - bool uses_fragment_time; - - Shader() : - dirty_list(this) { - shader = NULL; - valid = false; - custom_code_id = 0; - version = 1; - last_pass = 0; - } - }; - - mutable RID_PtrOwner<Shader> shader_owner; - mutable SelfList<Shader>::List _shader_dirty_list; - - void _shader_make_dirty(Shader *p_shader); - - RID shader_allocate() override; - void shader_initialize(RID p_rid) override; - - //virtual RID shader_create() override; - - virtual void shader_set_code(RID p_shader, const String &p_code) override; - virtual String shader_get_code(RID p_shader) const override; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override; - - virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; - - virtual void shader_add_custom_define(RID p_shader, const String &p_define); - virtual void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const; - virtual void shader_remove_custom_define(RID p_shader, const String &p_define); - - void _update_shader(Shader *p_shader) const; - void update_dirty_shaders(); - - // new - Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } - - // COMMON MATERIAL API - - struct Material { - RID self; - Shader *shader; - Map<StringName, Variant> params; - SelfList<Material> list; - SelfList<Material> dirty_list; - Vector<Pair<StringName, RID>> textures; - float line_width; - int render_priority; - - RID next_pass; - - uint32_t index; - uint64_t last_pass; - - // Map<Geometry *, int> geometry_owners; - // Map<InstanceBaseDependency *, int> instance_owners; - - bool can_cast_shadow_cache; - bool is_animated_cache; - - Material() : - list(this), - dirty_list(this) { - can_cast_shadow_cache = false; - is_animated_cache = false; - shader = NULL; - line_width = 1.0; - last_pass = 0; - render_priority = 0; - } - }; - - mutable SelfList<Material>::List _material_dirty_list; - void _material_make_dirty(Material *p_material) const; - - // void _material_add_geometry(RID p_material, Geometry *p_geometry); - // void _material_remove_geometry(RID p_material, Geometry *p_geometry); - - void _update_material(Material *p_material); - - mutable RID_PtrOwner<Material> material_owner; - - // new - void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {} - void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {} - - // old - RID material_allocate() override; - void material_initialize(RID p_rid) override; - - //virtual RID material_create() override; - - virtual void material_set_shader(RID p_material, RID p_shader) override; - virtual RID material_get_shader(RID p_material) const; - - virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override; - virtual Variant material_get_param(RID p_material, const StringName &p_param) const override; - virtual Variant material_get_param_default(RID p_material, const StringName &p_param) const; - - virtual void material_set_line_width(RID p_material, float p_width); - virtual void material_set_next_pass(RID p_material, RID p_next_material) override; - - virtual bool material_is_animated(RID p_material) override; - virtual bool material_casts_shadows(RID p_material) override; - virtual bool material_uses_tangents(RID p_material); - virtual bool material_uses_ensure_correct_normals(RID p_material); - - virtual void material_add_instance_owner(RID p_material, DependencyTracker *p_instance); - virtual void material_remove_instance_owner(RID p_material, DependencyTracker *p_instance); - - virtual void material_set_render_priority(RID p_material, int priority) override; - - void update_dirty_materials(); - - // RENDER TARGET - - struct RenderTarget { - RID self; - GLuint fbo; - GLuint color; - GLuint depth; - - GLuint multisample_fbo; - GLuint multisample_color; - GLuint multisample_depth; - bool multisample_active; - - struct Effect { - GLuint fbo; - int width; - int height; - - GLuint color; - - Effect() : - fbo(0), - width(0), - height(0), - color(0) { - } - }; - - Effect copy_screen_effect; - - struct MipMaps { - struct Size { - GLuint fbo; - GLuint color; - int width; - int height; - }; - - Vector<Size> sizes; - GLuint color; - int levels; - - MipMaps() : - color(0), - levels(0) { - } - }; - - MipMaps mip_maps[2]; - - struct External { - GLuint fbo; - GLuint color; - GLuint depth; - RID texture; - - External() : - fbo(0), - color(0), - depth(0) { - } - } external; - - int x, y, width, height; - - bool flags[RENDER_TARGET_FLAG_MAX]; - - // instead of allocating sized render targets immediately, - // defer this for faster startup - bool allocate_is_dirty = false; - bool used_in_frame; - GD_VS::ViewportMSAA msaa; - - bool use_fxaa; - bool use_debanding; - - RID texture; - - bool used_dof_blur_near; - bool mip_maps_allocated; - - Color clear_color; - bool clear_requested; - - RenderTarget() : - fbo(0), - color(0), - depth(0), - multisample_fbo(0), - multisample_color(0), - multisample_depth(0), - multisample_active(false), - x(0), - y(0), - width(0), - height(0), - used_in_frame(false), - msaa(GD_VS::VIEWPORT_MSAA_DISABLED), - use_fxaa(false), - use_debanding(false), - used_dof_blur_near(false), - mip_maps_allocated(false), - clear_color(Color(1, 1, 1, 1)), - clear_requested(false) { - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) { - flags[i] = false; - } - external.fbo = 0; - } - }; - - mutable RID_PtrOwner<RenderTarget> render_target_owner; - - void _render_target_clear(RenderTarget *rt); - void _render_target_allocate(RenderTarget *rt); - void _set_current_render_target(RID p_render_target); - - virtual RID render_target_create() override; - virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override; - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override; - virtual RID render_target_get_texture(RID p_render_target) override; - virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override; - - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override; - virtual bool render_target_was_used(RID p_render_target) override; - virtual void render_target_clear_used(RID p_render_target); - virtual void render_target_set_msaa(RID p_render_target, GD_VS::ViewportMSAA p_msaa); - virtual void render_target_set_use_fxaa(RID p_render_target, bool p_fxaa); - virtual void render_target_set_use_debanding(RID p_render_target, bool p_debanding); - - // new - void render_target_set_as_unused(RID p_render_target) override { render_target_clear_used(p_render_target); } - - void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override; - bool render_target_is_clear_requested(RID p_render_target) override; - Color render_target_get_clear_request_color(RID p_render_target) override; - void render_target_disable_clear_request(RID p_render_target) override; - void render_target_do_clear_request(RID p_render_target) override; - - // access from canvas - // RenderTarget * render_target_get(RID p_render_target); - - /* CANVAS SHADOW */ - - struct CanvasLightShadow { - RID self; - int size; - int height; - GLuint fbo; - GLuint depth; - GLuint distance; //for older devices - }; - - RID_PtrOwner<CanvasLightShadow> canvas_light_shadow_owner; - - virtual RID canvas_light_shadow_buffer_create(int p_width); - - /* LIGHT SHADOW MAPPING */ - /* - struct CanvasOccluder { - RID self; - - GLuint vertex_id; // 0 means, unconfigured - GLuint index_id; // 0 means, unconfigured - LocalVector<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 LocalVector<Vector2> &p_lines); -*/ - - virtual GD_VS::InstanceType get_base_type(RID p_rid) const override; - - virtual bool free(RID p_rid) override; - - struct Frame { - RenderTarget *current_rt; - - // these 2 may have been superceded by the equivalents in the render target. - // these may be able to be removed. - bool clear_request; - Color clear_request_color; - - float time[4]; - float delta; - uint64_t count; - - Frame() { - // current_rt = nullptr; - // clear_request = false; - } - } frame; - - void initialize(); - void finalize(); - - void _copy_screen(); - - virtual bool has_os_feature(const String &p_feature) const override; - - virtual void update_dirty_resources() override; - - virtual void set_debug_generate_wireframes(bool p_generate) override; - - // virtual void render_info_begin_capture() override; - // virtual void render_info_end_capture() override; - // virtual int get_captured_render_info(GD_VS::RenderInfo p_info) override; - - // virtual int get_render_info(GD_VS::RenderInfo p_info) override; - virtual String get_video_adapter_name() const override; - virtual String get_video_adapter_vendor() const override; - - void capture_timestamps_begin() override {} - void capture_timestamp(const String &p_name) override {} - uint32_t get_captured_timestamps_count() const override { return 0; } - uint64_t get_captured_timestamps_frame() const override { return 0; } - uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; } - uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; } - String get_captured_timestamp_name(uint32_t p_index) const override { return String(); } - - // make access easier to these - struct Dimensions { - // render target - int rt_width; - int rt_height; - - // window - int win_width; - int win_height; - Dimensions() { - rt_width = 0; - rt_height = 0; - win_width = 0; - win_height = 0; - } - } _dims; - - void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER, GLenum p_usage = GL_DYNAMIC_DRAW, bool p_optional_orphan = false) const; - bool safe_buffer_sub_data(unsigned int p_total_buffer_size, GLenum p_target, unsigned int p_offset, unsigned int p_data_size, const void *p_data, unsigned int &r_offset_after) const; - - void bind_framebuffer(GLuint framebuffer) { - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - } - - void bind_framebuffer_system() { - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); - } - - RasterizerStorageGLES2(); -}; - -inline bool RasterizerStorageGLES2::safe_buffer_sub_data(unsigned int p_total_buffer_size, GLenum p_target, unsigned int p_offset, unsigned int p_data_size, const void *p_data, unsigned int &r_offset_after) const { - r_offset_after = p_offset + p_data_size; -#ifdef DEBUG_ENABLED - // we are trying to write across the edge of the buffer - if (r_offset_after > p_total_buffer_size) - return false; -#endif - glBufferSubData(p_target, p_offset, p_data_size, p_data); - return true; -} - -// standardize the orphan / upload in one place so it can be changed per platform as necessary, and avoid future -// bugs causing pipeline stalls -inline void RasterizerStorageGLES2::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target, GLenum p_usage, bool p_optional_orphan) const { - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - // Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other) - if (!p_optional_orphan || (config.should_orphan)) { - glBufferData(p_target, p_buffer_size, NULL, p_usage); -#ifdef RASTERIZER_EXTRA_CHECKS - // fill with garbage off the end of the array - if (p_buffer_size) { - unsigned int start = p_offset + p_data_size; - unsigned int end = start + 1024; - if (end < p_buffer_size) { - uint8_t *garbage = (uint8_t *)alloca(1024); - for (int n = 0; n < 1024; n++) { - garbage[n] = Math::random(0, 255); - } - glBufferSubData(p_target, start, 1024, garbage); - } - } -#endif - } - RAST_DEV_DEBUG_ASSERT((p_offset + p_data_size) <= p_buffer_size); - glBufferSubData(p_target, p_offset, p_data_size, p_data); -} - -#endif // GLES2_BACKEND_ENABLED -#endif // RASTERIZERSTORAGEGLES2_H diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp deleted file mode 100644 index 2784b156fc..0000000000 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ /dev/null @@ -1,1125 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shader_compiler_gles2.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/os/os.h" - -//#ifdef GODOT_3 - -#ifdef GODOT_3 -#include "core/project_settings.h" -#include "core/string_buffer.h" -#include "core/string_builder.h" -#else -#include "core/config/project_settings.h" -#include "core/string/string_buffer.h" -#include "core/string/string_builder.h" - -#endif - -#define SL ShaderLanguage - -static String _mktab(int p_level) { - String tb; - for (int i = 0; i < p_level; i++) { - tb += "\t"; - } - - return tb; -} - -static String _typestr(SL::DataType p_type) { - return ShaderLanguage::get_datatype_name(p_type); -} - -static String _prestr(SL::DataPrecision p_pres) { - switch (p_pres) { - case SL::PRECISION_LOWP: - return "lowp "; - case SL::PRECISION_MEDIUMP: - return "mediump "; - case SL::PRECISION_HIGHP: - return "highp "; - case SL::PRECISION_DEFAULT: - return ""; - } - return ""; -} - -static String _qualstr(SL::ArgumentQualifier p_qual) { - switch (p_qual) { - case SL::ARGUMENT_QUALIFIER_IN: - return "in "; - case SL::ARGUMENT_QUALIFIER_OUT: - return "out "; - case SL::ARGUMENT_QUALIFIER_INOUT: - return "inout "; - } - return ""; -} - -static String _opstr(SL::Operator p_op) { - return SL::get_operator_text(p_op); -} - -static String _mkid(const String &p_id) { - String id = "m_" + p_id.replace("__", "_dus_"); - return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl -} - -static String f2sp0(float p_float) { - String num = rtoss(p_float); - if (num.find(".") == -1 && num.find("e") == -1) { - num += ".0"; - } - return num; -} - -static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) { - switch (p_type) { - case SL::TYPE_BOOL: - return p_values[0].boolean ? "true" : "false"; - case SL::TYPE_BVEC2: - case SL::TYPE_BVEC3: - case SL::TYPE_BVEC4: { - StringBuffer<> text; - - text += "bvec"; - text += itos(p_type - SL::TYPE_BOOL + 1); - text += "("; - - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += p_values[i].boolean ? "true" : "false"; - } - text += ")"; - return text.as_string(); - } - - // GLSL ES 2 doesn't support uints, so we just use signed ints instead... - case SL::TYPE_UINT: - return itos(p_values[0].uint); - case SL::TYPE_UVEC2: - case SL::TYPE_UVEC3: - case SL::TYPE_UVEC4: { - StringBuffer<> text; - - text += "ivec"; - text += itos(p_type - SL::TYPE_UINT + 1); - text += "("; - - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += itos(p_values[i].uint); - } - text += ")"; - return text.as_string(); - - } break; - - case SL::TYPE_INT: - return itos(p_values[0].sint); - case SL::TYPE_IVEC2: - case SL::TYPE_IVEC3: - case SL::TYPE_IVEC4: { - StringBuffer<> text; - - text += "ivec"; - text += itos(p_type - SL::TYPE_INT + 1); - text += "("; - - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += itos(p_values[i].sint); - } - text += ")"; - return text.as_string(); - - } break; - case SL::TYPE_FLOAT: - return f2sp0(p_values[0].real); - case SL::TYPE_VEC2: - case SL::TYPE_VEC3: - case SL::TYPE_VEC4: { - StringBuffer<> text; - - text += "vec"; - text += itos(p_type - SL::TYPE_FLOAT + 1); - text += "("; - - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += f2sp0(p_values[i].real); - } - text += ")"; - return text.as_string(); - - } break; - case SL::TYPE_MAT2: - case SL::TYPE_MAT3: - case SL::TYPE_MAT4: { - StringBuffer<> text; - - text += "mat"; - text += itos(p_type - SL::TYPE_MAT2 + 2); - text += "("; - - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += f2sp0(p_values[i].real); - } - text += ")"; - return text.as_string(); - - } break; - default: - ERR_FAIL_V(String()); - } -} - -void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added) { - int fidx = -1; - - for (int i = 0; i < p_node->functions.size(); i++) { - if (p_node->functions[i].name == p_for_func) { - fidx = i; - break; - } - } - - ERR_FAIL_COND(fidx == -1); - - for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { - if (r_added.has(E->get())) { - continue; - } - - _dump_function_deps(p_node, E->get(), p_func_code, r_to_add, r_added); - - SL::FunctionNode *fnode = NULL; - - for (int i = 0; i < p_node->functions.size(); i++) { - if (p_node->functions[i].name == E->get()) { - fnode = p_node->functions[i].function; - break; - } - } - - ERR_FAIL_COND(!fnode); - - r_to_add += "\n"; - - StringBuffer<128> header; - - header += _typestr(fnode->return_type); - header += " "; - header += _mkid(fnode->name); - header += "("; - - for (int i = 0; i < fnode->arguments.size(); i++) { - if (i > 0) - header += ", "; - - header += _qualstr(fnode->arguments[i].qualifier); - header += _prestr(fnode->arguments[i].precision); - header += _typestr(fnode->arguments[i].type); - header += " "; - header += _mkid(fnode->arguments[i].name); - } - - header += ")\n"; - r_to_add += header.as_string(); - r_to_add += p_func_code[E->get()]; - - r_added.insert(E->get()); - } -} - -String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) { - StringBuilder code; - - switch (p_node->type) { - default: { - } break; - case SL::Node::TYPE_SHADER: { - SL::ShaderNode *snode = (SL::ShaderNode *)p_node; - - for (int i = 0; i < snode->render_modes.size(); i++) { - if (p_default_actions.render_mode_defines.has(snode->render_modes[i]) && !used_rmode_defines.has(snode->render_modes[i])) { - r_gen_code.custom_defines.push_back(p_default_actions.render_mode_defines[snode->render_modes[i]].utf8()); - used_rmode_defines.insert(snode->render_modes[i]); - } - - if (p_actions.render_mode_flags.has(snode->render_modes[i])) { - *p_actions.render_mode_flags[snode->render_modes[i]] = true; - } - - if (p_actions.render_mode_values.has(snode->render_modes[i])) { - Pair<int *, int> &p = p_actions.render_mode_values[snode->render_modes[i]]; - *p.first = p.second; - } - } - - int max_texture_uniforms = 0; - int max_uniforms = 0; - - for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) { - if (SL::is_sampler_type(E->get().type)) - max_texture_uniforms++; - else - max_uniforms++; - } - - r_gen_code.texture_uniforms.resize(max_texture_uniforms); - r_gen_code.texture_hints.resize(max_texture_uniforms); - - r_gen_code.uniforms.resize(max_uniforms + max_texture_uniforms); - - StringBuilder vertex_global; - StringBuilder fragment_global; - - // uniforms - - for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) { - StringBuffer<> uniform_code; - - // use highp if no precision is specified to prevent different default values in fragment and vertex shader - SL::DataPrecision precision = E->get().precision; - if (precision == SL::PRECISION_DEFAULT && E->get().type != SL::TYPE_BOOL) { - precision = SL::PRECISION_HIGHP; - } - - uniform_code += "uniform "; - uniform_code += _prestr(precision); - uniform_code += _typestr(E->get().type); - uniform_code += " "; - uniform_code += _mkid(E->key()); - uniform_code += ";\n"; - - if (SL::is_sampler_type(E->get().type)) { - r_gen_code.texture_uniforms.write[E->get().texture_order] = E->key(); - r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint; - } else { - r_gen_code.uniforms.write[E->get().order] = E->key(); - } - - vertex_global += uniform_code.as_string(); - fragment_global += uniform_code.as_string(); - - p_actions.uniforms->insert(E->key(), E->get()); - } - - // varyings - - for (Map<StringName, SL::ShaderNode::Varying>::Element *E = snode->varyings.front(); E; E = E->next()) { - StringBuffer<> varying_code; - - varying_code += "varying "; - varying_code += _prestr(E->get().precision); - varying_code += _typestr(E->get().type); - varying_code += " "; - varying_code += _mkid(E->key()); - if (E->get().array_size > 0) { - varying_code += "["; - varying_code += itos(E->get().array_size); - varying_code += "]"; - } - varying_code += ";\n"; - - String final_code = varying_code.as_string(); - - vertex_global += final_code; - fragment_global += final_code; - } - - // constants - - for (int i = 0; i < snode->vconstants.size(); i++) { - String gcode; - gcode += "const "; - gcode += _prestr(snode->vconstants[i].precision); - gcode += _typestr(snode->vconstants[i].type); - gcode += " " + _mkid(String(snode->vconstants[i].name)); - gcode += "="; - gcode += _dump_node_code(snode->vconstants[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - gcode += ";\n"; - vertex_global += gcode; - fragment_global += gcode; - } - - // functions - - Map<StringName, String> function_code; - - for (int i = 0; i < snode->functions.size(); i++) { - SL::FunctionNode *fnode = snode->functions[i].function; - current_func_name = fnode->name; - function_code[fnode->name] = _dump_node_code(fnode->body, 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } - - Set<StringName> added_vertex; - Set<StringName> added_fragment; - - for (int i = 0; i < snode->functions.size(); i++) { - SL::FunctionNode *fnode = snode->functions[i].function; - - current_func_name = fnode->name; - - if (fnode->name == vertex_name) { - _dump_function_deps(snode, fnode->name, function_code, vertex_global, added_vertex); - r_gen_code.vertex = function_code[vertex_name]; - - } else if (fnode->name == fragment_name) { - _dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment); - r_gen_code.fragment = function_code[fragment_name]; - - } else if (fnode->name == light_name) { - _dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment); - r_gen_code.light = function_code[light_name]; - } - } - - r_gen_code.vertex_global = vertex_global.as_string(); - r_gen_code.fragment_global = fragment_global.as_string(); - - } break; - - case SL::Node::TYPE_FUNCTION: { - } break; - - case SL::Node::TYPE_BLOCK: { - SL::BlockNode *bnode = (SL::BlockNode *)p_node; - - if (!bnode->single_statement) { - code += _mktab(p_level - 1); - code += "{\n"; - } - - for (int i = 0; i < bnode->statements.size(); i++) { - String statement_code = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - - if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) { - code += statement_code; - } else { - code += _mktab(p_level); - code += statement_code; - code += ";\n"; - } - } - - if (!bnode->single_statement) { - code += _mktab(p_level - 1); - code += "}\n"; - } - } break; - - case SL::Node::TYPE_VARIABLE_DECLARATION: { - SL::VariableDeclarationNode *var_dec_node = (SL::VariableDeclarationNode *)p_node; - - StringBuffer<> declaration; - if (var_dec_node->is_const) { - declaration += "const "; - } - declaration += _prestr(var_dec_node->precision); - declaration += _typestr(var_dec_node->datatype); - - for (int i = 0; i < var_dec_node->declarations.size(); i++) { - if (i > 0) { - declaration += ","; - } - - declaration += " "; - - declaration += _mkid(var_dec_node->declarations[i].name); - - if (var_dec_node->declarations[i].initializer) { - declaration += " = "; - declaration += _dump_node_code(var_dec_node->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - } - - code += declaration.as_string(); - } break; - - case SL::Node::TYPE_VARIABLE: { - SL::VariableNode *var_node = (SL::VariableNode *)p_node; - - if (p_assigning && p_actions.write_flag_pointers.has(var_node->name)) { - *p_actions.write_flag_pointers[var_node->name] = true; - } - - if (p_default_actions.usage_defines.has(var_node->name) && !used_name_defines.has(var_node->name)) { - String define = p_default_actions.usage_defines[var_node->name]; - String node_name = define.substr(1, define.length()); - - if (define.begins_with("@")) { - define = p_default_actions.usage_defines[node_name]; - } - - if (!used_name_defines.has(node_name)) { - r_gen_code.custom_defines.push_back(define.utf8()); - } - used_name_defines.insert(var_node->name); - } - - if (p_actions.usage_flag_pointers.has(var_node->name) && !used_flag_pointers.has(var_node->name)) { - *p_actions.usage_flag_pointers[var_node->name] = true; - used_flag_pointers.insert(var_node->name); - } - - if (p_default_actions.renames.has(var_node->name)) { - code += p_default_actions.renames[var_node->name]; - } else { - code += _mkid(var_node->name); - } - - if (var_node->name == time_name) { - if (current_func_name == vertex_name) { - r_gen_code.uses_vertex_time = true; - } - if (current_func_name == fragment_name || current_func_name == light_name) { - r_gen_code.uses_fragment_time = true; - } - } - } break; - case SL::Node::TYPE_ARRAY_DECLARATION: { - SL::ArrayDeclarationNode *arr_dec_node = (SL::ArrayDeclarationNode *)p_node; - - StringBuffer<> declaration; - declaration += _prestr(arr_dec_node->precision); - declaration += _typestr(arr_dec_node->datatype); - - for (int i = 0; i < arr_dec_node->declarations.size(); i++) { - if (i > 0) { - declaration += ","; - } - - declaration += " "; - - declaration += _mkid(arr_dec_node->declarations[i].name); - declaration += "["; - declaration += itos(arr_dec_node->declarations[i].size); - declaration += "]"; - } - - code += declaration.as_string(); - } break; - case SL::Node::TYPE_ARRAY: { - SL::ArrayNode *arr_node = (SL::ArrayNode *)p_node; - - if (p_assigning && p_actions.write_flag_pointers.has(arr_node->name)) { - *p_actions.write_flag_pointers[arr_node->name] = true; - } - - if (p_default_actions.usage_defines.has(arr_node->name) && !used_name_defines.has(arr_node->name)) { - String define = p_default_actions.usage_defines[arr_node->name]; - String node_name = define.substr(1, define.length()); - - if (define.begins_with("@")) { - define = p_default_actions.usage_defines[node_name]; - } - - if (!used_name_defines.has(node_name)) { - r_gen_code.custom_defines.push_back(define.utf8()); - } - used_name_defines.insert(arr_node->name); - } - - if (p_actions.usage_flag_pointers.has(arr_node->name) && !used_flag_pointers.has(arr_node->name)) { - *p_actions.usage_flag_pointers[arr_node->name] = true; - used_flag_pointers.insert(arr_node->name); - } - - if (p_default_actions.renames.has(arr_node->name)) { - code += p_default_actions.renames[arr_node->name]; - } else { - code += _mkid(arr_node->name); - } - - if (arr_node->call_expression != NULL) { - code += "."; - code += _dump_node_code(arr_node->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false); - } - - if (arr_node->index_expression != NULL) { - code += "["; - code += _dump_node_code(arr_node->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "]"; - } - - if (arr_node->name == time_name) { - if (current_func_name == vertex_name) { - r_gen_code.uses_vertex_time = true; - } - if (current_func_name == fragment_name || current_func_name == light_name) { - r_gen_code.uses_fragment_time = true; - } - } - - } break; - case SL::Node::TYPE_CONSTANT: { - SL::ConstantNode *const_node = (SL::ConstantNode *)p_node; - - return get_constant_text(const_node->datatype, const_node->values); - } break; - - case SL::Node::TYPE_OPERATOR: { - SL::OperatorNode *op_node = (SL::OperatorNode *)p_node; - - switch (op_node->op) { - case SL::OP_ASSIGN: - case SL::OP_ASSIGN_ADD: - case SL::OP_ASSIGN_SUB: - case SL::OP_ASSIGN_MUL: - case SL::OP_ASSIGN_DIV: - case SL::OP_ASSIGN_SHIFT_LEFT: - case SL::OP_ASSIGN_SHIFT_RIGHT: - case SL::OP_ASSIGN_BIT_AND: - case SL::OP_ASSIGN_BIT_OR: - case SL::OP_ASSIGN_BIT_XOR: { - code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true); - code += " "; - code += _opstr(op_node->op); - code += " "; - code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } break; - - case SL::OP_ASSIGN_MOD: { - String a = _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String n = _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += a + " = " + n + " == 0 ? 0 : "; - code += a + " - " + n + " * (" + a + " / " + n + ")"; - } break; - - case SL::OP_BIT_INVERT: - case SL::OP_NEGATE: - case SL::OP_NOT: - case SL::OP_DECREMENT: - case SL::OP_INCREMENT: { - code += _opstr(op_node->op); - code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } break; - - case SL::OP_POST_DECREMENT: - case SL::OP_POST_INCREMENT: { - code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += _opstr(op_node->op); - } break; - - case SL::OP_CALL: - case SL::OP_CONSTRUCT: { - ERR_FAIL_COND_V(op_node->arguments[0]->type != SL::Node::TYPE_VARIABLE, String()); - - SL::VariableNode *var_node = (SL::VariableNode *)op_node->arguments[0]; - - if (op_node->op == SL::OP_CONSTRUCT) { - code += var_node->name; - } else { - if (var_node->name == "texture") { - // emit texture call - - if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D) { // || - // op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLEREXT) { - code += "texture2D"; - } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) { - code += "textureCube"; - } - - } else if (var_node->name == "textureLod") { - // emit texture call - - if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D) { - code += "texture2DLod"; - } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) { - code += "textureCubeLod"; - } - - } else if (var_node->name == "mix") { - switch (op_node->arguments[3]->get_datatype()) { - case SL::TYPE_BVEC2: { - code += "select2"; - } break; - - case SL::TYPE_BVEC3: { - code += "select3"; - } break; - - case SL::TYPE_BVEC4: { - code += "select4"; - } break; - - case SL::TYPE_VEC2: - case SL::TYPE_VEC3: - case SL::TYPE_VEC4: - case SL::TYPE_FLOAT: { - code += "mix"; - } break; - - default: { - SL::DataType type = op_node->arguments[3]->get_datatype(); - // FIXME: Proper error print or graceful handling - print_line(String("uhhhh invalid mix with type: ") + itos(type)); - } break; - } - - } else if (p_default_actions.renames.has(var_node->name)) { - code += p_default_actions.renames[var_node->name]; - } else if (internal_functions.has(var_node->name)) { - code += var_node->name; - } else { - code += _mkid(var_node->name); - } - } - - code += "("; - - for (int i = 1; i < op_node->arguments.size(); i++) { - if (i > 1) { - code += ", "; - } - - code += _dump_node_code(op_node->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - - code += ")"; - - if (p_default_actions.usage_defines.has(var_node->name) && !used_name_defines.has(var_node->name)) { - String define = p_default_actions.usage_defines[var_node->name]; - String node_name = define.substr(1, define.length()); - - if (define.begins_with("@")) { - define = p_default_actions.usage_defines[node_name]; - } - - if (!used_name_defines.has(node_name)) { - r_gen_code.custom_defines.push_back(define.utf8()); - } - used_name_defines.insert(var_node->name); - } - - } break; - - case SL::OP_INDEX: { - code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "["; - code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "]"; - } break; - - case SL::OP_SELECT_IF: { - code += "("; - code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += " ? "; - code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += " : "; - code += _dump_node_code(op_node->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ")"; - } break; - - case SL::OP_MOD: { - String a = _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String n = _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "(" + n + " == 0 ? 0 : "; - code += a + " - " + n + " * (" + a + " / " + n + "))"; - } break; - - default: { - if (p_use_scope) { - code += "("; - } - code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += " "; - code += _opstr(op_node->op); - code += " "; - code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (p_use_scope) { - code += ")"; - } - } break; - } - } break; - - case SL::Node::TYPE_CONTROL_FLOW: { - SL::ControlFlowNode *cf_node = (SL::ControlFlowNode *)p_node; - - if (cf_node->flow_op == SL::FLOW_OP_IF) { - code += _mktab(p_level); - code += "if ("; - code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ")\n"; - code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - - if (cf_node->blocks.size() == 2) { - code += _mktab(p_level); - code += "else\n"; - code += _dump_node_code(cf_node->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } - } else if (cf_node->flow_op == SL::FLOW_OP_DO) { - code += _mktab(p_level); - code += "do"; - code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - code += _mktab(p_level); - code += "while ("; - code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ");"; - } else if (cf_node->flow_op == SL::FLOW_OP_WHILE) { - code += _mktab(p_level); - code += "while ("; - code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ")\n"; - code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cf_node->flow_op == SL::FLOW_OP_FOR) { - code += _mktab(p_level); - code += "for ("; - code += _dump_node_code(cf_node->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "; "; - code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "; "; - code += _dump_node_code(cf_node->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ")\n"; - - code += _dump_node_code(cf_node->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - - } else if (cf_node->flow_op == SL::FLOW_OP_RETURN) { - code += _mktab(p_level); - code += "return"; - - if (cf_node->expressions.size()) { - code += " "; - code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - code += ";\n"; - } else if (cf_node->flow_op == SL::FLOW_OP_DISCARD) { - if (p_actions.usage_flag_pointers.has("DISCARD") && !used_flag_pointers.has("DISCARD")) { - *p_actions.usage_flag_pointers["DISCARD"] = true; - used_flag_pointers.insert("DISCARD"); - } - code += "discard;"; - } else if (cf_node->flow_op == SL::FLOW_OP_CONTINUE) { - code += "continue;"; - } else if (cf_node->flow_op == SL::FLOW_OP_BREAK) { - code += "break;"; - } - } break; - - case SL::Node::TYPE_MEMBER: { - SL::MemberNode *member_node = (SL::MemberNode *)p_node; - code += _dump_node_code(member_node->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "."; - code += member_node->name; - } break; - } - - return code.as_string(); -} - -ShaderLanguage::DataType ShaderCompilerGLES2::_get_variable_type(const StringName &p_type) { - // RS::GlobalVariableType gvt = ((RasterizerStorageRD *)(RendererStorage::base_singleton))->global_variable_get_type_internal(p_type); - RS::GlobalVariableType gvt = RS::GLOBAL_VAR_TYPE_MAX; - return RS::global_variable_type_get_shader_datatype(gvt); -} - -Error ShaderCompilerGLES2::compile(GD_VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { - - ShaderLanguage::VaryingFunctionNames var_names; - - Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), var_names, ShaderTypes::get_singleton()->get_types(), _get_variable_type); - - // Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) { - if (err != OK) { - Vector<String> shader = p_code.split("\n"); - for (int i = 0; i < shader.size(); i++) { - print_line(itos(i + 1) + " " + shader[i]); - } - - _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER); - return err; - } - - r_gen_code.custom_defines.clear(); - r_gen_code.uniforms.clear(); - r_gen_code.texture_uniforms.clear(); - r_gen_code.texture_hints.clear(); - r_gen_code.vertex = String(); - r_gen_code.vertex_global = String(); - r_gen_code.fragment = String(); - r_gen_code.fragment_global = String(); - r_gen_code.light = String(); - r_gen_code.uses_fragment_time = false; - r_gen_code.uses_vertex_time = false; - - used_name_defines.clear(); - used_rmode_defines.clear(); - used_flag_pointers.clear(); - - _dump_node_code(parser.get_shader(), 1, r_gen_code, *p_actions, actions[p_mode], false); - - return OK; -} - -ShaderCompilerGLES2::ShaderCompilerGLES2() { - /** CANVAS ITEM SHADER **/ - - actions[GD_VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "point_size"; - - actions[GD_VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] = "extra_matrix_instance"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["TIME"] = "time"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom"; - - actions[GD_VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["MODULATE"] = "final_modulate"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord"; - - actions[GD_VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color"; - actions[GD_VS::SHADER_CANVAS_ITEM].renames["SHADOW_VEC"] = "shadow_vec"; - - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["MODULATE"] = "#define MODULATE_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_VEC"] = "#define SHADOW_VEC_USED\n"; - - // Ported from GLES3 - - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["sinh"] = "#define SINH_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["cosh"] = "#define COSH_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["tanh"] = "#define TANH_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["asinh"] = "#define ASINH_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["acosh"] = "#define ACOSH_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["atanh"] = "#define ATANH_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["determinant"] = "#define DETERMINANT_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["transpose"] = "#define TRANSPOSE_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["outerProduct"] = "#define OUTER_PRODUCT_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["round"] = "#define ROUND_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["roundEven"] = "#define ROUND_EVEN_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["inverse"] = "#define INVERSE_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["isinf"] = "#define IS_INF_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["isnan"] = "#define IS_NAN_USED\n"; - actions[GD_VS::SHADER_CANVAS_ITEM].usage_defines["trunc"] = "#define TRUNC_USED\n"; - - /** SPATIAL SHADER **/ - - actions[GD_VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; - actions[GD_VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; - actions[GD_VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; - actions[GD_VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[GD_VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "projection_inverse_matrix"; - actions[GD_VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; - - actions[GD_VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; - actions[GD_VS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; - actions[GD_VS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; - actions[GD_VS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; - actions[GD_VS::SHADER_SPATIAL].renames["POSITION"] = "position"; - actions[GD_VS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; - actions[GD_VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; - actions[GD_VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; - actions[GD_VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "point_size"; - // gl_InstanceID is not available in OpenGL ES 2.0 - actions[GD_VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "0"; - - //builtins - - actions[GD_VS::SHADER_SPATIAL].renames["TIME"] = "time"; - actions[GD_VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; - - actions[GD_VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[GD_VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; - actions[GD_VS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; - actions[GD_VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; - actions[GD_VS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; - actions[GD_VS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; - actions[GD_VS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; - actions[GD_VS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; - actions[GD_VS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; - actions[GD_VS::SHADER_SPATIAL].renames["RIM"] = "rim"; - actions[GD_VS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; - actions[GD_VS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; - actions[GD_VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; - actions[GD_VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; - actions[GD_VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; - actions[GD_VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; - actions[GD_VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; - actions[GD_VS::SHADER_SPATIAL].renames["AO"] = "ao"; - actions[GD_VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; - actions[GD_VS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; - actions[GD_VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; - actions[GD_VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; - actions[GD_VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; - actions[GD_VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[GD_VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_texture"; - // Defined in GLES3, but not available in GLES2 - //actions[GD_VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; - actions[GD_VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; - actions[GD_VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - - //for light - actions[GD_VS::SHADER_SPATIAL].renames["VIEW"] = "view"; - actions[GD_VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; - actions[GD_VS::SHADER_SPATIAL].renames["LIGHT"] = "light"; - actions[GD_VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; - actions[GD_VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; - actions[GD_VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; - - actions[GD_VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - - actions[GD_VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["DEPTH_TEXTURE"] = "#define DEPTH_TEXTURE_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - - actions[GD_VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - - // Ported from GLES3 - - actions[GD_VS::SHADER_SPATIAL].usage_defines["sinh"] = "#define SINH_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["cosh"] = "#define COSH_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["tanh"] = "#define TANH_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["asinh"] = "#define ASINH_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["acosh"] = "#define ACOSH_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["atanh"] = "#define ATANH_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["determinant"] = "#define DETERMINANT_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["transpose"] = "#define TRANSPOSE_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["outerProduct"] = "#define OUTER_PRODUCT_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["round"] = "#define ROUND_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["roundEven"] = "#define ROUND_EVEN_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["inverse"] = "#define INVERSE_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["isinf"] = "#define IS_INF_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["isnan"] = "#define IS_NAN_USED\n"; - actions[GD_VS::SHADER_SPATIAL].usage_defines["trunc"] = "#define TRUNC_USED\n"; - - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; - - // Defined in GLES3, could be implemented in GLES2 too if there's a need for it - //actions[GD_VS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; - // Defined in GLES3, might not be possible in GLES2 as gl_FrontFacing is not available - //actions[GD_VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; - //actions[GD_VS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; - - bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley"); - - if (!force_lambert) { - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; - } - - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; - - bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx"); - - if (!force_blinn) { - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } - - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - actions[GD_VS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; - - // No defines for particle shaders in GLES2, there are no GPU particles - - vertex_name = "vertex"; - fragment_name = "fragment"; - light_name = "light"; - time_name = "TIME"; - - List<String> func_list; - - ShaderLanguage::get_builtin_funcs(&func_list); - - for (List<String>::Element *E = func_list.front(); E; E = E->next()) { - internal_functions.insert(E->get()); - } -} - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h deleted file mode 100644 index 580719c47a..0000000000 --- a/drivers/gles2/shader_compiler_gles2.h +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "drivers/gles_common/rasterizer_version.h" -#ifdef GODOT_3 -#include "core/pair.h" -#include "core/string_builder.h" -#include "servers/visual/shader_language.h" -#include "servers/visual/shader_types.h" -#include "servers/visual_server.h" -#else -#include "core/string/string_builder.h" -#include "core/templates/pair.h" -#include "servers/rendering/shader_language.h" -#include "servers/rendering/shader_types.h" -#include "servers/rendering_server.h" -#endif - -class ShaderCompilerGLES2 { -public: - struct IdentifierActions { - Map<StringName, Pair<int *, int>> render_mode_values; - Map<StringName, bool *> render_mode_flags; - Map<StringName, bool *> usage_flag_pointers; - Map<StringName, bool *> write_flag_pointers; - - Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms; - }; - - struct GeneratedCode { - Vector<CharString> custom_defines; - Vector<StringName> uniforms; - Vector<StringName> texture_uniforms; - Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; - - String vertex_global; - String vertex; - String fragment_global; - String fragment; - String light; - - bool uses_fragment_time; - bool uses_vertex_time; - }; - -private: - ShaderLanguage parser; - - struct DefaultIdentifierActions { - Map<StringName, String> renames; - Map<StringName, String> render_mode_defines; - Map<StringName, String> usage_defines; - }; - - void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added); - String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope = true); - - StringName current_func_name; - StringName vertex_name; - StringName fragment_name; - StringName light_name; - StringName time_name; - - Set<StringName> used_name_defines; - Set<StringName> used_flag_pointers; - Set<StringName> used_rmode_defines; - Set<StringName> internal_functions; - - DefaultIdentifierActions actions[GD_VS::SHADER_MAX]; - - // compatibility with godot 4 - static ShaderLanguage::DataType _get_variable_type(const StringName &p_type); - -public: - Error compile(GD_VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); - - ShaderCompilerGLES2(); -}; - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp deleted file mode 100644 index ca493a219b..0000000000 --- a/drivers/gles2/shader_gles2.cpp +++ /dev/null @@ -1,1136 +0,0 @@ -/*************************************************************************/ -/* shader_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shader_gles2.h" -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/os/memory.h" -#include "rasterizer_gles2.h" -#include "rasterizer_storage_gles2.h" - -#ifdef GODOT_3 -#include "core/print_string.h" -#include "core/project_settings.h" -#include "core/string_builder.h" -#else -#include "core/config/project_settings.h" -#include "core/string/print_string.h" -#include "core/string/string_builder.h" -#endif - -// #define DEBUG_OPENGL - -// #include "shaders/copy.glsl.gen.h" - -#ifdef DEBUG_OPENGL - -#define DEBUG_TEST_ERROR(m_section) \ - { \ - uint32_t err = glGetError(); \ - if (err) { \ - print_line("OpenGL Error #" + itos(err) + " at: " + m_section); \ - } \ - } -#else - -#define DEBUG_TEST_ERROR(m_section) - -#endif - -ShaderGLES2 *ShaderGLES2::active = NULL; - -//#define DEBUG_SHADER - -#ifdef DEBUG_SHADER - -#define DEBUG_PRINT(m_text) print_line(m_text); - -#else - -#define DEBUG_PRINT(m_text) - -#endif - -GLint ShaderGLES2::get_uniform_location(int p_index) const { - ERR_FAIL_COND_V(!version, -1); - - return version->uniform_location[p_index]; -} - -//#ifdef GODOT_3 - -bool ShaderGLES2::bind() { - if (active != this || !version || new_conditional_version.key != conditional_version.key) { - conditional_version = new_conditional_version; - version = get_current_version(); - } else { - return false; - } - - ERR_FAIL_COND_V(!version, false); - - if (!version->ok) { //broken, unable to bind (do not throw error, you saw it before already when it failed compilation). - glUseProgram(0); - return false; - } - - glUseProgram(version->id); - - DEBUG_TEST_ERROR("use program"); - - active = this; - uniforms_dirty = true; - - return true; -} - -void ShaderGLES2::unbind() { - version = NULL; - glUseProgram(0); - uniforms_dirty = true; - active = NULL; -} - -static void _display_error_with_code(const String &p_error, const Vector<const char *> &p_code) { - int line = 1; - String total_code; - - for (int i = 0; i < p_code.size(); i++) { - total_code += String(p_code[i]); - } - - Vector<String> lines = String(total_code).split("\n"); - - for (int j = 0; j < lines.size(); j++) { - print_line(itos(line) + ": " + lines[j]); - line++; - } - - ERR_PRINT(p_error); -} - -static String _mkid(const String &p_id) { - String id = "m_" + p_id; - return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl -} - -ShaderGLES2::Version *ShaderGLES2::get_current_version() { - if (!valid) - return nullptr; - - Version *_v = version_map.getptr(conditional_version); - - if (_v) { - if (conditional_version.code_version != 0) { - CustomCode *cc = custom_code_map.getptr(conditional_version.code_version); - ERR_FAIL_COND_V(!cc, _v); - if (cc->version == _v->code_version) - return _v; - } else { - return _v; - } - } - - if (!_v) - version_map[conditional_version] = Version(); - - Version &v = version_map[conditional_version]; - - if (!_v) { - v.uniform_location = memnew_arr(GLint, uniform_count); - } else { - if (v.ok) { - glDeleteShader(v.vert_id); - glDeleteShader(v.frag_id); - glDeleteProgram(v.id); - v.id = 0; - } - } - - v.ok = false; - - Vector<const char *> strings; - -#ifdef GLES_OVER_GL - strings.push_back("#version 120\n"); - strings.push_back("#define USE_GLES_OVER_GL\n"); - - // test - strings.push_back("#define highp\n"); - //#ifdef USE_GLES_OVER_GL - //#define lowp - //#define mediump - //#define highp - //#else - // precision highp float; - // precision highp int; - //#endif - -#else - strings.push_back("#version 100\n"); -//angle does not like -#ifdef JAVASCRIPT_ENABLED - strings.push_back("#define USE_HIGHP_PRECISION\n"); -#endif - - if (GLOBAL_GET("rendering/gles2/compatibility/enable_high_float.Android")) { - // enable USE_HIGHP_PRECISION but safeguarded by an availability check as highp support is optional in GLES2 - // see Section 4.5.4 of the GLSL_ES_Specification_1.00 - strings.push_back("#ifdef GL_FRAGMENT_PRECISION_HIGH\n #define USE_HIGHP_PRECISION\n#endif\n"); - } - -#endif - -#ifdef ANDROID_ENABLED - strings.push_back("#define ANDROID_ENABLED\n"); -#endif - - for (int i = 0; i < custom_defines.size(); i++) { - strings.push_back(custom_defines[i].get_data()); - strings.push_back("\n"); - } - - for (int j = 0; j < conditional_count; j++) { - bool enable = (conditional_version.version & (1 << j)) > 0; - - if (enable) { - strings.push_back(conditional_defines[j]); - DEBUG_PRINT(conditional_defines[j]); - } - } - - // keep them around during the function - CharString code_string; - CharString code_string2; - CharString code_globals; - - CustomCode *cc = NULL; - - if (conditional_version.code_version > 0) { - cc = custom_code_map.getptr(conditional_version.code_version); - - ERR_FAIL_COND_V(!cc, NULL); - v.code_version = cc->version; - } - - // program - - v.id = glCreateProgram(); - ERR_FAIL_COND_V(v.id == 0, NULL); - - if (cc) { - for (int i = 0; i < cc->custom_defines.size(); i++) { - strings.push_back(cc->custom_defines.write[i]); - DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i].get_data())); - } - } - - // vertex shader - - int string_base_size = strings.size(); - - strings.push_back(vertex_code0.get_data()); - - if (cc) { - code_globals = cc->vertex_globals.ascii(); - strings.push_back(code_globals.get_data()); - } - - strings.push_back(vertex_code1.get_data()); - - if (cc) { - code_string = cc->vertex.ascii(); - strings.push_back(code_string.get_data()); - } - - strings.push_back(vertex_code2.get_data()); - -#ifdef DEBUG_SHADER - - DEBUG_PRINT("\nVertex Code:\n\n" + String(code_string.get_data())); - -#endif - - v.vert_id = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(v.vert_id, strings.size(), &strings[0], NULL); - glCompileShader(v.vert_id); - - GLint status; - - glGetShaderiv(v.vert_id, GL_COMPILE_STATUS, &status); - if (status == GL_FALSE) { - GLsizei iloglen; - glGetShaderiv(v.vert_id, GL_INFO_LOG_LENGTH, &iloglen); - - if (iloglen < 0) { - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - - ERR_PRINT("No OpenGL vertex shader compiler log. What the frick?"); - } else { - if (iloglen == 0) { - iloglen = 4096; // buggy driver (Adreno 220+) - } - - char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); - ilogmem[iloglen] = '\0'; - glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem); - - String err_string = get_shader_name() + ": Vertex shader compilation failed:\n"; - - err_string += ilogmem; - - _display_error_with_code(err_string, strings); - - Memory::free_static(ilogmem); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - } - - ERR_FAIL_V(NULL); - } - - strings.resize(string_base_size); - - // fragment shader - - strings.push_back(fragment_code0.get_data()); - - if (cc) { - code_globals = cc->fragment_globals.ascii(); - strings.push_back(code_globals.get_data()); - } - - strings.push_back(fragment_code1.get_data()); - - if (cc) { - code_string = cc->light.ascii(); - strings.push_back(code_string.get_data()); - } - - strings.push_back(fragment_code2.get_data()); - - if (cc) { - code_string2 = cc->fragment.ascii(); - strings.push_back(code_string2.get_data()); - } - - strings.push_back(fragment_code3.get_data()); - -#ifdef DEBUG_SHADER - - if (cc) { - DEBUG_PRINT("\nFragment Code:\n\n" + String(cc->fragment_globals)); - } - DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string.get_data())); -#endif - - v.frag_id = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(v.frag_id, strings.size(), &strings[0], NULL); - glCompileShader(v.frag_id); - - glGetShaderiv(v.frag_id, GL_COMPILE_STATUS, &status); - if (status == GL_FALSE) { - GLsizei iloglen; - glGetShaderiv(v.frag_id, GL_INFO_LOG_LENGTH, &iloglen); - - if (iloglen < 0) { - glDeleteShader(v.frag_id); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - - ERR_PRINT("No OpenGL fragment shader compiler log. What the frick?"); - } else { - if (iloglen == 0) { - iloglen = 4096; // buggy driver (Adreno 220+) - } - - char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); - ilogmem[iloglen] = '\0'; - glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem); - - String err_string = get_shader_name() + ": Fragment shader compilation failed:\n"; - - err_string += ilogmem; - - _display_error_with_code(err_string, strings); - - Memory::free_static(ilogmem); - glDeleteShader(v.frag_id); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - } - - ERR_FAIL_V(NULL); - } - - glAttachShader(v.id, v.frag_id); - glAttachShader(v.id, v.vert_id); - - // bind the attribute locations. This has to be done before linking so that the - // linker doesn't assign some random indices - - for (int i = 0; i < attribute_pair_count; i++) { - glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name); - } - - glLinkProgram(v.id); - - glGetProgramiv(v.id, GL_LINK_STATUS, &status); - if (status == GL_FALSE) { - GLsizei iloglen; - glGetProgramiv(v.id, GL_INFO_LOG_LENGTH, &iloglen); - - if (iloglen < 0) { - glDeleteShader(v.frag_id); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - - ERR_PRINT("No OpenGL program link log. What the frick?"); - ERR_FAIL_V(NULL); - } - - if (iloglen == 0) { - iloglen = 4096; // buggy driver (Adreno 220+) - } - - char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); - ilogmem[iloglen] = '\0'; - glGetProgramInfoLog(v.id, iloglen, &iloglen, ilogmem); - - String err_string = get_shader_name() + ": Program linking failed:\n"; - - err_string += ilogmem; - - _display_error_with_code(err_string, strings); - - Memory::free_static(ilogmem); - glDeleteShader(v.frag_id); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - - ERR_FAIL_V(NULL); - } - - // get uniform locations - - glUseProgram(v.id); - - for (int i = 0; i < uniform_count; i++) { - v.uniform_location[i] = glGetUniformLocation(v.id, uniform_names[i]); - } - - for (int i = 0; i < texunit_pair_count; i++) { - GLint loc = glGetUniformLocation(v.id, texunit_pairs[i].name); - if (loc >= 0) { - if (texunit_pairs[i].index < 0) { - glUniform1i(loc, max_image_units + texunit_pairs[i].index); - } else { - glUniform1i(loc, texunit_pairs[i].index); - } - } - } - - if (cc) { - // uniforms - for (int i = 0; i < cc->custom_uniforms.size(); i++) { - String native_uniform_name = _mkid(cc->custom_uniforms[i]); - GLint location = glGetUniformLocation(v.id, (native_uniform_name).ascii().get_data()); - v.custom_uniform_locations[cc->custom_uniforms[i]] = location; - } - - // textures - for (int i = 0; i < cc->texture_uniforms.size(); i++) { - String native_uniform_name = _mkid(cc->texture_uniforms[i]); - GLint location = glGetUniformLocation(v.id, (native_uniform_name).ascii().get_data()); - v.custom_uniform_locations[cc->texture_uniforms[i]] = location; - glUniform1i(location, i); - } - } - - glUseProgram(0); - v.ok = true; - - if (cc) { - cc->versions.insert(conditional_version.version); - } - - return &v; -} - -GLint ShaderGLES2::get_uniform_location(const String &p_name) const { - ERR_FAIL_COND_V(!version, -1); - return glGetUniformLocation(version->id, p_name.ascii().get_data()); -} - -void ShaderGLES2::setup( - const char **p_conditional_defines, - int p_conditional_count, - const char **p_uniform_names, - int p_uniform_count, - const AttributePair *p_attribute_pairs, - int p_attribute_count, - const TexUnitPair *p_texunit_pairs, - int p_texunit_pair_count, - const char *p_vertex_code, - const char *p_fragment_code, - int p_vertex_code_start, - int p_fragment_code_start) { - ERR_FAIL_COND(version); - - conditional_version.key = 0; - new_conditional_version.key = 0; - uniform_count = p_uniform_count; - conditional_count = p_conditional_count; - conditional_defines = p_conditional_defines; - uniform_names = p_uniform_names; - vertex_code = p_vertex_code; - fragment_code = p_fragment_code; - texunit_pairs = p_texunit_pairs; - texunit_pair_count = p_texunit_pair_count; - vertex_code_start = p_vertex_code_start; - fragment_code_start = p_fragment_code_start; - attribute_pairs = p_attribute_pairs; - attribute_pair_count = p_attribute_count; - - { - String globals_tag = "\nVERTEX_SHADER_GLOBALS"; - String code_tag = "\nVERTEX_SHADER_CODE"; - String code = vertex_code; - int cpos = code.find(globals_tag); - if (cpos == -1) { - vertex_code0 = code.ascii(); - } else { - vertex_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code.find(code_tag); - - if (cpos == -1) { - vertex_code1 = code.ascii(); - } else { - vertex_code1 = code.substr(0, cpos).ascii(); - vertex_code2 = code.substr(cpos + code_tag.length(), code.length()).ascii(); - } - } - } - - { - String globals_tag = "\nFRAGMENT_SHADER_GLOBALS"; - String code_tag = "\nFRAGMENT_SHADER_CODE"; - String light_code_tag = "\nLIGHT_SHADER_CODE"; - String code = fragment_code; - int cpos = code.find(globals_tag); - if (cpos == -1) { - fragment_code0 = code.ascii(); - } else { - fragment_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code.find(light_code_tag); - - String code2; - - if (cpos != -1) { - fragment_code1 = code.substr(0, cpos).ascii(); - code2 = code.substr(cpos + light_code_tag.length(), code.length()); - } else { - code2 = code; - } - - cpos = code2.find(code_tag); - if (cpos == -1) { - fragment_code2 = code2.ascii(); - } else { - fragment_code2 = code2.substr(0, cpos).ascii(); - fragment_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); - } - } - } - - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_image_units); - - valid = true; -} - -void ShaderGLES2::finish() { - const VersionKey *V = NULL; - - while ((V = version_map.next(V))) { - Version &v = version_map[*V]; - glDeleteShader(v.vert_id); - glDeleteShader(v.frag_id); - glDeleteProgram(v.id); - - if (v.uniform_location) - memdelete_arr(v.uniform_location); - } -} - -void ShaderGLES2::clear_caches() { - const VersionKey *V = NULL; - - while ((V = version_map.next(V))) { - Version &v = version_map[*V]; - glDeleteShader(v.vert_id); - glDeleteShader(v.frag_id); - glDeleteProgram(v.id); - memdelete_arr(v.uniform_location); - } - - version_map.clear(); - - custom_code_map.clear(); - version = NULL; - last_custom_code = 1; - uniforms_dirty = true; -} - -uint32_t ShaderGLES2::create_custom_shader() { - custom_code_map[last_custom_code] = CustomCode(); - custom_code_map[last_custom_code].version = 1; - return last_custom_code++; -} - -void ShaderGLES2::set_custom_shader_code(uint32_t p_code_id, - const String &p_vertex, - const String &p_vertex_globals, - const String &p_fragment, - const String &p_light, - const String &p_fragment_globals, - const Vector<StringName> &p_uniforms, - const Vector<StringName> &p_texture_uniforms, - const Vector<CharString> &p_custom_defines) { - CustomCode *cc = custom_code_map.getptr(p_code_id); - ERR_FAIL_COND(!cc); - - cc->vertex = p_vertex; - cc->vertex_globals = p_vertex_globals; - cc->fragment = p_fragment; - cc->fragment_globals = p_fragment_globals; - cc->light = p_light; - cc->custom_uniforms = p_uniforms; - cc->custom_defines = p_custom_defines; - cc->texture_uniforms = p_texture_uniforms; - cc->version++; -} - -void ShaderGLES2::set_custom_shader(uint32_t p_code_id) { - new_conditional_version.code_version = p_code_id; -} - -void ShaderGLES2::free_custom_shader(uint32_t p_code_id) { - ERR_FAIL_COND(!custom_code_map.has(p_code_id)); - if (conditional_version.code_version == p_code_id) { - conditional_version.code_version = 0; //do not keep using a version that is going away - unbind(); - } - - VersionKey key; - key.code_version = p_code_id; - for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { - key.version = E->get(); - ERR_CONTINUE(!version_map.has(key)); - Version &v = version_map[key]; - - glDeleteShader(v.vert_id); - glDeleteShader(v.frag_id); - glDeleteProgram(v.id); - memdelete_arr(v.uniform_location); - v.id = 0; - - version_map.erase(key); - } - - custom_code_map.erase(p_code_id); -} - -void ShaderGLES2::use_material(void *p_material) { - RasterizerStorageGLES2::Material *material = (RasterizerStorageGLES2::Material *)p_material; - - if (!material) { - return; - } - - if (!material->shader) { - return; - } - - Version *v = version_map.getptr(conditional_version); - - // bind uniforms - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = material->shader->uniforms.front(); E; E = E->next()) { - if (E->get().texture_order >= 0) - continue; // this is a texture, doesn't go here - - Map<StringName, GLint>::Element *L = v->custom_uniform_locations.find(E->key()); - if (!L || L->get() < 0) - continue; //uniform not valid - - GLuint location = L->get(); - - Map<StringName, Variant>::Element *V = material->params.find(E->key()); - - if (V) { - switch (E->get().type) { - case ShaderLanguage::TYPE_BOOL: { - bool boolean = V->get(); - glUniform1i(location, boolean ? 1 : 0); - } break; - - case ShaderLanguage::TYPE_BVEC2: { - int flags = V->get(); - glUniform2i(location, (flags & 1) ? 1 : 0, (flags & 2) ? 1 : 0); - } break; - - case ShaderLanguage::TYPE_BVEC3: { - int flags = V->get(); - glUniform3i(location, (flags & 1) ? 1 : 0, (flags & 2) ? 1 : 0, (flags & 4) ? 1 : 0); - - } break; - - case ShaderLanguage::TYPE_BVEC4: { - int flags = V->get(); - glUniform4i(location, (flags & 1) ? 1 : 0, (flags & 2) ? 1 : 0, (flags & 4) ? 1 : 0, (flags & 8) ? 1 : 0); - - } break; - - case ShaderLanguage::TYPE_INT: - case ShaderLanguage::TYPE_UINT: { - int value = V->get(); - glUniform1i(location, value); - } break; - - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_UVEC2: { - Array r = V->get(); - const int count = 2; - if (r.size() == count) { - int values[count]; - for (int i = 0; i < count; i++) { - values[i] = r[i]; - } - glUniform2i(location, values[0], values[1]); - } - - } break; - - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_UVEC3: { - Array r = V->get(); - const int count = 3; - if (r.size() == count) { - int values[count]; - for (int i = 0; i < count; i++) { - values[i] = r[i]; - } - glUniform3i(location, values[0], values[1], values[2]); - } - - } break; - - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC4: { - Array r = V->get(); - const int count = 4; - if (r.size() == count) { - int values[count]; - for (int i = 0; i < count; i++) { - values[i] = r[i]; - } - glUniform4i(location, values[0], values[1], values[2], values[3]); - } - - } break; - - case ShaderLanguage::TYPE_FLOAT: { - float value = V->get(); - glUniform1f(location, value); - - } break; - - case ShaderLanguage::TYPE_VEC2: { - Vector2 value = V->get(); - glUniform2f(location, value.x, value.y); - } break; - - case ShaderLanguage::TYPE_VEC3: { - Vector3 value = V->get(); - glUniform3f(location, value.x, value.y, value.z); - } break; - - case ShaderLanguage::TYPE_VEC4: { - if (V->get().get_type() == Variant::COLOR) { - Color value = V->get(); - glUniform4f(location, value.r, value.g, value.b, value.a); - } else if (V->get().get_type() == Variant::QUATERNION) { - Quaternion value = V->get(); - glUniform4f(location, value.x, value.y, value.z, value.w); - } else { - Plane value = V->get(); - glUniform4f(location, value.normal.x, value.normal.y, value.normal.z, value.d); - } - - } break; - - case ShaderLanguage::TYPE_MAT2: { - Transform2D tr = V->get(); - GLfloat matrix[4] = { - /* build a 16x16 matrix */ - tr.elements[0][0], - tr.elements[0][1], - tr.elements[1][0], - tr.elements[1][1], - }; - glUniformMatrix2fv(location, 1, GL_FALSE, matrix); - - } break; - - case ShaderLanguage::TYPE_MAT3: { - Basis val = V->get(); - - GLfloat mat[9] = { - val.elements[0][0], - val.elements[1][0], - val.elements[2][0], - val.elements[0][1], - val.elements[1][1], - val.elements[2][1], - val.elements[0][2], - val.elements[1][2], - val.elements[2][2], - }; - - glUniformMatrix3fv(location, 1, GL_FALSE, mat); - - } break; - - case ShaderLanguage::TYPE_MAT4: { - Transform2D tr = V->get(); - GLfloat matrix[16] = { /* build a 16x16 matrix */ - tr.elements[0][0], - tr.elements[0][1], - 0, - 0, - tr.elements[1][0], - tr.elements[1][1], - 0, - 0, - 0, - 0, - 1, - 0, - tr.elements[2][0], - tr.elements[2][1], - 0, - 1 - }; - - glUniformMatrix4fv(location, 1, GL_FALSE, matrix); - - } break; - - default: { - ERR_PRINT("ShaderNode type missing, bug?"); - } break; - } - } else if (E->get().default_value.size()) { - const Vector<ShaderLanguage::ConstantNode::Value> &values = E->get().default_value; - switch (E->get().type) { - case ShaderLanguage::TYPE_BOOL: { - glUniform1i(location, values[0].boolean); - } break; - - case ShaderLanguage::TYPE_BVEC2: { - glUniform2i(location, values[0].boolean, values[1].boolean); - } break; - - case ShaderLanguage::TYPE_BVEC3: { - glUniform3i(location, values[0].boolean, values[1].boolean, values[2].boolean); - } break; - - case ShaderLanguage::TYPE_BVEC4: { - glUniform4i(location, values[0].boolean, values[1].boolean, values[2].boolean, values[3].boolean); - } break; - - case ShaderLanguage::TYPE_INT: { - glUniform1i(location, values[0].sint); - } break; - - case ShaderLanguage::TYPE_IVEC2: { - glUniform2i(location, values[0].sint, values[1].sint); - } break; - - case ShaderLanguage::TYPE_IVEC3: { - glUniform3i(location, values[0].sint, values[1].sint, values[2].sint); - } break; - - case ShaderLanguage::TYPE_IVEC4: { - glUniform4i(location, values[0].sint, values[1].sint, values[2].sint, values[3].sint); - } break; - - case ShaderLanguage::TYPE_UINT: { - glUniform1i(location, values[0].uint); - } break; - - case ShaderLanguage::TYPE_UVEC2: { - glUniform2i(location, values[0].uint, values[1].uint); - } break; - - case ShaderLanguage::TYPE_UVEC3: { - glUniform3i(location, values[0].uint, values[1].uint, values[2].uint); - } break; - - case ShaderLanguage::TYPE_UVEC4: { - glUniform4i(location, values[0].uint, values[1].uint, values[2].uint, values[3].uint); - } break; - - case ShaderLanguage::TYPE_FLOAT: { - glUniform1f(location, values[0].real); - } break; - - case ShaderLanguage::TYPE_VEC2: { - glUniform2f(location, values[0].real, values[1].real); - } break; - - case ShaderLanguage::TYPE_VEC3: { - glUniform3f(location, values[0].real, values[1].real, values[2].real); - } break; - - case ShaderLanguage::TYPE_VEC4: { - glUniform4f(location, values[0].real, values[1].real, values[2].real, values[3].real); - } break; - - case ShaderLanguage::TYPE_MAT2: { - GLfloat mat[4]; - - for (int i = 0; i < 4; i++) { - mat[i] = values[i].real; - } - - glUniformMatrix2fv(location, 1, GL_FALSE, mat); - } break; - - case ShaderLanguage::TYPE_MAT3: { - GLfloat mat[9]; - - for (int i = 0; i < 9; i++) { - mat[i] = values[i].real; - } - - glUniformMatrix3fv(location, 1, GL_FALSE, mat); - - } break; - - case ShaderLanguage::TYPE_MAT4: { - GLfloat mat[16]; - - for (int i = 0; i < 16; i++) { - mat[i] = values[i].real; - } - - glUniformMatrix4fv(location, 1, GL_FALSE, mat); - - } break; - - case ShaderLanguage::TYPE_SAMPLER2D: { - } break; - - /* - case ShaderLanguage::TYPE_SAMPLEREXT: { - } break; -*/ - case ShaderLanguage::TYPE_ISAMPLER2D: { - } break; - - case ShaderLanguage::TYPE_USAMPLER2D: { - } break; - - case ShaderLanguage::TYPE_SAMPLERCUBE: { - } break; - - case ShaderLanguage::TYPE_SAMPLER2DARRAY: - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: - case ShaderLanguage::TYPE_SAMPLER3D: - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: { - // Not implemented in GLES2 - } break; - - case ShaderLanguage::TYPE_VOID: { - // Nothing to do? - } break; - default: { - ERR_PRINT("ShaderNode type missing, bug?"); - } break; - } - } else { //zero - - switch (E->get().type) { - case ShaderLanguage::TYPE_BOOL: { - glUniform1i(location, GL_FALSE); - } break; - - case ShaderLanguage::TYPE_BVEC2: { - glUniform2i(location, GL_FALSE, GL_FALSE); - } break; - - case ShaderLanguage::TYPE_BVEC3: { - glUniform3i(location, GL_FALSE, GL_FALSE, GL_FALSE); - } break; - - case ShaderLanguage::TYPE_BVEC4: { - glUniform4i(location, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - } break; - - case ShaderLanguage::TYPE_INT: { - glUniform1i(location, 0); - } break; - - case ShaderLanguage::TYPE_IVEC2: { - glUniform2i(location, 0, 0); - } break; - - case ShaderLanguage::TYPE_IVEC3: { - glUniform3i(location, 0, 0, 0); - } break; - - case ShaderLanguage::TYPE_IVEC4: { - glUniform4i(location, 0, 0, 0, 0); - } break; - - case ShaderLanguage::TYPE_UINT: { - glUniform1i(location, 0); - } break; - - case ShaderLanguage::TYPE_UVEC2: { - glUniform2i(location, 0, 0); - } break; - - case ShaderLanguage::TYPE_UVEC3: { - glUniform3i(location, 0, 0, 0); - } break; - - case ShaderLanguage::TYPE_UVEC4: { - glUniform4i(location, 0, 0, 0, 0); - } break; - - case ShaderLanguage::TYPE_FLOAT: { - glUniform1f(location, 0); - } break; - - case ShaderLanguage::TYPE_VEC2: { - glUniform2f(location, 0, 0); - } break; - - case ShaderLanguage::TYPE_VEC3: { - glUniform3f(location, 0, 0, 0); - } break; - - case ShaderLanguage::TYPE_VEC4: { - glUniform4f(location, 0, 0, 0, 0); - } break; - - case ShaderLanguage::TYPE_MAT2: { - GLfloat mat[4] = { 0, 0, 0, 0 }; - - glUniformMatrix2fv(location, 1, GL_FALSE, mat); - } break; - - case ShaderLanguage::TYPE_MAT3: { - GLfloat mat[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - glUniformMatrix3fv(location, 1, GL_FALSE, mat); - - } break; - - case ShaderLanguage::TYPE_MAT4: { - GLfloat mat[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - glUniformMatrix4fv(location, 1, GL_FALSE, mat); - - } break; - - case ShaderLanguage::TYPE_SAMPLER2D: { - } break; - - /* - case ShaderLanguage::TYPE_SAMPLEREXT: { - } break; -*/ - - case ShaderLanguage::TYPE_ISAMPLER2D: { - } break; - - case ShaderLanguage::TYPE_USAMPLER2D: { - } break; - - case ShaderLanguage::TYPE_SAMPLERCUBE: { - } break; - - case ShaderLanguage::TYPE_SAMPLER2DARRAY: - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: - case ShaderLanguage::TYPE_SAMPLER3D: - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: { - // Not implemented in GLES2 - } break; - - case ShaderLanguage::TYPE_VOID: { - // Nothing to do? - } break; - default: { - ERR_PRINT("ShaderNode type missing, bug?"); - } break; - } - } - } -} - -ShaderGLES2::ShaderGLES2() { - version = NULL; - last_custom_code = 1; - uniforms_dirty = true; -} - -ShaderGLES2::~ShaderGLES2() { - finish(); -} - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h deleted file mode 100644 index 4f327c2707..0000000000 --- a/drivers/gles2/shader_gles2.h +++ /dev/null @@ -1,283 +0,0 @@ -/*************************************************************************/ -/* shader_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -// This must come first to avoid windows.h mess -#include "platform_config.h" -#ifndef GLES2_INCLUDE_H -#include <GLES2/gl2.h> -#else -#include GLES2_INCLUDE_H -#endif - -#include "core/math/camera_matrix.h" -#ifdef GODOT_3 -#include "core/hash_map.h" -#include "core/map.h" -#include "core/pair.h" -#include "core/variant.h" -#include "servers/visual/shader_language.h" -#else -#include "core/templates/hash_map.h" -#include "core/templates/map.h" -#include "core/templates/pair.h" -#include "core/variant/variant.h" -#include "servers/rendering/shader_language.h" -#endif - -#include <stdio.h> - -class RasterizerStorageGLES2; -//#ifdef GODOT_3 - -class ShaderGLES2 { -protected: - struct Enum { - uint64_t mask; - uint64_t shift; - const char *defines[16]; - }; - - struct EnumValue { - uint64_t set_mask; - uint64_t clear_mask; - }; - - struct AttributePair { - const char *name; - int index; - }; - - struct UniformPair { - const char *name; - Variant::Type type_hint; - }; - - struct TexUnitPair { - const char *name; - int index; - }; - - bool uniforms_dirty; - -private: - bool valid = false; - - //@TODO Optimize to a fixed set of shader pools and use a LRU - int uniform_count; - int texunit_pair_count; - int conditional_count; - int vertex_code_start; - int fragment_code_start; - int attribute_pair_count; - - struct CustomCode { - String vertex; - String vertex_globals; - String fragment; - String fragment_globals; - String light; - uint32_t version; - Vector<StringName> texture_uniforms; - Vector<StringName> custom_uniforms; - Vector<CharString> custom_defines; - Set<uint32_t> versions; - }; - - struct Version { - GLuint id; - GLuint vert_id; - GLuint frag_id; - GLint *uniform_location; - Vector<GLint> texture_uniform_locations; - Map<StringName, GLint> custom_uniform_locations; - uint32_t code_version; - bool ok; - Version() { - id = 0; - vert_id = 0; - frag_id = 0; - uniform_location = NULL; - code_version = 0; - ok = false; - } - }; - - Version *version; - - union VersionKey { - struct { - uint32_t version; - uint32_t code_version; - }; - uint64_t key; - bool operator==(const VersionKey &p_key) const { return key == p_key.key; } - bool operator<(const VersionKey &p_key) const { return key < p_key.key; } - }; - - struct VersionKeyHash { - static _FORCE_INLINE_ uint32_t hash(const VersionKey &p_key) { return HashMapHasherDefault::hash(p_key.key); } - }; - - //this should use a way more cachefriendly version.. - HashMap<VersionKey, Version, VersionKeyHash> version_map; - - HashMap<uint32_t, CustomCode> custom_code_map; - uint32_t last_custom_code; - - VersionKey conditional_version; - VersionKey new_conditional_version; - - virtual String get_shader_name() const = 0; - - const char **conditional_defines; - const char **uniform_names; - const AttributePair *attribute_pairs; - const TexUnitPair *texunit_pairs; - const char *vertex_code; - const char *fragment_code; - CharString fragment_code0; - CharString fragment_code1; - CharString fragment_code2; - CharString fragment_code3; - - CharString vertex_code0; - CharString vertex_code1; - CharString vertex_code2; - - Vector<CharString> custom_defines; - - Version *get_current_version(); - - static ShaderGLES2 *active; - - int max_image_units; - - Map<StringName, Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value>>> uniform_values; - -protected: - _FORCE_INLINE_ int _get_uniform(int p_which) const; - _FORCE_INLINE_ void _set_conditional(int p_which, bool p_value); - - void setup(const char **p_conditional_defines, - int p_conditional_count, - const char **p_uniform_names, - int p_uniform_count, - const AttributePair *p_attribute_pairs, - int p_attribute_count, - const TexUnitPair *p_texunit_pairs, - int p_texunit_pair_count, - const char *p_vertex_code, - const char *p_fragment_code, - int p_vertex_code_start, - int p_fragment_code_start); - - ShaderGLES2(); - -public: - enum { - CUSTOM_SHADER_DISABLED = 0 - }; - - GLint get_uniform_location(const String &p_name) const; - GLint get_uniform_location(int p_index) const; - - static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; } - bool bind(); - void unbind(); - - inline GLuint get_program() const { return version ? version->id : 0; } - - void clear_caches(); - - uint32_t create_custom_shader(); - void set_custom_shader_code(uint32_t p_code_id, - const String &p_vertex, - const String &p_vertex_globals, - const String &p_fragment, - const String &p_light, - const String &p_fragment_globals, - const Vector<StringName> &p_uniforms, - const Vector<StringName> &p_texture_uniforms, - const Vector<CharString> &p_custom_defines); - - void set_custom_shader(uint32_t p_code_id); - void free_custom_shader(uint32_t p_code_id); - - uint32_t get_version_key() const { return conditional_version.version; } - - // this void* is actually a RasterizerStorageGLES2::Material, but C++ doesn't - // like forward declared nested classes. - void use_material(void *p_material); - - _FORCE_INLINE_ uint32_t get_version() const { return new_conditional_version.version; } - _FORCE_INLINE_ bool is_version_valid() const { return version && version->ok; } - - virtual void init() = 0; - void finish(); - - void add_custom_define(const String &p_define) { - custom_defines.push_back(p_define.utf8()); - } - - void get_custom_defines(Vector<String> *p_defines) { - for (int i = 0; i < custom_defines.size(); i++) { - p_defines->push_back(custom_defines[i].get_data()); - } - } - - void remove_custom_define(const String &p_define) { - custom_defines.erase(p_define.utf8()); - } - - virtual ~ShaderGLES2(); -}; - -// called a lot, made inline - -int ShaderGLES2::_get_uniform(int p_which) const { - ERR_FAIL_INDEX_V(p_which, uniform_count, -1); - ERR_FAIL_COND_V(!version, -1); - return version->uniform_location[p_which]; -} - -void ShaderGLES2::_set_conditional(int p_which, bool p_value) { - ERR_FAIL_INDEX(p_which, conditional_count); - if (p_value) - new_conditional_version.version |= (1 << p_which); - else - new_conditional_version.version &= ~(1 << p_which); -} - -#endif // GLES2_BACKEND_ENABLED diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub deleted file mode 100644 index bcd6ea79fb..0000000000 --- a/drivers/gles2/shaders/SCsub +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -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("scene.glsl") - env.GLES2_GLSL("cubemap_filter.glsl") - env.GLES2_GLSL("cube_to_dp.glsl") - # env.GLES2_GLSL('blend_shape.glsl'); - # env.GLES2_GLSL('screen_space_reflection.glsl'); - env.GLES2_GLSL("effect_blur.glsl") - # env.GLES2_GLSL('subsurf_scattering.glsl'); - # env.GLES2_GLSL('ssao.glsl'); - # env.GLES2_GLSL('ssao_minify.glsl'); - # env.GLES2_GLSL('ssao_blur.glsl'); - # env.GLES2_GLSL('exposure.glsl'); - env.GLES2_GLSL("tonemap.glsl") - # env.GLES2_GLSL('particles.glsl'); - env.GLES2_GLSL("lens_distorted.glsl") diff --git a/drivers/gles2/shaders/blend_shape.glsl b/drivers/gles2/shaders/blend_shape.glsl deleted file mode 100644 index 247e98c7aa..0000000000 --- a/drivers/gles2/shaders/blend_shape.glsl +++ /dev/null @@ -1,192 +0,0 @@ -/* clang-format off */ -[vertex] - -/* -from VisualServer: - -ARRAY_VERTEX=0, -ARRAY_NORMAL=1, -ARRAY_TANGENT=2, -ARRAY_COLOR=3, -ARRAY_TEX_UV=4, -ARRAY_TEX_UV2=5, -ARRAY_BONES=6, -ARRAY_WEIGHTS=7, -ARRAY_INDEX=8, -*/ - -#ifdef USE_2D_VERTEX -#define VFORMAT vec2 -#else -#define VFORMAT vec3 -#endif - -/* INPUT ATTRIBS */ - -layout(location = 0) in highp VFORMAT vertex_attrib; -/* clang-format on */ -layout(location = 1) in vec3 normal_attrib; - -#ifdef ENABLE_TANGENT -layout(location = 2) in vec4 tangent_attrib; -#endif - -#ifdef ENABLE_COLOR -layout(location = 3) in vec4 color_attrib; -#endif - -#ifdef ENABLE_UV -layout(location = 4) in vec2 uv_attrib; -#endif - -#ifdef ENABLE_UV2 -layout(location = 5) in vec2 uv2_attrib; -#endif - -#ifdef ENABLE_SKELETON -layout(location = 6) in ivec4 bone_attrib; -layout(location = 7) in vec4 weight_attrib; -#endif - -/* BLEND ATTRIBS */ - -#ifdef ENABLE_BLEND - -layout(location = 8) in highp VFORMAT vertex_attrib_blend; -layout(location = 9) in vec3 normal_attrib_blend; - -#ifdef ENABLE_TANGENT -layout(location = 10) in vec4 tangent_attrib_blend; -#endif - -#ifdef ENABLE_COLOR -layout(location = 11) in vec4 color_attrib_blend; -#endif - -#ifdef ENABLE_UV -layout(location = 12) in vec2 uv_attrib_blend; -#endif - -#ifdef ENABLE_UV2 -layout(location = 13) in vec2 uv2_attrib_blend; -#endif - -#ifdef ENABLE_SKELETON -layout(location = 14) in ivec4 bone_attrib_blend; -layout(location = 15) in vec4 weight_attrib_blend; -#endif - -#endif - -/* OUTPUTS */ - -out VFORMAT vertex_out; //tfb: - -#ifdef ENABLE_NORMAL -out vec3 normal_out; //tfb:ENABLE_NORMAL -#endif - -#ifdef ENABLE_TANGENT -out vec4 tangent_out; //tfb:ENABLE_TANGENT -#endif - -#ifdef ENABLE_COLOR -out vec4 color_out; //tfb:ENABLE_COLOR -#endif - -#ifdef ENABLE_UV -out vec2 uv_out; //tfb:ENABLE_UV -#endif - -#ifdef ENABLE_UV2 -out vec2 uv2_out; //tfb:ENABLE_UV2 -#endif - -#ifdef ENABLE_SKELETON -out ivec4 bone_out; //tfb:ENABLE_SKELETON -out vec4 weight_out; //tfb:ENABLE_SKELETON -#endif - -uniform float blend_amount; - -void main() { -#ifdef ENABLE_BLEND - - vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount; - -#ifdef ENABLE_NORMAL - normal_out = normal_attrib_blend + normal_attrib * blend_amount; -#endif - -#ifdef ENABLE_TANGENT - - tangent_out.xyz = tangent_attrib_blend.xyz + tangent_attrib.xyz * blend_amount; - tangent_out.w = tangent_attrib_blend.w; //just copy, no point in blending his -#endif - -#ifdef ENABLE_COLOR - - color_out = color_attrib_blend + color_attrib * blend_amount; -#endif - -#ifdef ENABLE_UV - - uv_out = uv_attrib_blend + uv_attrib * blend_amount; -#endif - -#ifdef ENABLE_UV2 - - uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount; -#endif - -#ifdef ENABLE_SKELETON - - bone_out = bone_attrib_blend; - weight_out = weight_attrib_blend + weight_attrib * blend_amount; -#endif - -#else //ENABLE_BLEND - - vertex_out = vertex_attrib * blend_amount; - -#ifdef ENABLE_NORMAL - normal_out = normal_attrib * blend_amount; -#endif - -#ifdef ENABLE_TANGENT - - tangent_out.xyz = tangent_attrib.xyz * blend_amount; - tangent_out.w = tangent_attrib.w; //just copy, no point in blending his -#endif - -#ifdef ENABLE_COLOR - - color_out = color_attrib * blend_amount; -#endif - -#ifdef ENABLE_UV - - uv_out = uv_attrib * blend_amount; -#endif - -#ifdef ENABLE_UV2 - - uv2_out = uv2_attrib * blend_amount; -#endif - -#ifdef ENABLE_SKELETON - - bone_out = bone_attrib; - weight_out = weight_attrib * blend_amount; -#endif - -#endif - gl_Position = vec4(0.0); -} - -/* clang-format off */ -[fragment] - -void main() { -} -/* clang-format on */ diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl deleted file mode 100644 index 3dee2faa88..0000000000 --- a/drivers/gles2/shaders/canvas.glsl +++ /dev/null @@ -1,686 +0,0 @@ -/* clang-format off */ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif - -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 - -#ifdef USE_ATTRIB_LIGHT_ANGLE -// shared with tangent, not used in canvas shader -attribute highp float light_angle; // attrib:2 -#endif - -attribute vec4 color_attrib; // attrib:3 -attribute vec2 uv_attrib; // attrib:4 - -#ifdef USE_ATTRIB_MODULATE -attribute highp vec4 modulate_attrib; // attrib:5 -#endif - -#ifdef USE_ATTRIB_LARGE_VERTEX -// shared with skeleton attributes, not used in batched shader -attribute highp vec2 translate_attrib; // attrib:6 -attribute highp vec4 basis_attrib; // attrib:7 -#endif - -#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; - -#ifdef USE_ATTRIB_MODULATE -// modulate doesn't need interpolating but we need to send it to the fragment shader -varying vec4 modulate_interp; -#endif - -#ifdef MODULATE_USED -uniform vec4 final_modulate; -#endif - -uniform highp vec2 color_texpixel_size; - -#ifdef USE_TEXTURE_RECT - -uniform vec4 dst_rect; -uniform vec4 src_rect; - -#endif - -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 - -/* clang-format on */ - -vec2 select(vec2 a, vec2 b, bvec2 c) { - vec2 ret; - - ret.x = c.x ? b.x : a.x; - ret.y = c.y ? b.y : a.y; - - return ret; -} - -void main() { - vec4 color = color_attrib; - vec2 uv; - -#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; - -#ifdef USE_INSTANCE_CUSTOM - vec4 instance_custom = instance_custom_data; -#else - vec4 instance_custom = vec4(0.0); -#endif - -#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 - uv = src_rect.xy + abs(src_rect.zw) * vertex.yx; - } else { - uv = src_rect.xy + abs(src_rect.zw) * vertex; - } - - vec4 outvec = vec4(0.0, 0.0, 0.0, 1.0); - - // This is what is done in the GLES 3 bindings and should - // take care of flipped rects. - // - // But it doesn't. - // I don't know why, will need to investigate further. - - outvec.xy = dst_rect.xy + abs(dst_rect.zw) * select(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0))); - - // outvec.xy = dst_rect.xy + abs(dst_rect.zw) * vertex; -#else - vec4 outvec = vec4(vertex.xy, 0.0, 1.0); - - uv = uv_attrib; -#endif - - float point_size = 1.0; - - { - vec2 src_vtx = outvec.xy; - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ - } - - gl_PointSize = point_size; - -#ifdef USE_ATTRIB_MODULATE - // modulate doesn't need interpolating but we need to send it to the fragment shader - modulate_interp = modulate_attrib; -#endif - -#ifdef USE_ATTRIB_LARGE_VERTEX - // transform is in attributes - vec2 temp; - - temp = outvec.xy; - temp.x = (outvec.x * basis_attrib.x) + (outvec.y * basis_attrib.z); - temp.y = (outvec.x * basis_attrib.y) + (outvec.y * basis_attrib.w); - - temp += translate_attrib; - outvec.xy = temp; - -#else - - // transform is in uniforms -#if !defined(SKIP_TRANSFORM_USED) - outvec = extra_matrix_instance * outvec; - outvec = modelview_matrix * outvec; -#endif - -#endif // not large integer - - color_interp = color; - -#ifdef USE_PIXEL_SNAP - outvec.xy = floor(outvec + 0.5).xy; - // precision issue on some hardware creates artifacts within texture - // offset uv by a small amount to avoid - uv += 1e-5; -#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 - - uv_interp = uv; - 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 - -#ifdef USE_ATTRIB_LIGHT_ANGLE - // we add a fixed offset because we are using the sign later, - // and don't want floating point error around 0.0 - float la = abs(light_angle) - 1.0; - - // vector light angle - vec4 vla; - vla.xy = vec2(cos(la), sin(la)); - vla.zw = vec2(-vla.y, vla.x); - - // vertical flip encoded in the sign - vla.zw *= sign(light_angle); - - // apply the transform matrix. - // The rotate will be encoded in the transform matrix for single rects, - // and just the flips in the light angle. - // For batching we will encode the rotation and the flips - // in the light angle, and can use the same shader. - local_rot.xy = normalize((modelview_matrix * (extra_matrix_instance * vec4(vla.xy, 0.0, 0.0))).xy); - local_rot.zw = normalize((modelview_matrix * (extra_matrix_instance * vec4(vla.zw, 0.0, 0.0))).xy); -#else - 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 // not using light angle - -#endif -} - -/* clang-format off */ -[fragment] - -// texture2DLodEXT and textureCubeLodEXT are fragment shader specific. -// Do not copy these defines in the vertex section. -#ifndef USE_GLES_OVER_GL -#ifdef GL_EXT_shader_texture_lod -#extension GL_EXT_shader_texture_lod : enable -#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) -#endif -#endif // !USE_GLES_OVER_GL - -#ifdef GL_ARB_shader_texture_lod -#extension GL_ARB_shader_texture_lod : enable -#endif - -#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) -#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) -#endif - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -#include "stdlib.glsl" - -uniform sampler2D color_texture; // texunit:-1 -/* clang-format on */ -uniform highp vec2 color_texpixel_size; -uniform mediump sampler2D normal_texture; // texunit:-2 - -varying mediump vec2 uv_interp; -varying mediump vec4 color_interp; - -#ifdef USE_ATTRIB_MODULATE -varying mediump vec4 modulate_interp; -#endif - -uniform highp float time; - -uniform vec4 final_modulate; - -#ifdef SCREEN_TEXTURE_USED - -uniform sampler2D screen_texture; // texunit:-4 - -#endif - -#ifdef SCREEN_UV_USED - -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:-6 -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 - -/* clang-format on */ - -void light_compute( - inout vec4 light, - inout vec2 light_vec, - inout float light_height, - inout vec4 light_color, - vec2 light_uv, - inout vec4 shadow_color, - inout vec2 shadow_vec, - vec3 normal, - vec2 uv, -#if defined(SCREEN_UV_USED) - vec2 screen_uv, -#endif - vec4 color) { - -#if defined(USE_LIGHT_SHADER_CODE) - - /* clang-format off */ - -LIGHT_SHADER_CODE - - /* clang-format on */ - -#endif -} - -void main() { - vec4 color = color_interp; - vec2 uv = uv_interp; -#ifdef USE_FORCE_REPEAT - //needs to use this to workaround GLES2/WebGL1 forcing tiling that textures that don't support it - uv = mod(uv, vec2(1.0, 1.0)); -#endif - -#if !defined(COLOR_USED) - //default behavior, texture by color - color *= texture2D(color_texture, uv); -#endif - -#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).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 - } - -#ifdef USE_ATTRIB_MODULATE - color *= modulate_interp; -#else -#if !defined(MODULATE_USED) - color *= final_modulate; -#endif -#endif - -#ifdef USE_LIGHTING - - vec2 light_vec = transformed_light_uv; - vec2 shadow_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, - shadow_vec, - 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 - -#ifdef SHADOW_VEC_USED - mat3 inverse_light_matrix = mat3(light_matrix); - inverse_light_matrix[0] = normalize(inverse_light_matrix[0]); - inverse_light_matrix[1] = normalize(inverse_light_matrix[1]); - inverse_light_matrix[2] = normalize(inverse_light_matrix[2]); - shadow_vec = (inverse_light_matrix * vec3(shadow_vec, 0.0)).xy; -#else - shadow_vec = light_uv_interp.zw; -#endif - - float angle_to_light = -atan(shadow_vec.x, shadow_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 = shadow_vec; - sh = 0.0 + (1.0 / 8.0); - } else if (abs_angle > 135.0 * PI / 180.0) { - point = -shadow_vec; - sh = 0.5 + (1.0 / 8.0); - } else if (angle_to_light > 0.0) { - point = vec2(shadow_vec.y, -shadow_vec.x); - sh = 0.25 + (1.0 / 8.0); - } else { - point = vec2(-shadow_vec.y, shadow_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 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) - -#else - -#define SHADOW_DEPTH(m_tex, m_uv) (texture2D((m_tex), (m_uv)).r) - -#endif - -#ifdef SHADOW_USE_GRADIENT - - /* clang-format off */ - /* GLSL es 100 doesn't support line continuation characters(backslashes) */ -#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); } - /* clang-format on */ - -#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 deleted file mode 100644 index 2abcd5e67c..0000000000 --- a/drivers/gles2/shaders/canvas_shadow.glsl +++ /dev/null @@ -1,60 +0,0 @@ -/* 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; - -varying highp vec4 position_interp; - -void main() { - gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex, 1.0))); - position_interp = gl_Position; -} - -/* clang-format off */ -[fragment] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#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 - -#ifdef USE_RGBA_SHADOWS - - highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0)); - comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0); - gl_FragColor = comp; -#else - - gl_FragColor = vec4(depth); -#endif -} diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl deleted file mode 100644 index e833722ac3..0000000000 --- a/drivers/gles2/shaders/copy.glsl +++ /dev/null @@ -1,191 +0,0 @@ -/* 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 vec4 vertex_attrib; // attrib:0 -/* clang-format on */ - -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -attribute vec3 cube_in; // attrib:4 -#else -attribute vec2 uv_in; // attrib:4 -#endif - -attribute vec2 uv2_in; // attrib:5 - -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -varying vec3 cube_interp; -#else -varying vec2 uv_interp; -#endif -varying vec2 uv2_interp; - -// These definitions are here because the shader-wrapper builder does -// not understand `#elif defined()` -#ifdef USE_DISPLAY_TRANSFORM -#endif - -#ifdef USE_COPY_SECTION -uniform highp vec4 copy_section; -#elif defined(USE_DISPLAY_TRANSFORM) -uniform highp mat4 display_transform; -#endif - -void main() { -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) - cube_interp = cube_in; -#elif defined(USE_ASYM_PANO) - uv_interp = vertex_attrib.xy; -#else - uv_interp = uv_in; -#endif - - uv2_interp = uv2_in; - gl_Position = vertex_attrib; - -#ifdef USE_COPY_SECTION - uv_interp = copy_section.xy + uv_interp * copy_section.zw; - gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; -#elif defined(USE_DISPLAY_TRANSFORM) - uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy; -#endif -} - -/* clang-format off */ -[fragment] - -#define M_PI 3.14159265359 - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -varying vec3 cube_interp; -#else -varying vec2 uv_interp; -#endif -/* clang-format on */ - -#ifdef USE_ASYM_PANO -uniform highp mat4 pano_transform; -uniform highp vec4 asym_proj; -#endif - -#ifdef USE_CUBEMAP -uniform samplerCube source_cube; // texunit:0 -#else -uniform sampler2D source; // texunit:0 -#endif - -#ifdef SEP_CBCR_TEXTURE -uniform sampler2D CbCr; //texunit:1 -#endif - -varying vec2 uv2_interp; - -#ifdef USE_MULTIPLIER -uniform float multiplier; -#endif - -#ifdef USE_CUSTOM_ALPHA -uniform float custom_alpha; -#endif - -#if defined(USE_PANORAMA) || defined(USE_ASYM_PANO) -uniform highp mat4 sky_transform; - -vec4 texturePanorama(sampler2D pano, vec3 normal) { - vec2 st = vec2( - atan(normal.x, normal.z), - acos(normal.y)); - - if (st.x < 0.0) - st.x += M_PI * 2.0; - - st /= vec2(M_PI * 2.0, M_PI); - - return texture2D(pano, st); -} - -#endif - -void main() { -#ifdef USE_PANORAMA - - vec3 cube_normal = normalize(cube_interp); - cube_normal.z = -cube_normal.z; - cube_normal = mat3(sky_transform) * cube_normal; - cube_normal.z = -cube_normal.z; - - vec4 color = texturePanorama(source, cube_normal); - -#elif defined(USE_ASYM_PANO) - - // When an asymmetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result. - // Asymmetrical projection means the center of projection is no longer in the center of the screen but shifted. - // The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image. - - vec3 cube_normal; - cube_normal.z = -1.0; - cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y; - cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a; - cube_normal = mat3(sky_transform) * mat3(pano_transform) * cube_normal; - cube_normal.z = -cube_normal.z; - - vec4 color = texturePanorama(source, normalize(cube_normal.xyz)); - -#elif defined(USE_CUBEMAP) - vec4 color = textureCube(source_cube, normalize(cube_interp)); -#elif defined(SEP_CBCR_TEXTURE) - vec4 color; - color.r = texture2D(source, uv_interp).r; - color.gb = texture2D(CbCr, uv_interp).rg - vec2(0.5, 0.5); - color.a = 1.0; -#else - vec4 color = texture2D(source, uv_interp); -#endif - -#ifdef YCBCR_TO_RGB - // YCbCr -> RGB conversion - - // Using BT.601, which is the standard for SDTV is provided as a reference - color.rgb = mat3( - vec3(1.00000, 1.00000, 1.00000), - vec3(0.00000, -0.34413, 1.77200), - vec3(1.40200, -0.71414, 0.00000)) * - color.rgb; -#endif - -#ifdef USE_NO_ALPHA - color.a = 1.0; -#endif - -#ifdef USE_CUSTOM_ALPHA - color.a = custom_alpha; -#endif - -#ifdef USE_MULTIPLIER - color.rgb *= multiplier; -#endif - - gl_FragColor = color; -} diff --git a/drivers/gles2/shaders/cube_to_dp.glsl b/drivers/gles2/shaders/cube_to_dp.glsl deleted file mode 100644 index 1612ec3d5a..0000000000 --- a/drivers/gles2/shaders/cube_to_dp.glsl +++ /dev/null @@ -1,100 +0,0 @@ -/* clang-format off */ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - -attribute highp vec4 vertex_attrib; // attrib:0 -/* clang-format on */ -attribute vec2 uv_in; // attrib:4 - -varying vec2 uv_interp; - -void main() { - uv_interp = uv_in; - gl_Position = vertex_attrib; -} - -/* clang-format off */ -[fragment] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -uniform highp samplerCube source_cube; //texunit:0 -/* clang-format on */ -varying vec2 uv_interp; - -uniform bool z_flip; -uniform highp float z_far; -uniform highp float z_near; -uniform highp float bias; - -void main() { - highp vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0); - /* - if (z_flip) { - normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); - } else { - normal.z = -0.5 + 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); - } - */ - - //normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); - //normal.xy *= 1.0 + normal.z; - - normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); - normal = normalize(normal); - /* - normal.z = 0.5; - normal = normalize(normal); - */ - - if (!z_flip) { - normal.z = -normal.z; - } - - //normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 )); - float depth = textureCube(source_cube, normal).r; - - // absolute values for direction cosines, bigger value equals closer to basis axis - vec3 unorm = abs(normal); - - if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { - // x code - unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); - } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { - // y code - unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); - } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { - // z code - unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); - } else { - // oh-no we messed up code - // has to be - unorm = vec3(1.0, 0.0, 0.0); - } - - float depth_fix = 1.0 / dot(normal, unorm); - - depth = 2.0 * depth - 1.0; - float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near)); - gl_FragDepth = (linear_depth * depth_fix + bias) / z_far; -} diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl deleted file mode 100644 index f5c91cc707..0000000000 --- a/drivers/gles2/shaders/cubemap_filter.glsl +++ /dev/null @@ -1,231 +0,0 @@ -/* 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 vec2 vertex; // attrib:0 -/* clang-format on */ -attribute highp vec2 uv; // attrib:4 - -varying highp vec2 uv_interp; - -void main() { - uv_interp = uv; - gl_Position = vec4(vertex, 0, 1); -} - -/* clang-format off */ -[fragment] - -// texture2DLodEXT and textureCubeLodEXT are fragment shader specific. -// Do not copy these defines in the vertex section. -#ifndef USE_GLES_OVER_GL -#ifdef GL_EXT_shader_texture_lod -#extension GL_EXT_shader_texture_lod : enable -#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) -#endif -#endif // !USE_GLES_OVER_GL - -#ifdef GL_ARB_shader_texture_lod -#extension GL_ARB_shader_texture_lod : enable -#endif - -#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) -#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) -#endif - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif - -#endif - -#ifdef USE_SOURCE_PANORAMA -uniform sampler2D source_panorama; //texunit:0 -#else -uniform samplerCube source_cube; //texunit:0 -#endif -/* clang-format on */ - -uniform int face_id; -uniform float roughness; -varying highp vec2 uv_interp; - -uniform sampler2D radical_inverse_vdc_cache; // texunit:1 - -#define M_PI 3.14159265359 - -#ifdef LOW_QUALITY - -#define SAMPLE_COUNT 64 - -#else - -#define SAMPLE_COUNT 512 - -#endif - -#ifdef USE_SOURCE_PANORAMA - -vec4 texturePanorama(sampler2D pano, vec3 normal) { - vec2 st = vec2( - atan(normal.x, normal.z), - acos(normal.y)); - - if (st.x < 0.0) - st.x += M_PI * 2.0; - - st /= vec2(M_PI * 2.0, M_PI); - - return texture2DLod(pano, st, 0.0); -} - -#endif - -vec3 texelCoordToVec(vec2 uv, int faceID) { - mat3 faceUvVectors[6]; - - // -x - faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z - faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face - - // +x - faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z - faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face - - // -y - faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z - faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face - - // +y - faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z - faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face - - // -z - faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x - faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face - - // +z - faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face - - // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. - vec3 result; - for (int i = 0; i < 6; i++) { - if (i == faceID) { - result = (faceUvVectors[i][0] * uv.x) + (faceUvVectors[i][1] * uv.y) + faceUvVectors[i][2]; - break; - } - } - return normalize(result); -} - -vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { - float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] - - // Compute distribution direction - float Phi = 2.0 * M_PI * Xi.x; - float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); - float SinTheta = sqrt(1.0 - CosTheta * CosTheta); - - // Convert to spherical direction - vec3 H; - H.x = SinTheta * cos(Phi); - H.y = SinTheta * sin(Phi); - H.z = CosTheta; - - vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 TangentX = normalize(cross(UpVector, N)); - vec3 TangentY = cross(N, TangentX); - - // Tangent to world space - return TangentX * H.x + TangentY * H.y + N * H.z; -} - -float radical_inverse_VdC(int i) { - return texture2D(radical_inverse_vdc_cache, vec2(float(i) / 512.0, 0.0)).x; -} - -vec2 Hammersley(int i, int N) { - return vec2(float(i) / float(N), radical_inverse_VdC(i)); -} - -uniform bool z_flip; - -void main() { - vec3 color = vec3(0.0); - - vec2 uv = (uv_interp * 2.0) - 1.0; - vec3 N = texelCoordToVec(uv, face_id); - -#ifdef USE_DIRECT_WRITE - -#ifdef USE_SOURCE_PANORAMA - - gl_FragColor = vec4(texturePanorama(source_panorama, N).rgb, 1.0); -#else - - gl_FragColor = vec4(textureCube(source_cube, N).rgb, 1.0); -#endif //USE_SOURCE_PANORAMA - -#else - - vec4 sum = vec4(0.0); - - for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) { - vec2 xi = Hammersley(sample_num, SAMPLE_COUNT); - - vec3 H = ImportanceSampleGGX(xi, roughness, N); - vec3 V = N; - vec3 L = (2.0 * dot(V, H) * H - V); - - float NdotL = clamp(dot(N, L), 0.0, 1.0); - - if (NdotL > 0.0) { - -#ifdef USE_SOURCE_PANORAMA - vec3 val = texturePanorama(source_panorama, L).rgb; -#else - vec3 val = textureCubeLod(source_cube, L, 0.0).rgb; -#endif - //mix using Linear, to approximate high end back-end - val = mix(pow((val + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), val * (1.0 / 12.92), vec3(lessThan(val, vec3(0.04045)))); - - sum.rgb += val * NdotL; - - sum.a += NdotL; - } - } - - sum /= sum.a; - - vec3 a = vec3(0.055); - sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308)))); - - gl_FragColor = vec4(sum.rgb, 1.0); -#endif -} diff --git a/drivers/gles2/shaders/effect_blur.glsl b/drivers/gles2/shaders/effect_blur.glsl deleted file mode 100644 index 7b607dd76a..0000000000 --- a/drivers/gles2/shaders/effect_blur.glsl +++ /dev/null @@ -1,308 +0,0 @@ -/* clang-format off */ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif - -attribute vec2 vertex_attrib; // attrib:0 -/* clang-format on */ -attribute vec2 uv_in; // attrib:4 - -varying vec2 uv_interp; - -#ifdef USE_BLUR_SECTION - -uniform vec4 blur_section; - -#endif - -void main() { - uv_interp = uv_in; - gl_Position = vec4(vertex_attrib, 0.0, 1.0); -#ifdef USE_BLUR_SECTION - - uv_interp = blur_section.xy + uv_interp * blur_section.zw; - gl_Position.xy = (blur_section.xy + (gl_Position.xy * 0.5 + 0.5) * blur_section.zw) * 2.0 - 1.0; -#endif -} - -/* clang-format off */ -[fragment] - -// texture2DLodEXT and textureCubeLodEXT are fragment shader specific. -// Do not copy these defines in the vertex section. -#ifndef USE_GLES_OVER_GL -#ifdef GL_EXT_shader_texture_lod -#extension GL_EXT_shader_texture_lod : enable -#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) -#endif -#endif // !USE_GLES_OVER_GL - -#ifdef GL_ARB_shader_texture_lod -#extension GL_ARB_shader_texture_lod : enable -#endif - -#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) -#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) -#endif - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -varying vec2 uv_interp; -/* clang-format on */ -uniform sampler2D source_color; //texunit:0 - -uniform float lod; -uniform vec2 pixel_size; - -#if defined(GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL) - -uniform float glow_strength; - -#endif - -#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR) - -#ifdef USE_GLES_OVER_GL -#ifdef DOF_QUALITY_LOW -const int dof_kernel_size = 5; -const int dof_kernel_from = 2; -const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388); -#endif - -#ifdef DOF_QUALITY_MEDIUM -const int dof_kernel_size = 11; -const int dof_kernel_from = 5; -const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037); - -#endif - -#ifdef DOF_QUALITY_HIGH -const int dof_kernel_size = 21; -const int dof_kernel_from = 10; -const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174); -#endif -#endif - -uniform sampler2D dof_source_depth; //texunit:1 -uniform float dof_begin; -uniform float dof_end; -uniform vec2 dof_dir; -uniform float dof_radius; - -#endif - -#ifdef GLOW_FIRST_PASS - -uniform highp float luminance_cap; - -uniform float glow_bloom; -uniform float glow_hdr_threshold; -uniform float glow_hdr_scale; - -#endif - -uniform float camera_z_far; -uniform float camera_z_near; - -void main() { -#ifdef GLOW_GAUSSIAN_HORIZONTAL - vec2 pix_size = pixel_size; - pix_size *= 0.5; //reading from larger buffer, so use more samples - vec4 color = texture2DLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.174938; - color += texture2DLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.165569; - color += texture2DLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.140367; - color += texture2DLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.106595; - color += texture2DLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.165569; - color += texture2DLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.140367; - color += texture2DLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.106595; - color *= glow_strength; - gl_FragColor = color; -#endif - -#ifdef GLOW_GAUSSIAN_VERTICAL - vec4 color = texture2DLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.288713; - color += texture2DLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.233062; - color += texture2DLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.122581; - color += texture2DLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062; - color += texture2DLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581; - color *= glow_strength; - gl_FragColor = color; -#endif - -#ifndef USE_GLES_OVER_GL -#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR) - -#ifdef DOF_QUALITY_LOW - const int dof_kernel_size = 5; - const int dof_kernel_from = 2; - float dof_kernel[5]; - dof_kernel[0] = 0.153388; - dof_kernel[1] = 0.221461; - dof_kernel[2] = 0.250301; - dof_kernel[3] = 0.221461; - dof_kernel[4] = 0.153388; -#endif - -#ifdef DOF_QUALITY_MEDIUM - const int dof_kernel_size = 11; - const int dof_kernel_from = 5; - float dof_kernel[11]; - dof_kernel[0] = 0.055037; - dof_kernel[1] = 0.072806; - dof_kernel[2] = 0.090506; - dof_kernel[3] = 0.105726; - dof_kernel[4] = 0.116061; - dof_kernel[5] = 0.119726; - dof_kernel[6] = 0.116061; - dof_kernel[7] = 0.105726; - dof_kernel[8] = 0.090506; - dof_kernel[9] = 0.072806; - dof_kernel[10] = 0.055037; -#endif - -#ifdef DOF_QUALITY_HIGH - const int dof_kernel_size = 21; - const int dof_kernel_from = 10; - float dof_kernel[21]; - dof_kernel[0] = 0.028174; - dof_kernel[1] = 0.032676; - dof_kernel[2] = 0.037311; - dof_kernel[3] = 0.041944; - dof_kernel[4] = 0.046421; - dof_kernel[5] = 0.050582; - dof_kernel[6] = 0.054261; - dof_kernel[7] = 0.057307; - dof_kernel[8] = 0.059587; - dof_kernel[9] = 0.060998; - dof_kernel[10] = 0.061476; - dof_kernel[11] = 0.060998; - dof_kernel[12] = 0.059587; - dof_kernel[13] = 0.057307; - dof_kernel[14] = 0.054261; - dof_kernel[15] = 0.050582; - dof_kernel[16] = 0.046421; - dof_kernel[17] = 0.041944; - dof_kernel[18] = 0.037311; - dof_kernel[19] = 0.032676; - dof_kernel[20] = 0.028174; -#endif -#endif -#endif //!USE_GLES_OVER_GL - -#ifdef DOF_FAR_BLUR - - vec4 color_accum = vec4(0.0); - - float depth = texture2DLod(dof_source_depth, uv_interp, 0.0).r; - depth = depth * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); -#endif - - float amount = smoothstep(dof_begin, dof_end, depth); - float k_accum = 0.0; - - for (int i = 0; i < dof_kernel_size; i++) { - int int_ofs = i - dof_kernel_from; - vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius; - - float tap_k = dof_kernel[i]; - - float tap_depth = texture2D(dof_source_depth, tap_uv, 0.0).r; - tap_depth = tap_depth * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near)); -#endif - float tap_amount = int_ofs == 0 ? 1.0 : smoothstep(dof_begin, dof_end, tap_depth); - tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect - - vec4 tap_color = texture2DLod(source_color, tap_uv, 0.0) * tap_k; - - k_accum += tap_k * tap_amount; - color_accum += tap_color * tap_amount; - } - - if (k_accum > 0.0) { - color_accum /= k_accum; - } - - gl_FragColor = color_accum; ///k_accum; - -#endif - -#ifdef DOF_NEAR_BLUR - - vec4 color_accum = vec4(0.0); - - float max_accum = 0.0; - - for (int i = 0; i < dof_kernel_size; i++) { - int int_ofs = i - dof_kernel_from; - vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius; - float ofs_influence = max(0.0, 1.0 - abs(float(int_ofs)) / float(dof_kernel_from)); - - float tap_k = dof_kernel[i]; - - vec4 tap_color = texture2DLod(source_color, tap_uv, 0.0); - - float tap_depth = texture2D(dof_source_depth, tap_uv, 0.0).r; - tap_depth = tap_depth * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near)); -#endif - float tap_amount = 1.0 - smoothstep(dof_end, dof_begin, tap_depth); - tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect - -#ifdef DOF_NEAR_FIRST_TAP - - tap_color.a = 1.0 - smoothstep(dof_end, dof_begin, tap_depth); - -#endif - - max_accum = max(max_accum, tap_amount * ofs_influence); - - color_accum += tap_color * tap_k; - } - - color_accum.a = max(color_accum.a, sqrt(max_accum)); - - gl_FragColor = color_accum; - -#endif - -#ifdef GLOW_FIRST_PASS - - float luminance = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b)); - float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom); - - gl_FragColor = min(gl_FragColor * feedback, vec4(luminance_cap)); - -#endif -} diff --git a/drivers/gles2/shaders/exposure.glsl b/drivers/gles2/shaders/exposure.glsl deleted file mode 100644 index c20812bfa3..0000000000 --- a/drivers/gles2/shaders/exposure.glsl +++ /dev/null @@ -1,86 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ - -void main() { - gl_Position = vertex_attrib; -} - -/* clang-format off */ -[fragment] - -uniform highp sampler2D source_exposure; //texunit:0 -/* clang-format on */ - -#ifdef EXPOSURE_BEGIN - -uniform highp ivec2 source_render_size; -uniform highp ivec2 target_size; - -#endif - -#ifdef EXPOSURE_END - -uniform highp sampler2D prev_exposure; //texunit:1 -uniform highp float exposure_adjust; -uniform highp float min_luminance; -uniform highp float max_luminance; - -#endif - -layout(location = 0) out highp float exposure; - -void main() { -#ifdef EXPOSURE_BEGIN - - ivec2 src_pos = ivec2(gl_FragCoord.xy) * source_render_size / target_size; - -#if 1 - //more precise and expensive, but less jittery - ivec2 next_pos = ivec2(gl_FragCoord.xy + ivec2(1)) * source_render_size / target_size; - next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel - highp vec3 source_color = vec3(0.0); - for (int i = src_pos.x; i < next_pos.x; i++) { - for (int j = src_pos.y; j < next_pos.y; j++) { - source_color += texelFetch(source_exposure, ivec2(i, j), 0).rgb; - } - } - - source_color /= float((next_pos.x - src_pos.x) * (next_pos.y - src_pos.y)); -#else - highp vec3 source_color = texelFetch(source_exposure, src_pos, 0).rgb; - -#endif - - exposure = max(source_color.r, max(source_color.g, source_color.b)); - -#else - - ivec2 coord = ivec2(gl_FragCoord.xy); - exposure = texelFetch(source_exposure, coord * 3 + ivec2(0, 0), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 0), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 0), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 1), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 1), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 1), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 2), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 2), 0).r; - exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 2), 0).r; - exposure *= (1.0 / 9.0); - -#ifdef EXPOSURE_END - -#ifdef EXPOSURE_FORCE_SET - //will stay as is -#else - highp float prev_lum = texelFetch(prev_exposure, ivec2(0, 0), 0).r; //1 pixel previous exposure - exposure = clamp(prev_lum + (exposure - prev_lum) * exposure_adjust, min_luminance, max_luminance); - -#endif //EXPOSURE_FORCE_SET - -#endif //EXPOSURE_END - -#endif //EXPOSURE_BEGIN -} diff --git a/drivers/gles2/shaders/lens_distorted.glsl b/drivers/gles2/shaders/lens_distorted.glsl deleted file mode 100644 index d568006ccc..0000000000 --- a/drivers/gles2/shaders/lens_distorted.glsl +++ /dev/null @@ -1,84 +0,0 @@ -/* 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 vec2 vertex; // attrib:0 -/* clang-format on */ - -uniform vec2 offset; -uniform vec2 scale; - -varying vec2 uv_interp; - -void main() { - uv_interp = vertex.xy * 2.0 - 1.0; - - vec2 v = vertex.xy * scale + offset; - gl_Position = vec4(v, 0.0, 1.0); -} - -/* clang-format off */ -[fragment] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -uniform sampler2D source; //texunit:0 -/* clang-format on */ - -uniform vec2 eye_center; -uniform float k1; -uniform float k2; -uniform float upscale; -uniform float aspect_ratio; - -varying vec2 uv_interp; - -void main() { - vec2 coords = uv_interp; - vec2 offset = coords - eye_center; - - // take aspect ratio into account - offset.y /= aspect_ratio; - - // distort - vec2 offset_sq = offset * offset; - float radius_sq = offset_sq.x + offset_sq.y; - float radius_s4 = radius_sq * radius_sq; - float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4); - offset *= distortion_scale; - - // reapply aspect ratio - offset.y *= aspect_ratio; - - // add our eye center back in - coords = offset + eye_center; - coords /= upscale; - - // and check our color - if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); - } else { - coords = (coords + vec2(1.0)) / vec2(2.0); - gl_FragColor = texture2D(source, coords); - } -} diff --git a/drivers/gles2/shaders/particles.glsl b/drivers/gles2/shaders/particles.glsl deleted file mode 100644 index b7fcb94ed2..0000000000 --- a/drivers/gles2/shaders/particles.glsl +++ /dev/null @@ -1,258 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 color; -/* clang-format on */ -layout(location = 1) in highp vec4 velocity_active; -layout(location = 2) in highp vec4 custom; -layout(location = 3) in highp vec4 xform_1; -layout(location = 4) in highp vec4 xform_2; -layout(location = 5) in highp vec4 xform_3; - -struct Attractor { - vec3 pos; - vec3 dir; - float radius; - float eat_radius; - float strength; - float attenuation; -}; - -#define MAX_ATTRACTORS 64 - -uniform bool emitting; -uniform float system_phase; -uniform float prev_system_phase; -uniform int total_particles; -uniform float explosiveness; -uniform float randomness; -uniform float time; -uniform float delta; - -uniform int attractor_count; -uniform Attractor attractors[MAX_ATTRACTORS]; -uniform bool clear; -uniform uint cycle; -uniform float lifetime; -uniform mat4 emission_transform; -uniform uint random_seed; - -out highp vec4 out_color; //tfb: -out highp vec4 out_velocity_active; //tfb: -out highp vec4 out_custom; //tfb: -out highp vec4 out_xform_1; //tfb: -out highp vec4 out_xform_2; //tfb: -out highp vec4 out_xform_3; //tfb: - -#if defined(USE_MATERIAL) - -/* clang-format off */ -layout(std140) uniform UniformData { //ubo:0 - -MATERIAL_UNIFORMS -}; -/* clang-format on */ - -#endif - -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ - -uint hash(uint x) { - x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); - x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); - x = (x >> uint(16)) ^ x; - return x; -} - -void main() { -#ifdef PARTICLES_COPY - - out_color = color; - out_velocity_active = velocity_active; - out_custom = custom; - out_xform_1 = xform_1; - out_xform_2 = xform_2; - out_xform_3 = xform_3; - -#else - - bool apply_forces = true; - bool apply_velocity = true; - float local_delta = delta; - - float mass = 1.0; - - float restart_phase = float(gl_VertexID) / float(total_particles); - - if (randomness > 0.0) { - uint seed = cycle; - if (restart_phase >= system_phase) { - seed -= uint(1); - } - seed *= uint(total_particles); - seed += uint(gl_VertexID); - float random = float(hash(seed) % uint(65536)) / 65536.0; - restart_phase += randomness * random * 1.0 / float(total_particles); - } - - restart_phase *= (1.0 - explosiveness); - bool restart = false; - bool shader_active = velocity_active.a > 0.5; - - if (system_phase > prev_system_phase) { - // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed - - if (restart_phase >= prev_system_phase && restart_phase < system_phase) { - restart = true; -#ifdef USE_FRACTIONAL_DELTA - local_delta = (system_phase - restart_phase) * lifetime; -#endif - } - - } else { - if (restart_phase >= prev_system_phase) { - restart = true; -#ifdef USE_FRACTIONAL_DELTA - local_delta = (1.0 - restart_phase + system_phase) * lifetime; -#endif - } else if (restart_phase < system_phase) { - restart = true; -#ifdef USE_FRACTIONAL_DELTA - local_delta = (system_phase - restart_phase) * lifetime; -#endif - } - } - - uint current_cycle = cycle; - - if (system_phase < restart_phase) { - current_cycle -= uint(1); - } - - uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID); - int index = int(gl_VertexID); - - if (restart) { - shader_active = emitting; - } - - mat4 xform; - -#if defined(ENABLE_KEEP_DATA) - if (clear) { -#else - if (clear || restart) { -#endif - out_color = vec4(1.0); - out_velocity_active = vec4(0.0); - out_custom = vec4(0.0); - if (!restart) - shader_active = false; - - xform = mat4( - vec4(1.0, 0.0, 0.0, 0.0), - vec4(0.0, 1.0, 0.0, 0.0), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(0.0, 0.0, 0.0, 1.0)); - } else { - out_color = color; - out_velocity_active = velocity_active; - out_custom = custom; - xform = transpose(mat4(xform_1, xform_2, xform_3, vec4(vec3(0.0), 1.0))); - } - - if (shader_active) { - //execute shader - - { - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ - } - -#if !defined(DISABLE_FORCE) - - if (false) { - vec3 force = vec3(0.0); - for (int i = 0; i < attractor_count; i++) { - vec3 rel_vec = xform[3].xyz - attractors[i].pos; - float dist = length(rel_vec); - if (attractors[i].radius < dist) - continue; - if (attractors[i].eat_radius > 0.0 && attractors[i].eat_radius > dist) { - out_velocity_active.a = 0.0; - } - - rel_vec = normalize(rel_vec); - - float attenuation = pow(dist / attractors[i].radius, attractors[i].attenuation); - - if (attractors[i].dir == vec3(0.0)) { - //towards center - force += attractors[i].strength * rel_vec * attenuation * mass; - } else { - force += attractors[i].strength * attractors[i].dir * attenuation * mass; - } - } - - out_velocity_active.xyz += force * local_delta; - } -#endif - -#if !defined(DISABLE_VELOCITY) - - if (true) { - xform[3].xyz += out_velocity_active.xyz * local_delta; - } -#endif - } else { - xform = mat4(0.0); - } - - xform = transpose(xform); - - out_velocity_active.a = mix(0.0, 1.0, shader_active); - - out_xform_1 = xform[0]; - out_xform_2 = xform[1]; - out_xform_3 = xform[2]; - -#endif //PARTICLES_COPY -} - -/* clang-format off */ -[fragment] - -//any code here is never executed, stuff is filled just so it works - -#if defined(USE_MATERIAL) - -layout(std140) uniform UniformData { - -MATERIAL_UNIFORMS -}; - -#endif - -FRAGMENT_SHADER_GLOBALS - -void main() { - { - -LIGHT_SHADER_CODE - - } - - { - -FRAGMENT_SHADER_CODE - - } -} -/* clang-format on */ diff --git a/drivers/gles2/shaders/resolve.glsl b/drivers/gles2/shaders/resolve.glsl deleted file mode 100644 index 071cb37a99..0000000000 --- a/drivers/gles2/shaders/resolve.glsl +++ /dev/null @@ -1,42 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ -layout(location = 4) in vec2 uv_in; - -out vec2 uv_interp; - -void main() { - uv_interp = uv_in; - gl_Position = vertex_attrib; -} - -/* clang-format off */ -[fragment] - -#if !defined(GLES_OVER_GL) -precision mediump float; -#endif - -in vec2 uv_interp; -/* clang-format on */ -uniform sampler2D source_specular; //texunit:0 -uniform sampler2D source_ssr; //texunit:1 - -uniform vec2 pixel_size; - -in vec2 uv2_interp; - -layout(location = 0) out vec4 frag_color; - -void main() { - vec4 specular = texture(source_specular, uv_interp); - -#ifdef USE_SSR - vec4 ssr = textureLod(source_ssr, uv_interp, 0.0); - specular.rgb = mix(specular.rgb, ssr.rgb * specular.a, ssr.a); -#endif - - frag_color = vec4(specular.rgb, 1.0); -} diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl deleted file mode 100644 index ba3a81a532..0000000000 --- a/drivers/gles2/shaders/scene.glsl +++ /dev/null @@ -1,2176 +0,0 @@ -/* clang-format off */ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif - -/* clang-format on */ -#include "stdlib.glsl" -/* clang-format off */ - -#define SHADER_IS_SRGB true - -#define M_PI 3.14159265359 - -// -// attributes -// - -attribute highp vec4 vertex_attrib; // attrib:0 -/* clang-format on */ -attribute vec3 normal_attrib; // attrib:1 - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -attribute vec4 tangent_attrib; // attrib:2 -#endif - -#if defined(ENABLE_COLOR_INTERP) -attribute vec4 color_attrib; // attrib:3 -#endif - -#if defined(ENABLE_UV_INTERP) -attribute vec2 uv_attrib; // attrib:4 -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -attribute vec2 uv2_attrib; // attrib:5 -#endif - -#ifdef USE_SKELETON - -#ifdef USE_SKELETON_SOFTWARE - -attribute highp vec4 bone_transform_row_0; // attrib:13 -attribute highp vec4 bone_transform_row_1; // attrib:14 -attribute highp vec4 bone_transform_row_2; // attrib:15 - -#else - -attribute vec4 bone_ids; // attrib:6 -attribute highp vec4 bone_weights; // attrib:7 - -uniform highp sampler2D bone_transforms; // texunit:-1 -uniform ivec2 skeleton_texture_size; - -#endif - -#endif - -#ifdef USE_INSTANCING - -attribute highp vec4 instance_xform_row_0; // attrib:8 -attribute highp vec4 instance_xform_row_1; // attrib:9 -attribute highp vec4 instance_xform_row_2; // attrib:10 - -attribute highp vec4 instance_color; // attrib:11 -attribute highp vec4 instance_custom_data; // attrib:12 - -#endif - -// -// uniforms -// - -uniform highp mat4 camera_matrix; -uniform highp mat4 camera_inverse_matrix; -uniform highp mat4 projection_matrix; -uniform highp mat4 projection_inverse_matrix; - -uniform highp mat4 world_transform; - -uniform highp float time; - -uniform highp vec2 viewport_size; - -#ifdef RENDER_DEPTH -uniform float light_bias; -uniform float light_normal_bias; -#endif - -// -// varyings -// - -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) -varying highp vec4 position_interp; -#endif - -varying highp vec3 vertex_interp; -varying vec3 normal_interp; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -varying vec3 tangent_interp; -varying vec3 binormal_interp; -#endif - -#if defined(ENABLE_COLOR_INTERP) -varying vec4 color_interp; -#endif - -#if defined(ENABLE_UV_INTERP) -varying vec2 uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -varying vec2 uv2_interp; -#endif - -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -varying highp float dp_clip; -uniform highp float shadow_dual_paraboloid_render_zfar; -uniform highp float shadow_dual_paraboloid_render_side; - -#endif - -#if defined(USE_SHADOW) && defined(USE_LIGHTING) - -uniform highp mat4 light_shadow_matrix; -varying highp vec4 shadow_coord; - -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) -uniform highp mat4 light_shadow_matrix2; -varying highp vec4 shadow_coord2; -#endif - -#if defined(LIGHT_USE_PSSM4) - -uniform highp mat4 light_shadow_matrix3; -uniform highp mat4 light_shadow_matrix4; -varying highp vec4 shadow_coord3; -varying highp vec4 shadow_coord4; - -#endif - -#endif - -#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) - -varying highp vec3 diffuse_interp; -varying highp vec3 specular_interp; - -// general for all lights -uniform highp vec4 light_color; -uniform highp vec4 shadow_color; -uniform highp float light_specular; - -// directional -uniform highp vec3 light_direction; - -// omni -uniform highp vec3 light_position; - -uniform highp float light_range; -uniform highp float light_attenuation; - -// spot -uniform highp float light_spot_attenuation; -uniform highp float light_spot_range; -uniform highp float light_spot_angle; - -void light_compute( - vec3 N, - vec3 L, - vec3 V, - vec3 light_color, - vec3 attenuation, - float roughness) { -//this makes lights behave closer to linear, but then addition of lights looks bad -//better left disabled - -//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); -/* -#define SRGB_APPROX(m_var) {\ - float S1 = sqrt(m_var);\ - float S2 = sqrt(S1);\ - float S3 = sqrt(S2);\ - m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ - } -*/ -#define SRGB_APPROX(m_var) - - float NdotL = dot(N, L); - float cNdotL = max(NdotL, 0.0); // clamped NdotL - float NdotV = dot(N, V); - float cNdotV = max(NdotV, 0.0); - -#if defined(DIFFUSE_OREN_NAYAR) - vec3 diffuse_brdf_NL; -#else - float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif - -#if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - -#elif defined(DIFFUSE_OREN_NAYAR) - - { - // see http://mimosa-pudica.net/improved-oren-nayar.html - float LdotV = dot(L, V); - - float s = LdotV - NdotL * NdotV; - float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); - - float sigma2 = roughness * roughness; // TODO: this needs checking - vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); - float B = 0.45 * sigma2 / (sigma2 + 0.09); - - diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); - } -#else - // lambert by default for everything else - diffuse_brdf_NL = cNdotL * (1.0 / M_PI); -#endif - - SRGB_APPROX(diffuse_brdf_NL) - - diffuse_interp += light_color * diffuse_brdf_NL * attenuation; - - if (roughness > 0.0) { - // D - float specular_brdf_NL = 0.0; - -#if !defined(SPECULAR_DISABLED) - //normalized blinn always unless disabled - vec3 H = normalize(V + L); - float cNdotH = max(dot(N, H), 0.0); - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess) * cNdotL; - blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = blinn; -#endif - - SRGB_APPROX(specular_brdf_NL) - specular_interp += specular_brdf_NL * light_color * attenuation * (1.0 / M_PI); - } -} - -#endif - -#ifdef USE_VERTEX_LIGHTING - -#ifdef USE_REFLECTION_PROBE1 - -uniform highp mat4 refprobe1_local_matrix; -varying mediump vec4 refprobe1_reflection_normal_blend; -uniform highp vec3 refprobe1_box_extents; - -#ifndef USE_LIGHTMAP -varying mediump vec3 refprobe1_ambient_normal; -#endif - -#endif //reflection probe1 - -#ifdef USE_REFLECTION_PROBE2 - -uniform highp mat4 refprobe2_local_matrix; -varying mediump vec4 refprobe2_reflection_normal_blend; -uniform highp vec3 refprobe2_box_extents; - -#ifndef USE_LIGHTMAP -varying mediump vec3 refprobe2_ambient_normal; -#endif - -#endif //reflection probe2 - -#endif //vertex lighting for refprobes - -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -varying vec4 fog_interp; - -uniform mediump vec4 fog_color_base; -#ifdef LIGHT_MODE_DIRECTIONAL -uniform mediump vec4 fog_sun_color_amount; -#endif - -uniform bool fog_transmit_enabled; -uniform mediump float fog_transmit_curve; - -#ifdef FOG_DEPTH_ENABLED -uniform highp float fog_depth_begin; -uniform mediump float fog_depth_curve; -uniform mediump float fog_max_distance; -#endif - -#ifdef FOG_HEIGHT_ENABLED -uniform highp float fog_height_min; -uniform highp float fog_height_max; -uniform mediump float fog_height_curve; -#endif - -#endif //fog - -void main() { - highp vec4 vertex = vertex_attrib; - - mat4 world_matrix = world_transform; - -#ifdef USE_INSTANCING - { - highp mat4 m = mat4( - instance_xform_row_0, - instance_xform_row_1, - instance_xform_row_2, - vec4(0.0, 0.0, 0.0, 1.0)); - world_matrix = world_matrix * transpose(m); - } - -#endif - - vec3 normal = normal_attrib; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - vec3 tangent = tangent_attrib.xyz; - float binormalf = tangent_attrib.a; - vec3 binormal = normalize(cross(normal, tangent) * binormalf); -#endif - -#if defined(ENABLE_COLOR_INTERP) - color_interp = color_attrib; -#ifdef USE_INSTANCING - color_interp *= instance_color; -#endif -#endif - -#if defined(ENABLE_UV_INTERP) - uv_interp = uv_attrib; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) - uv2_interp = uv2_attrib; -#endif - -#if defined(OVERRIDE_POSITION) - highp vec4 position; -#endif - -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = world_matrix * vertex; - normal = normalize((world_matrix * vec4(normal, 0.0)).xyz); -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - - tangent = normalize((world_matrix * vec4(tangent, 0.0)).xyz); - binormal = normalize((world_matrix * vec4(binormal, 0.0)).xyz); -#endif -#endif - -#ifdef USE_SKELETON - - highp mat4 bone_transform = mat4(0.0); - -#ifdef USE_SKELETON_SOFTWARE - // passing the transform as attributes - - bone_transform[0] = vec4(bone_transform_row_0.x, bone_transform_row_1.x, bone_transform_row_2.x, 0.0); - bone_transform[1] = vec4(bone_transform_row_0.y, bone_transform_row_1.y, bone_transform_row_2.y, 0.0); - bone_transform[2] = vec4(bone_transform_row_0.z, bone_transform_row_1.z, bone_transform_row_2.z, 0.0); - bone_transform[3] = vec4(bone_transform_row_0.w, bone_transform_row_1.w, bone_transform_row_2.w, 1.0); - -#else - // look up transform from the "pose texture" - { - for (int i = 0; i < 4; i++) { - ivec2 tex_ofs = ivec2(int(bone_ids[i]) * 3, 0); - - highp mat4 b = mat4( - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(0, 0)), - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(1, 0)), - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(2, 0)), - vec4(0.0, 0.0, 0.0, 1.0)); - - bone_transform += transpose(b) * bone_weights[i]; - } - } - -#endif - - world_matrix = world_matrix * bone_transform; - -#endif - -#ifdef USE_INSTANCING - vec4 instance_custom = instance_custom_data; -#else - vec4 instance_custom = vec4(0.0); - -#endif - - mat4 local_projection_matrix = projection_matrix; - - mat4 modelview = camera_inverse_matrix * world_matrix; - float roughness = 1.0; - -#define projection_matrix local_projection_matrix -#define world_transform world_matrix - - float point_size = 1.0; - - { - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ - } - - gl_PointSize = point_size; - vec4 outvec = vertex; - - // use local coordinates -#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) - vertex = modelview * vertex; - normal = normalize((modelview * vec4(normal, 0.0)).xyz); - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent = normalize((modelview * vec4(tangent, 0.0)).xyz); - binormal = normalize((modelview * vec4(binormal, 0.0)).xyz); -#endif -#endif - -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = camera_inverse_matrix * vertex; - normal = normalize((camera_inverse_matrix * vec4(normal, 0.0)).xyz); -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent = normalize((camera_inverse_matrix * vec4(tangent, 0.0)).xyz); - binormal = normalize((camera_inverse_matrix * vec4(binormal, 0.0)).xyz); -#endif -#endif - - vertex_interp = vertex.xyz; - normal_interp = normal; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent_interp = tangent; - binormal_interp = binormal; -#endif - -#ifdef RENDER_DEPTH - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - - vertex_interp.z *= shadow_dual_paraboloid_render_side; - normal_interp.z *= shadow_dual_paraboloid_render_side; - - dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias - - //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges - - highp vec3 vtx = vertex_interp + normalize(vertex_interp) * light_bias; - highp float distance = length(vtx); - vtx = normalize(vtx); - vtx.xy /= 1.0 - vtx.z; - vtx.z = (distance / shadow_dual_paraboloid_render_zfar); - vtx.z = vtx.z * 2.0 - 1.0; - - vertex_interp = vtx; - -#else - float z_ofs = light_bias; - z_ofs += (1.0 - abs(normal_interp.z)) * light_normal_bias; - - vertex_interp.z -= z_ofs; -#endif //dual parabolloid - -#endif //depth - -//vertex lighting -#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) - //vertex shaded version of lighting (more limited) - vec3 L; - vec3 light_att; - -#ifdef LIGHT_MODE_OMNI - vec3 light_vec = light_position - vertex_interp; - float light_length = length(light_vec); - - float normalized_distance = light_length / light_range; - - if (normalized_distance < 1.0) { - float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); - - vec3 attenuation = vec3(omni_attenuation); - light_att = vec3(omni_attenuation); - } else { - light_att = vec3(0.0); - } - - L = normalize(light_vec); - -#endif - -#ifdef LIGHT_MODE_SPOT - - vec3 light_rel_vec = light_position - vertex_interp; - float light_length = length(light_rel_vec); - float normalized_distance = light_length / light_range; - - if (normalized_distance < 1.0) { - float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); - vec3 spot_dir = light_direction; - - float spot_cutoff = light_spot_angle; - - float angle = dot(-normalize(light_rel_vec), spot_dir); - - if (angle > spot_cutoff) { - float scos = max(angle, spot_cutoff); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); - - spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); - - light_att = vec3(spot_attenuation); - } else { - light_att = vec3(0.0); - } - } else { - light_att = vec3(0.0); - } - - L = normalize(light_rel_vec); - -#endif - -#ifdef LIGHT_MODE_DIRECTIONAL - vec3 light_vec = -light_direction; - light_att = vec3(1.0); //no base attenuation - L = normalize(light_vec); -#endif - - diffuse_interp = vec3(0.0); - specular_interp = vec3(0.0); - light_compute(normal_interp, L, -normalize(vertex_interp), light_color.rgb, light_att, roughness); - -#endif - -//shadows (for both vertex and fragment) -#if defined(USE_SHADOW) && defined(USE_LIGHTING) - - vec4 vi4 = vec4(vertex_interp, 1.0); - shadow_coord = light_shadow_matrix * vi4; - -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) - shadow_coord2 = light_shadow_matrix2 * vi4; -#endif - -#if defined(LIGHT_USE_PSSM4) - shadow_coord3 = light_shadow_matrix3 * vi4; - shadow_coord4 = light_shadow_matrix4 * vi4; - -#endif - -#endif //use shadow and use lighting - -#ifdef USE_VERTEX_LIGHTING - -#ifdef USE_REFLECTION_PROBE1 - { - vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); - vec3 local_pos = (refprobe1_local_matrix * vec4(vertex_interp, 1.0)).xyz; - vec3 inner_pos = abs(local_pos / refprobe1_box_extents); - float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - - { - vec3 local_ref_vec = (refprobe1_local_matrix * vec4(ref_normal, 0.0)).xyz; - refprobe1_reflection_normal_blend.xyz = local_ref_vec; - refprobe1_reflection_normal_blend.a = blend; - } -#ifndef USE_LIGHTMAP - - refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz; -#endif - } - -#endif //USE_REFLECTION_PROBE1 - -#ifdef USE_REFLECTION_PROBE2 - { - vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); - vec3 local_pos = (refprobe2_local_matrix * vec4(vertex_interp, 1.0)).xyz; - vec3 inner_pos = abs(local_pos / refprobe2_box_extents); - float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - - { - vec3 local_ref_vec = (refprobe2_local_matrix * vec4(ref_normal, 0.0)).xyz; - refprobe2_reflection_normal_blend.xyz = local_ref_vec; - refprobe2_reflection_normal_blend.a = blend; - } -#ifndef USE_LIGHTMAP - - refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz; -#endif - } - -#endif //USE_REFLECTION_PROBE2 - -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - - float fog_amount = 0.0; - -#ifdef LIGHT_MODE_DIRECTIONAL - - vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(normalize(vertex_interp), light_direction), 0.0), 8.0)); -#else - vec3 fog_color = fog_color_base.rgb; -#endif - -#ifdef FOG_DEPTH_ENABLED - - { - float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); - - fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; - } -#endif - -#ifdef FOG_HEIGHT_ENABLED - { - float y = (camera_matrix * vec4(vertex_interp, 1.0)).y; - fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); - } -#endif - fog_interp = vec4(fog_color, fog_amount); - -#endif //fog - -#endif //use vertex lighting - -#if defined(OVERRIDE_POSITION) - gl_Position = position; -#else - gl_Position = projection_matrix * vec4(vertex_interp, 1.0); -#endif - -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) - position_interp = gl_Position; -#endif -} - -/* clang-format off */ -[fragment] - -// texture2DLodEXT and textureCubeLodEXT are fragment shader specific. -// Do not copy these defines in the vertex section. -#ifndef USE_GLES_OVER_GL -#ifdef GL_EXT_shader_texture_lod -#extension GL_EXT_shader_texture_lod : enable -#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) -#endif -#endif // !USE_GLES_OVER_GL - -#ifdef GL_ARB_shader_texture_lod -#extension GL_ARB_shader_texture_lod : enable -#endif - -#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) -#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) -#endif - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -#include "stdlib.glsl" - -#define M_PI 3.14159265359 -#define SHADER_IS_SRGB true - -// -// uniforms -// - -uniform highp mat4 camera_matrix; -/* clang-format on */ -uniform highp mat4 camera_inverse_matrix; -uniform highp mat4 projection_matrix; -uniform highp mat4 projection_inverse_matrix; - -uniform highp mat4 world_transform; - -uniform highp float time; - -uniform highp vec2 viewport_size; - -#if defined(SCREEN_UV_USED) -uniform vec2 screen_pixel_size; -#endif - -#if defined(SCREEN_TEXTURE_USED) -uniform highp sampler2D screen_texture; //texunit:-4 -#endif -#if defined(DEPTH_TEXTURE_USED) -uniform highp sampler2D depth_texture; //texunit:-4 -#endif - -#ifdef USE_REFLECTION_PROBE1 - -#ifdef USE_VERTEX_LIGHTING - -varying mediump vec4 refprobe1_reflection_normal_blend; -#ifndef USE_LIGHTMAP -varying mediump vec3 refprobe1_ambient_normal; -#endif - -#else - -uniform bool refprobe1_use_box_project; -uniform highp vec3 refprobe1_box_extents; -uniform vec3 refprobe1_box_offset; -uniform highp mat4 refprobe1_local_matrix; - -#endif //use vertex lighting - -uniform bool refprobe1_exterior; - -uniform highp samplerCube reflection_probe1; //texunit:-5 - -uniform float refprobe1_intensity; -uniform vec4 refprobe1_ambient; - -#endif //USE_REFLECTION_PROBE1 - -#ifdef USE_REFLECTION_PROBE2 - -#ifdef USE_VERTEX_LIGHTING - -varying mediump vec4 refprobe2_reflection_normal_blend; -#ifndef USE_LIGHTMAP -varying mediump vec3 refprobe2_ambient_normal; -#endif - -#else - -uniform bool refprobe2_use_box_project; -uniform highp vec3 refprobe2_box_extents; -uniform vec3 refprobe2_box_offset; -uniform highp mat4 refprobe2_local_matrix; - -#endif //use vertex lighting - -uniform bool refprobe2_exterior; - -uniform highp samplerCube reflection_probe2; //texunit:-6 - -uniform float refprobe2_intensity; -uniform vec4 refprobe2_ambient; - -#endif //USE_REFLECTION_PROBE2 - -#define RADIANCE_MAX_LOD 6.0 - -#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - -void reflection_process(samplerCube reflection_map, -#ifdef USE_VERTEX_LIGHTING - vec3 ref_normal, -#ifndef USE_LIGHTMAP - vec3 amb_normal, -#endif - float ref_blend, - -#else //no vertex lighting - vec3 normal, vec3 vertex, - mat4 local_matrix, - bool use_box_project, vec3 box_extents, vec3 box_offset, -#endif //vertex lighting - bool exterior, float intensity, vec4 ref_ambient, float roughness, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) { - vec4 reflection; - -#ifdef USE_VERTEX_LIGHTING - - reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; - - float blend = ref_blend; //crappier blend formula for vertex - blend *= blend; - blend = max(0.0, 1.0 - blend); - -#else //fragment lighting - - vec3 local_pos = (local_matrix * vec4(vertex, 1.0)).xyz; - - if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box - return; - } - - vec3 inner_pos = abs(local_pos / box_extents); - float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - blend = mix(length(inner_pos), blend, blend); - blend *= blend; - blend = max(0.0, 1.0 - blend); - - //reflect and make local - vec3 ref_normal = normalize(reflect(vertex, normal)); - ref_normal = (local_matrix * vec4(ref_normal, 0.0)).xyz; - - if (use_box_project) { //box project - - vec3 nrdir = normalize(ref_normal); - vec3 rbmax = (box_extents - local_pos) / nrdir; - vec3 rbmin = (-box_extents - local_pos) / nrdir; - - vec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0, 0.0, 0.0)))); - - float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); - vec3 posonbox = local_pos + nrdir * fa; - ref_normal = posonbox - box_offset.xyz; - } - - reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; -#endif - - if (exterior) { - reflection.rgb = mix(skybox, reflection.rgb, blend); - } - reflection.rgb *= intensity; - reflection.a = blend; - reflection.rgb *= blend; - - reflection_accum += reflection; - -#ifndef USE_LIGHTMAP - - vec4 ambient_out; -#ifndef USE_VERTEX_LIGHTING - - vec3 amb_normal = (local_matrix * vec4(normal, 0.0)).xyz; -#endif - - ambient_out.rgb = textureCubeLod(reflection_map, amb_normal, RADIANCE_MAX_LOD).rgb; - ambient_out.rgb = mix(ref_ambient.rgb, ambient_out.rgb, ref_ambient.a); - if (exterior) { - ambient_out.rgb = mix(ambient, ambient_out.rgb, blend); - } - - ambient_out.a = blend; - ambient_out.rgb *= blend; - ambient_accum += ambient_out; - -#endif -} - -#endif //use refprobe 1 or 2 - -#ifdef USE_LIGHTMAP -uniform mediump sampler2D lightmap; //texunit:-4 -uniform mediump float lightmap_energy; -#endif - -#ifdef USE_LIGHTMAP_CAPTURE -uniform mediump vec4[12] lightmap_captures; -uniform bool lightmap_capture_sky; - -#endif - -#ifdef USE_RADIANCE_MAP - -uniform samplerCube radiance_map; // texunit:-2 - -uniform mat4 radiance_inverse_xform; - -#endif - -uniform vec4 bg_color; -uniform float bg_energy; - -uniform float ambient_sky_contribution; -uniform vec4 ambient_color; -uniform float ambient_energy; - -#ifdef USE_LIGHTING - -uniform highp vec4 shadow_color; - -#ifdef USE_VERTEX_LIGHTING - -//get from vertex -varying highp vec3 diffuse_interp; -varying highp vec3 specular_interp; - -uniform highp vec3 light_direction; //may be used by fog, so leave here - -#else -//done in fragment -// general for all lights -uniform highp vec4 light_color; - -uniform highp float light_specular; - -// directional -uniform highp vec3 light_direction; -// omni -uniform highp vec3 light_position; - -uniform highp float light_attenuation; - -// spot -uniform highp float light_spot_attenuation; -uniform highp float light_spot_range; -uniform highp float light_spot_angle; -#endif - -//this is needed outside above if because dual paraboloid wants it -uniform highp float light_range; - -#ifdef USE_SHADOW - -uniform highp vec2 shadow_pixel_size; - -#if defined(LIGHT_MODE_OMNI) || defined(LIGHT_MODE_SPOT) -uniform highp sampler2D light_shadow_atlas; //texunit:-3 -#endif - -#ifdef LIGHT_MODE_DIRECTIONAL -uniform highp sampler2D light_directional_shadow; // texunit:-3 -uniform highp vec4 light_split_offsets; -#endif - -varying highp vec4 shadow_coord; - -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) -varying highp vec4 shadow_coord2; -#endif - -#if defined(LIGHT_USE_PSSM4) - -varying highp vec4 shadow_coord3; -varying highp vec4 shadow_coord4; - -#endif - -uniform vec4 light_clamp; - -#endif // light shadow - -// directional shadow - -#endif - -// -// varyings -// - -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) -varying highp vec4 position_interp; -#endif - -varying highp vec3 vertex_interp; -varying vec3 normal_interp; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -varying vec3 tangent_interp; -varying vec3 binormal_interp; -#endif - -#if defined(ENABLE_COLOR_INTERP) -varying vec4 color_interp; -#endif - -#if defined(ENABLE_UV_INTERP) -varying vec2 uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -varying vec2 uv2_interp; -#endif - -varying vec3 view_interp; - -vec3 F0(float metallic, float specular, vec3 albedo) { - float dielectric = 0.16 * specular * specular; - // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials; - // see https://google.github.io/filament/Filament.md.html - return mix(vec3(dielectric), albedo, vec3(metallic)); -} - -/* clang-format off */ - -FRAGMENT_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -varying highp float dp_clip; - -#endif - -#ifdef USE_LIGHTING - -// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. -// We're dividing this factor off because the overall term we'll end up looks like -// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): -// -// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) -// -// We're basically regouping this as -// -// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] -// -// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. -// -// The contents of the D and G (G1) functions (GGX) are taken from -// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). -// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). - -/* -float G_GGX_2cos(float cos_theta_m, float alpha) { - // Schlick's approximation - // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) - // Eq. (19), although see Heitz (2014) the about the problems with his derivation. - // It nevertheless approximates GGX well with k = alpha/2. - float k = 0.5 * alpha; - return 0.5 / (cos_theta_m * (1.0 - k) + k); - - // float cos2 = cos_theta_m * cos_theta_m; - // float sin2 = (1.0 - cos2); - // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2)); -} -*/ - -// This approximates G_GGX_2cos(cos_theta_l, alpha) * G_GGX_2cos(cos_theta_v, alpha) -// See Filament docs, Specular G section. -float V_GGX(float cos_theta_l, float cos_theta_v, float alpha) { - return 0.5 / mix(2.0 * cos_theta_l * cos_theta_v, cos_theta_l + cos_theta_v, alpha); -} - -float D_GGX(float cos_theta_m, float alpha) { - float alpha2 = alpha * alpha; - float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; - return alpha2 / (M_PI * d * d); -} - -/* -float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { - float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float s_x = alpha_x * cos_phi; - float s_y = alpha_y * sin_phi; - return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001); -} -*/ - -// This approximates G_GGX_anisotropic_2cos(cos_theta_l, ...) * G_GGX_anisotropic_2cos(cos_theta_v, ...) -// See Filament docs, Anisotropic specular BRDF section. -float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) { - float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV)); - float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL)); - return 0.5 / (Lambda_V + Lambda_L); -} - -float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi, float NdotH) { - float alpha2 = alpha_x * alpha_y; - highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * NdotH); - highp float v2 = dot(v, v); - float w2 = alpha2 / v2; - float D = alpha2 * w2 * w2 * (1.0 / M_PI); - return D; - - /* float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float r_x = cos_phi / alpha_x; - float r_y = sin_phi / alpha_y; - float d = cos2 + sin2 * (r_x * r_x + r_y * r_y); - return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001); */ -} - -float SchlickFresnel(float u) { - float m = 1.0 - u; - float m2 = m * m; - return m2 * m2 * m; // pow(m,5) -} - -float GTR1(float NdotH, float a) { - if (a >= 1.0) - return 1.0 / M_PI; - float a2 = a * a; - float t = 1.0 + (a2 - 1.0) * NdotH * NdotH; - return (a2 - 1.0) / (M_PI * log(a2) * t); -} - -void light_compute( - vec3 N, - vec3 L, - vec3 V, - vec3 B, - vec3 T, - vec3 light_color, - vec3 attenuation, - vec3 diffuse_color, - vec3 transmission, - float specular_blob_intensity, - float roughness, - float metallic, - float specular, - float rim, - float rim_tint, - float clearcoat, - float clearcoat_gloss, - float anisotropy, - inout vec3 diffuse_light, - inout vec3 specular_light, - inout float alpha) { -//this makes lights behave closer to linear, but then addition of lights looks bad -//better left disabled - -//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); -/* -#define SRGB_APPROX(m_var) {\ - float S1 = sqrt(m_var);\ - float S2 = sqrt(S1);\ - float S3 = sqrt(S2);\ - m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ - } -*/ -#define SRGB_APPROX(m_var) - -#if defined(USE_LIGHT_SHADER_CODE) - // light is written by the light shader - - vec3 normal = N; - vec3 albedo = diffuse_color; - vec3 light = L; - vec3 view = V; - - /* clang-format off */ - -LIGHT_SHADER_CODE - - /* clang-format on */ - -#else - float NdotL = dot(N, L); - float cNdotL = max(NdotL, 0.0); // clamped NdotL - float NdotV = dot(N, V); - float cNdotV = max(abs(NdotV), 1e-6); - -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) - vec3 H = normalize(V + L); -#endif - -#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) - float cNdotH = max(dot(N, H), 0.0); -#endif - -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) - float cLdotH = max(dot(L, H), 0.0); -#endif - - if (metallic < 1.0) { -#if defined(DIFFUSE_OREN_NAYAR) - vec3 diffuse_brdf_NL; -#else - float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif - -#if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - -#elif defined(DIFFUSE_OREN_NAYAR) - - { - // see http://mimosa-pudica.net/improved-oren-nayar.html - float LdotV = dot(L, V); - - float s = LdotV - NdotL * NdotV; - float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); - - float sigma2 = roughness * roughness; // TODO: this needs checking - vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); - float B = 0.45 * sigma2 / (sigma2 + 0.09); - - diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); - } - -#elif defined(DIFFUSE_TOON) - - diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); - -#elif defined(DIFFUSE_BURLEY) - - { - float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5; - float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); - float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); - diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; - /* - float energyBias = mix(roughness, 0.0, 0.5); - float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); - float fd90 = energyBias + 2.0 * VoH * VoH * roughness; - float f0 = 1.0; - float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); - float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); - - diffuse_brdf_NL = lightScatter * viewScatter * energyFactor; - */ - } -#else - // lambert - diffuse_brdf_NL = cNdotL * (1.0 / M_PI); -#endif - - SRGB_APPROX(diffuse_brdf_NL) - - diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; - -#if defined(TRANSMISSION_USED) - diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation; -#endif - -#if defined(LIGHT_USE_RIM) - float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); - diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color; -#endif - } - - if (roughness > 0.0) { - -#if defined(SPECULAR_SCHLICK_GGX) - vec3 specular_brdf_NL = vec3(0.0); -#else - float specular_brdf_NL = 0.0; -#endif - -#if defined(SPECULAR_BLINN) - - //normalized blinn - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess) * cNdotL; - blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = blinn; - -#elif defined(SPECULAR_PHONG) - - vec3 R = normalize(-reflect(L, N)); - float cRdotV = max(0.0, dot(R, V)); - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float phong = pow(cRdotV, shininess); - phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); - -#elif defined(SPECULAR_TOON) - - vec3 R = normalize(-reflect(L, N)); - float RdotV = dot(R, V); - float mid = 1.0 - roughness; - mid *= mid; - specular_brdf_NL = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; - -#elif defined(SPECULAR_DISABLED) - // none.. -#elif defined(SPECULAR_SCHLICK_GGX) - // shlick+ggx as default - -#if defined(LIGHT_USE_ANISOTROPY) - float alpha_ggx = roughness * roughness; - float aspect = sqrt(1.0 - anisotropy * 0.9); - float ax = alpha_ggx / aspect; - float ay = alpha_ggx * aspect; - float XdotH = dot(T, H); - 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); - -#else - float alpha_ggx = roughness * roughness; - float D = D_GGX(cNdotH, alpha_ggx); - //float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx); - float G = V_GGX(cNdotL, cNdotV, alpha_ggx); -#endif - // F - vec3 f0 = F0(metallic, specular, diffuse_color); - float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); - - specular_brdf_NL = cNdotL * D * F * G; - -#endif - - SRGB_APPROX(specular_brdf_NL) - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; - -#if defined(LIGHT_USE_CLEARCOAT) - -#if !defined(SPECULAR_SCHLICK_GGX) - float cLdotH5 = SchlickFresnel(cLdotH); -#endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); - float Fr = mix(.04, 1.0, cLdotH5); - //float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - float Gr = V_GGX(cNdotL, cNdotV, 0.25); - - float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - - specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; -#endif - } - -#ifdef USE_SHADOW_TO_OPACITY - alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0)); -#endif - -#endif //defined(USE_LIGHT_SHADER_CODE) -} - -#endif -// shadows - -#ifdef USE_SHADOW - -#ifdef USE_RGBA_SHADOWS - -#define SHADOW_DEPTH(m_val) dot(m_val, vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) - -#else - -#define SHADOW_DEPTH(m_val) (m_val).r - -#endif - -#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, SHADOW_DEPTH(texture2D(p_shadow, p_pos))) -#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, SHADOW_DEPTH(texture2DProj(p_shadow, p_pos))) - -float sample_shadow(highp sampler2D shadow, highp vec4 spos) { -#ifdef SHADOW_MODE_PCF_13 - - spos.xyz /= spos.w; - vec2 pos = spos.xy; - float depth = spos.z; - - float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth); - return avg * (1.0 / 13.0); -#endif - -#ifdef SHADOW_MODE_PCF_5 - - spos.xyz /= spos.w; - vec2 pos = spos.xy; - float depth = spos.z; - - float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); - avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); - return avg * (1.0 / 5.0); - -#endif - -#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) - - return SAMPLE_SHADOW_TEXEL_PROJ(shadow, spos); -#endif -} - -#endif - -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#if defined(USE_VERTEX_LIGHTING) - -varying vec4 fog_interp; - -#else -uniform mediump vec4 fog_color_base; -#ifdef LIGHT_MODE_DIRECTIONAL -uniform mediump vec4 fog_sun_color_amount; -#endif - -uniform bool fog_transmit_enabled; -uniform mediump float fog_transmit_curve; - -#ifdef FOG_DEPTH_ENABLED -uniform highp float fog_depth_begin; -uniform mediump float fog_depth_curve; -uniform mediump float fog_max_distance; -#endif - -#ifdef FOG_HEIGHT_ENABLED -uniform highp float fog_height_min; -uniform highp float fog_height_max; -uniform mediump float fog_height_curve; -#endif - -#endif //vertex lit -#endif //fog - -void main() { -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - - if (dp_clip > 0.0) - discard; -#endif - highp vec3 vertex = vertex_interp; - vec3 view = -normalize(vertex_interp); - vec3 albedo = vec3(1.0); - vec3 transmission = vec3(0.0); - float metallic = 0.0; - float specular = 0.5; - vec3 emission = vec3(0.0); - float roughness = 1.0; - float rim = 0.0; - float rim_tint = 0.0; - float clearcoat = 0.0; - float clearcoat_gloss = 0.0; - float anisotropy = 0.0; - vec2 anisotropy_flow = vec2(1.0, 0.0); - float sss_strength = 0.0; //unused - // gl_FragDepth is not available in GLES2, so writing to DEPTH is not converted to gl_FragDepth by Godot compiler resulting in a - // compile error because DEPTH is not a variable. - float m_DEPTH = 0.0; - - float alpha = 1.0; - float side = 1.0; - - float specular_blob_intensity = 1.0; -#if defined(SPECULAR_TOON) - specular_blob_intensity *= specular * 2.0; -#endif - -#if defined(ENABLE_AO) - float ao = 1.0; - float ao_light_affect = 0.0; -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - vec3 binormal = normalize(binormal_interp) * side; - vec3 tangent = normalize(tangent_interp) * side; -#else - vec3 binormal = vec3(0.0); - vec3 tangent = vec3(0.0); -#endif - vec3 normal = normalize(normal_interp) * side; - -#if defined(ENABLE_NORMALMAP) - vec3 normalmap = vec3(0.5); -#endif - float normaldepth = 1.0; - -#if defined(ALPHA_SCISSOR_USED) - float alpha_scissor = 0.5; -#endif - -#if defined(SCREEN_UV_USED) - vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; -#endif - - { - /* clang-format off */ - -FRAGMENT_SHADER_CODE - - /* clang-format on */ - } - -#if defined(ENABLE_NORMALMAP) - normalmap.xy = normalmap.xy * 2.0 - 1.0; - normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); - - normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; - //normal = normalmap; -#endif - - normal = normalize(normal); - - vec3 N = normal; - - vec3 specular_light = vec3(0.0, 0.0, 0.0); - vec3 diffuse_light = vec3(0.0, 0.0, 0.0); - vec3 ambient_light = vec3(0.0, 0.0, 0.0); - - vec3 eye_position = view; - -#if !defined(USE_SHADOW_TO_OPACITY) - -#if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { - discard; - } -#endif // ALPHA_SCISSOR_USED - -#ifdef USE_DEPTH_PREPASS - if (alpha < 0.1) { - discard; - } -#endif // USE_DEPTH_PREPASS - -#endif // !USE_SHADOW_TO_OPACITY - -#ifdef BASE_PASS - - // IBL precalculations - float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0); - vec3 f0 = F0(metallic, specular, albedo); - vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); - -#ifdef AMBIENT_LIGHT_DISABLED - ambient_light = vec3(0.0, 0.0, 0.0); -#else - -#ifdef USE_RADIANCE_MAP - - vec3 ref_vec = reflect(-eye_position, N); - ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); - - ref_vec.z *= -1.0; - - specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy; -#ifndef USE_LIGHTMAP - { - vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); - vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy; - env_ambient *= 1.0 - F; - - ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution); - } -#endif - -#else - - ambient_light = ambient_color.rgb; - specular_light = bg_color.rgb * bg_energy; - -#endif -#endif // AMBIENT_LIGHT_DISABLED - ambient_light *= ambient_energy; - -#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - - vec4 ambient_accum = vec4(0.0); - vec4 reflection_accum = vec4(0.0); - -#ifdef USE_REFLECTION_PROBE1 - - reflection_process(reflection_probe1, -#ifdef USE_VERTEX_LIGHTING - refprobe1_reflection_normal_blend.rgb, -#ifndef USE_LIGHTMAP - refprobe1_ambient_normal, -#endif - refprobe1_reflection_normal_blend.a, -#else - normal_interp, vertex_interp, refprobe1_local_matrix, - refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset, -#endif - refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness, - ambient_light, specular_light, reflection_accum, ambient_accum); - -#endif // USE_REFLECTION_PROBE1 - -#ifdef USE_REFLECTION_PROBE2 - - reflection_process(reflection_probe2, -#ifdef USE_VERTEX_LIGHTING - refprobe2_reflection_normal_blend.rgb, -#ifndef USE_LIGHTMAP - refprobe2_ambient_normal, -#endif - refprobe2_reflection_normal_blend.a, -#else - normal_interp, vertex_interp, refprobe2_local_matrix, - refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset, -#endif - refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness, - ambient_light, specular_light, reflection_accum, ambient_accum); - -#endif // USE_REFLECTION_PROBE2 - - if (reflection_accum.a > 0.0) { - specular_light = reflection_accum.rgb / reflection_accum.a; - } - -#ifndef USE_LIGHTMAP - if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; - } -#endif - -#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - - // environment BRDF approximation - { -#if defined(DIFFUSE_TOON) - //simplify for toon, as - specular_light *= specular * metallic * albedo * 2.0; -#else - - // scales the specular reflections, needs to be be computed before lighting happens, - // but after environment and reflection probes are added - //TODO: this curve is not really designed for gammaspace, should be adjusted - const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); - const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); - vec4 r = roughness * c0 + c1; - float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; - vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * F + env.y; - -#endif - } - -#ifdef USE_LIGHTMAP - //ambient light will come entirely from lightmap is lightmap is used - ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy; -#endif - -#ifdef USE_LIGHTMAP_CAPTURE - { - vec3 cone_dirs[12]; - cone_dirs[0] = vec3(0.0, 0.0, 1.0); - cone_dirs[1] = vec3(0.866025, 0.0, 0.5); - cone_dirs[2] = vec3(0.267617, 0.823639, 0.5); - cone_dirs[3] = vec3(-0.700629, 0.509037, 0.5); - cone_dirs[4] = vec3(-0.700629, -0.509037, 0.5); - cone_dirs[5] = vec3(0.267617, -0.823639, 0.5); - cone_dirs[6] = vec3(0.0, 0.0, -1.0); - cone_dirs[7] = vec3(0.866025, 0.0, -0.5); - cone_dirs[8] = vec3(0.267617, 0.823639, -0.5); - cone_dirs[9] = vec3(-0.700629, 0.509037, -0.5); - cone_dirs[10] = vec3(-0.700629, -0.509037, -0.5); - cone_dirs[11] = vec3(0.267617, -0.823639, -0.5); - - vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; - vec4 captured = vec4(0.0); - float sum = 0.0; - for (int i = 0; i < 12; i++) { - float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect - captured += lightmap_captures[i] * amount; - sum += amount; - } - - captured /= sum; - - if (lightmap_capture_sky) { - ambient_light = mix(ambient_light, captured.rgb, captured.a); - } else { - ambient_light = captured.rgb; - } - } -#endif - -#endif //BASE PASS - -// -// Lighting -// -#ifdef USE_LIGHTING - -#ifndef USE_VERTEX_LIGHTING - vec3 L; -#endif - vec3 light_att = vec3(1.0); - -#ifdef LIGHT_MODE_OMNI - -#ifndef USE_VERTEX_LIGHTING - vec3 light_vec = light_position - vertex; - float light_length = length(light_vec); - - float normalized_distance = light_length / light_range; - if (normalized_distance < 1.0) { - float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); - - light_att = vec3(omni_attenuation); - } else { - light_att = vec3(0.0); - } - L = normalize(light_vec); - -#endif - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW - { - highp vec4 splane = shadow_coord; - float shadow_len = length(splane.xyz); - - splane.xyz = normalize(splane.xyz); - - vec4 clamp_rect = light_clamp; - - if (splane.z >= 0.0) { - splane.z += 1.0; - - clamp_rect.y += clamp_rect.w; - } else { - splane.z = 1.0 - splane.z; - } - - splane.xy /= splane.z; - splane.xy = splane.xy * 0.5 + 0.5; - splane.z = shadow_len / light_range; - - splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; - splane.w = 1.0; - - float shadow = sample_shadow(light_shadow_atlas, splane); - - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); - } -#endif - -#endif //SHADOWS_DISABLED - -#endif //type omni - -#ifdef LIGHT_MODE_DIRECTIONAL - -#ifndef USE_VERTEX_LIGHTING - vec3 light_vec = -light_direction; - L = normalize(light_vec); -#endif - float depth_z = -vertex.z; - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW - -#ifdef USE_VERTEX_LIGHTING - //compute shadows in a mobile friendly way - -#ifdef LIGHT_USE_PSSM4 - //take advantage of prefetch - float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); - float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); - float shadow3 = sample_shadow(light_directional_shadow, shadow_coord3); - float shadow4 = sample_shadow(light_directional_shadow, shadow_coord4); - - if (depth_z < light_split_offsets.w) { - float pssm_fade = 0.0; - float shadow_att = 1.0; -#ifdef LIGHT_USE_PSSM_BLEND - float shadow_att2 = 1.0; - float pssm_blend = 0.0; - bool use_blend = true; -#endif - if (depth_z < light_split_offsets.y) { - if (depth_z < light_split_offsets.x) { - shadow_att = shadow1; - -#ifdef LIGHT_USE_PSSM_BLEND - shadow_att2 = shadow2; - - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); -#endif - } else { - shadow_att = shadow2; - -#ifdef LIGHT_USE_PSSM_BLEND - shadow_att2 = shadow3; - - pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#endif - } - } else { - if (depth_z < light_split_offsets.z) { - shadow_att = shadow3; - -#if defined(LIGHT_USE_PSSM_BLEND) - shadow_att2 = shadow4; - pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); -#endif - - } else { - shadow_att = shadow4; - pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); - -#if defined(LIGHT_USE_PSSM_BLEND) - use_blend = false; -#endif - } - } -#if defined(LIGHT_USE_PSSM_BLEND) - if (use_blend) { - shadow_att = mix(shadow_att, shadow_att2, pssm_blend); - } -#endif - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); - } - -#endif //LIGHT_USE_PSSM4 - -#ifdef LIGHT_USE_PSSM2 - - //take advantage of prefetch - float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); - float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); - - if (depth_z < light_split_offsets.y) { - float shadow_att = 1.0; - float pssm_fade = 0.0; - -#ifdef LIGHT_USE_PSSM_BLEND - float shadow_att2 = 1.0; - float pssm_blend = 0.0; - bool use_blend = true; -#endif - if (depth_z < light_split_offsets.x) { - float pssm_fade = 0.0; - shadow_att = shadow1; - -#ifdef LIGHT_USE_PSSM_BLEND - shadow_att2 = shadow2; - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); -#endif - } else { - shadow_att = shadow2; - pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#ifdef LIGHT_USE_PSSM_BLEND - use_blend = false; -#endif - } -#ifdef LIGHT_USE_PSSM_BLEND - if (use_blend) { - shadow_att = mix(shadow_att, shadow_att2, pssm_blend); - } -#endif - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); - } - -#endif //LIGHT_USE_PSSM2 - -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) - - light_att *= mix(shadow_color.rgb, vec3(1.0), sample_shadow(light_directional_shadow, shadow_coord)); -#endif //orthogonal - -#else //fragment version of pssm - - { -#ifdef LIGHT_USE_PSSM4 - if (depth_z < light_split_offsets.w) { -#elif defined(LIGHT_USE_PSSM2) - if (depth_z < light_split_offsets.y) { -#else - if (depth_z < light_split_offsets.x) { -#endif //pssm2 - - highp vec4 pssm_coord; - float pssm_fade = 0.0; - -#ifdef LIGHT_USE_PSSM_BLEND - float pssm_blend; - highp vec4 pssm_coord2; - bool use_blend = true; -#endif - -#ifdef LIGHT_USE_PSSM4 - - if (depth_z < light_split_offsets.y) { - if (depth_z < light_split_offsets.x) { - pssm_coord = shadow_coord; - -#ifdef LIGHT_USE_PSSM_BLEND - pssm_coord2 = shadow_coord2; - - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); -#endif - } else { - pssm_coord = shadow_coord2; - -#ifdef LIGHT_USE_PSSM_BLEND - pssm_coord2 = shadow_coord3; - - pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#endif - } - } else { - if (depth_z < light_split_offsets.z) { - pssm_coord = shadow_coord3; - -#if defined(LIGHT_USE_PSSM_BLEND) - pssm_coord2 = shadow_coord4; - pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); -#endif - - } else { - pssm_coord = shadow_coord4; - pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); - -#if defined(LIGHT_USE_PSSM_BLEND) - use_blend = false; -#endif - } - } - -#endif // LIGHT_USE_PSSM4 - -#ifdef LIGHT_USE_PSSM2 - if (depth_z < light_split_offsets.x) { - pssm_coord = shadow_coord; - -#ifdef LIGHT_USE_PSSM_BLEND - pssm_coord2 = shadow_coord2; - pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); -#endif - } else { - pssm_coord = shadow_coord2; - pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#ifdef LIGHT_USE_PSSM_BLEND - use_blend = false; -#endif - } - -#endif // LIGHT_USE_PSSM2 - -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) - { - pssm_coord = shadow_coord; - } -#endif - - float shadow = sample_shadow(light_directional_shadow, pssm_coord); - -#ifdef LIGHT_USE_PSSM_BLEND - if (use_blend) { - shadow = mix(shadow, sample_shadow(light_directional_shadow, pssm_coord2), pssm_blend); - } -#endif - - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); - } - } -#endif //use vertex lighting - -#endif //use shadow - -#endif // SHADOWS_DISABLED - -#endif - -#ifdef LIGHT_MODE_SPOT - - light_att = vec3(1.0); - -#ifndef USE_VERTEX_LIGHTING - - vec3 light_rel_vec = light_position - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length / light_range; - - if (normalized_distance < 1.0) { - float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); - vec3 spot_dir = light_direction; - - float spot_cutoff = light_spot_angle; - float angle = dot(-normalize(light_rel_vec), spot_dir); - - if (angle > spot_cutoff) { - float scos = max(angle, spot_cutoff); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); - spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); - - light_att = vec3(spot_attenuation); - } else { - light_att = vec3(0.0); - } - } else { - light_att = vec3(0.0); - } - - L = normalize(light_rel_vec); - -#endif - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW - { - highp vec4 splane = shadow_coord; - - float shadow = sample_shadow(light_shadow_atlas, splane); - light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); - } -#endif - -#endif // SHADOWS_DISABLED - -#endif // LIGHT_MODE_SPOT - -#ifdef USE_VERTEX_LIGHTING - //vertex lighting - - specular_light += specular_interp * specular_blob_intensity * light_att; - diffuse_light += diffuse_interp * albedo * light_att; - -#else - //fragment lighting - light_compute( - normal, - L, - eye_position, - binormal, - tangent, - light_color.xyz, - light_att, - albedo, - transmission, - specular_blob_intensity * light_specular, - roughness, - metallic, - specular, - rim, - rim_tint, - clearcoat, - clearcoat_gloss, - anisotropy, - diffuse_light, - specular_light, - alpha); - -#endif //vertex lighting - -#endif //USE_LIGHTING - //compute and merge - -#ifdef USE_SHADOW_TO_OPACITY - - alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); - -#if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { - discard; - } -#endif // ALPHA_SCISSOR_USED - -#ifdef USE_DEPTH_PREPASS - if (alpha < 0.1) { - discard; - } -#endif // USE_DEPTH_PREPASS - -#endif // !USE_SHADOW_TO_OPACITY - -#ifndef RENDER_DEPTH - -#ifdef SHADELESS - - gl_FragColor = vec4(albedo, alpha); -#else - - ambient_light *= albedo; - -#if defined(ENABLE_AO) - ambient_light *= ao; - ao_light_affect = mix(1.0, ao, ao_light_affect); - specular_light *= ao_light_affect; - diffuse_light *= ao_light_affect; -#endif - - diffuse_light *= 1.0 - metallic; - ambient_light *= 1.0 - metallic; - - gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha); - - //add emission if in base pass -#ifdef BASE_PASS - gl_FragColor.rgb += emission; -#endif - // gl_FragColor = vec4(normal, 1.0); - -//apply fog -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#if defined(USE_VERTEX_LIGHTING) - -#if defined(BASE_PASS) - gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_interp.rgb, fog_interp.a); -#else - gl_FragColor.rgb *= (1.0 - fog_interp.a); -#endif // BASE_PASS - -#else //pixel based fog - float fog_amount = 0.0; - -#ifdef LIGHT_MODE_DIRECTIONAL - - vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(eye_position, light_direction), 0.0), 8.0)); -#else - vec3 fog_color = fog_color_base.rgb; -#endif - -#ifdef FOG_DEPTH_ENABLED - - { - float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); - - fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; - - if (fog_transmit_enabled) { - vec3 total_light = gl_FragColor.rgb; - float transmit = pow(fog_z, fog_transmit_curve); - fog_color = mix(max(total_light, fog_color), fog_color, transmit); - } - } -#endif - -#ifdef FOG_HEIGHT_ENABLED - { - float y = (camera_matrix * vec4(vertex, 1.0)).y; - fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); - } -#endif - -#if defined(BASE_PASS) - gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_color, fog_amount); -#else - gl_FragColor.rgb *= (1.0 - fog_amount); -#endif // BASE_PASS - -#endif //use vertex lit - -#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#endif //unshaded - -#else // not RENDER_DEPTH -//depth render -#ifdef USE_RGBA_SHADOWS - - highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias - highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0)); - comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0); - gl_FragColor = comp; - -#endif -#endif -} diff --git a/drivers/gles2/shaders/screen_space_reflection.glsl b/drivers/gles2/shaders/screen_space_reflection.glsl deleted file mode 100644 index 6b5b7c885c..0000000000 --- a/drivers/gles2/shaders/screen_space_reflection.glsl +++ /dev/null @@ -1,284 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ -layout(location = 4) in vec2 uv_in; - -out vec2 uv_interp; -out vec2 pos_interp; - -void main() { - uv_interp = uv_in; - gl_Position = vertex_attrib; - pos_interp.xy = gl_Position.xy; -} - -/* clang-format off */ -[fragment] - -in vec2 uv_interp; -/* clang-format on */ -in vec2 pos_interp; - -uniform sampler2D source_diffuse; //texunit:0 -uniform sampler2D source_normal_roughness; //texunit:1 -uniform sampler2D source_depth; //texunit:2 - -uniform float camera_z_near; -uniform float camera_z_far; - -uniform vec2 viewport_size; -uniform vec2 pixel_size; - -uniform float filter_mipmap_levels; - -uniform mat4 inverse_projection; -uniform mat4 projection; - -uniform int num_steps; -uniform float depth_tolerance; -uniform float distance_fade; -uniform float curve_fade_in; - -layout(location = 0) out vec4 frag_color; - -vec2 view_to_screen(vec3 view_pos, out float w) { - vec4 projected = projection * vec4(view_pos, 1.0); - projected.xyz /= projected.w; - projected.xy = projected.xy * 0.5 + 0.5; - w = projected.w; - return projected.xy; -} - -#define M_PI 3.14159265359 - -void main() { - vec4 diffuse = texture(source_diffuse, uv_interp); - vec4 normal_roughness = texture(source_normal_roughness, uv_interp); - - vec3 normal; - - normal = normal_roughness.xyz * 2.0 - 1.0; - - float roughness = normal_roughness.w; - - float depth_tex = texture(source_depth, uv_interp).r; - - vec4 world_pos = inverse_projection * vec4(uv_interp * 2.0 - 1.0, depth_tex * 2.0 - 1.0, 1.0); - vec3 vertex = world_pos.xyz / world_pos.w; - - vec3 view_dir = normalize(vertex); - vec3 ray_dir = normalize(reflect(view_dir, normal)); - - if (dot(ray_dir, normal) < 0.001) { - frag_color = vec4(0.0); - return; - } - //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0); - - //ray_dir = normalize(vec3(1,1,-1)); - - //////////////// - - //make ray length and clip it against the near plane (don't want to trace beyond visible) - float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far; - vec3 ray_end = vertex + ray_dir * ray_len; - - float w_begin; - vec2 vp_line_begin = view_to_screen(vertex, w_begin); - float w_end; - vec2 vp_line_end = view_to_screen(ray_end, w_end); - vec2 vp_line_dir = vp_line_end - vp_line_begin; - - //we need to interpolate w along the ray, to generate perspective correct reflections - - w_begin = 1.0 / w_begin; - w_end = 1.0 / w_end; - - float z_begin = vertex.z * w_begin; - float z_end = ray_end.z * w_end; - - vec2 line_begin = vp_line_begin / pixel_size; - vec2 line_dir = vp_line_dir / pixel_size; - float z_dir = z_end - z_begin; - float w_dir = w_end - w_begin; - - // clip the line to the viewport edges - - float scale_max_x = min(1.0, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x)); - float scale_max_y = min(1.0, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y)); - float scale_min_x = min(1.0, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x)); - float scale_min_y = min(1.0, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y)); - float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y); - line_dir *= line_clip; - z_dir *= line_clip; - w_dir *= line_clip; - - //clip z and w advance to line advance - vec2 line_advance = normalize(line_dir); //down to pixel - float step_size = length(line_advance) / length(line_dir); - float z_advance = z_dir * step_size; // adapt z advance to line advance - float w_advance = w_dir * step_size; // adapt w advance to line advance - - //make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice) - float advance_angle_adj = 1.0 / max(abs(line_advance.x), abs(line_advance.y)); - line_advance *= advance_angle_adj; // adapt z advance to line advance - z_advance *= advance_angle_adj; - w_advance *= advance_angle_adj; - - vec2 pos = line_begin; - float z = z_begin; - float w = w_begin; - float z_from = z / w; - float z_to = z_from; - float depth; - vec2 prev_pos = pos; - - bool found = false; - - float steps_taken = 0.0; - - for (int i = 0; i < num_steps; i++) { - pos += line_advance; - z += z_advance; - w += w_advance; - - //convert to linear depth - - depth = texture(source_depth, pos * pixel_size).r * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); -#endif - depth = -depth; - - z_from = z_to; - z_to = z / w; - - if (depth > z_to) { - //if depth was surpassed - if (depth <= max(z_to, z_from) + depth_tolerance) { - //check the depth tolerance - found = true; - } - break; - } - - steps_taken += 1.0; - prev_pos = pos; - } - - if (found) { - float margin_blend = 1.0; - - vec2 margin = vec2((viewport_size.x + viewport_size.y) * 0.5 * 0.05); //make a uniform margin - if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, viewport_size + margin)))) { - //clip outside screen + margin - frag_color = vec4(0.0); - return; - } - - { - //blend fading out towards external margin - vec2 margin_grad = mix(pos - viewport_size, -pos, lessThan(pos, vec2(0.0))); - margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y)); - //margin_blend=1.0; - } - - vec2 final_pos; - float grad; - grad = steps_taken / float(num_steps); - float initial_fade = curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), curve_fade_in); - float fade = pow(clamp(1.0 - grad, 0.0, 1.0), distance_fade) * initial_fade; - final_pos = pos; - -#ifdef REFLECT_ROUGHNESS - - vec4 final_color; - //if roughness is enabled, do screen space cone tracing - if (roughness > 0.001) { - /////////////////////////////////////////////////////////////////////////////////////// - //use a blurred version (in consecutive mipmaps) of the screen to simulate roughness - - float gloss = 1.0 - roughness; - float cone_angle = roughness * M_PI * 0.5; - vec2 cone_dir = final_pos - line_begin; - float cone_len = length(cone_dir); - cone_dir = normalize(cone_dir); //will be used normalized from now on - float max_mipmap = filter_mipmap_levels - 1.0; - float gloss_mult = gloss; - - float rem_alpha = 1.0; - final_color = vec4(0.0); - - for (int i = 0; i < 7; i++) { - float op_len = 2.0 * tan(cone_angle) * cone_len; //opposite side of iso triangle - float radius; - { - //fit to sphere inside cone (sphere ends at end of cone), something like this: - // ___ - // \O/ - // V - // - // as it avoids bleeding from beyond the reflection as much as possible. As a plus - // it also makes the rough reflection more elongated. - float a = op_len; - float h = cone_len; - float a2 = a * a; - float fh2 = 4.0f * h * h; - radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h); - } - - //find the place where screen must be sampled - vec2 sample_pos = (line_begin + cone_dir * (cone_len - radius)) * pixel_size; - //radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels - float mipmap = clamp(log2(radius), 0.0, max_mipmap); - - //mipmap = max(mipmap-1.0,0.0); - //do sampling - - vec4 sample_color; - { - sample_color = textureLod(source_diffuse, sample_pos, mipmap); - } - - //multiply by gloss - sample_color.rgb *= gloss_mult; - sample_color.a = gloss_mult; - - rem_alpha -= sample_color.a; - if (rem_alpha < 0.0) { - sample_color.rgb *= (1.0 - abs(rem_alpha)); - } - - final_color += sample_color; - - if (final_color.a >= 0.95) { - // This code of accumulating gloss and aborting on near one - // makes sense when you think of cone tracing. - // Think of it as if roughness was 0, then we could abort on the first - // iteration. For lesser roughness values, we need more iterations, but - // each needs to have less influence given the sphere is smaller - break; - } - - cone_len -= radius * 2.0; //go to next (smaller) circle. - - gloss_mult *= gloss; - } - } else { - final_color = textureLod(source_diffuse, final_pos * pixel_size, 0.0); - } - - frag_color = vec4(final_color.rgb, fade * margin_blend); - -#else - frag_color = vec4(textureLod(source_diffuse, final_pos * pixel_size, 0.0).rgb, fade * margin_blend); -#endif - - } else { - frag_color = vec4(0.0, 0.0, 0.0, 0.0); - } -} diff --git a/drivers/gles2/shaders/ssao.glsl b/drivers/gles2/shaders/ssao.glsl deleted file mode 100644 index 0fd29e8dcc..0000000000 --- a/drivers/gles2/shaders/ssao.glsl +++ /dev/null @@ -1,283 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ - -void main() { - gl_Position = vertex_attrib; - gl_Position.z = 1.0; -} - -/* clang-format off */ -[fragment] - -#define TWO_PI 6.283185307179586476925286766559 - -#ifdef SSAO_QUALITY_HIGH - -#define NUM_SAMPLES (80) - -#endif - -#ifdef SSAO_QUALITY_LOW - -#define NUM_SAMPLES (15) - -#endif - -#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) - -#define NUM_SAMPLES (40) - -#endif - -// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower -// miplevel to maintain reasonable spatial locality in the cache -// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. -// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively -#define LOG_MAX_OFFSET (3) - -// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp -#define MAX_MIP_LEVEL (4) - -// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent -// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 - -const int ROTATIONS[] = int[]( - 1, 1, 2, 3, 2, 5, 2, 3, 2, - 3, 3, 5, 5, 3, 4, 7, 5, 5, 7, - 9, 8, 5, 5, 7, 7, 7, 8, 5, 8, - 11, 12, 7, 10, 13, 8, 11, 8, 7, 14, - 11, 11, 13, 12, 13, 19, 17, 13, 11, 18, - 19, 11, 11, 14, 17, 21, 15, 16, 17, 18, - 13, 17, 11, 17, 19, 18, 25, 18, 19, 19, - 29, 21, 19, 27, 31, 29, 21, 18, 17, 29, - 31, 31, 23, 18, 25, 26, 25, 23, 19, 34, - 19, 27, 21, 25, 39, 29, 17, 21, 27); -/* clang-format on */ - -//#define NUM_SPIRAL_TURNS (7) -const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1]; - -uniform sampler2D source_depth; //texunit:0 -uniform highp usampler2D source_depth_mipmaps; //texunit:1 -uniform sampler2D source_normal; //texunit:2 - -uniform ivec2 screen_size; -uniform float camera_z_far; -uniform float camera_z_near; - -uniform float intensity_div_r6; -uniform float radius; - -#ifdef ENABLE_RADIUS2 -uniform float intensity_div_r62; -uniform float radius2; -#endif - -uniform float bias; -uniform float proj_scale; - -layout(location = 0) out float visibility; - -uniform vec4 proj_info; - -vec3 reconstructCSPosition(vec2 S, float z) { -#ifdef USE_ORTHOGONAL_PROJECTION - return vec3((S.xy * proj_info.xy + proj_info.zw), z); -#else - return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z); - -#endif -} - -vec3 getPosition(ivec2 ssP) { - vec3 P; - P.z = texelFetch(source_depth, ssP, 0).r; - - P.z = P.z * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); -#endif - P.z = -P.z; - - // Offset to pixel center - P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); - return P; -} - -/** Reconstructs screen-space unit normal from screen-space position */ -vec3 reconstructCSFaceNormal(vec3 C) { - return normalize(cross(dFdy(C), dFdx(C))); -} - -/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ -vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) { - // Radius relative to ssR - float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); - float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; - - ssR = alpha; - return vec2(cos(angle), sin(angle)); -} - -/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ -vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { - // Derivation: - // mipLevel = floor(log(ssR / MAX_OFFSET)); - int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); - - ivec2 ssP = ivec2(ssR * unitOffset) + ssC; - - vec3 P; - - // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. - // Manually clamp to the texture size because texelFetch bypasses the texture unit - ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1)); - - if (mipLevel < 1) { - //read from depth buffer - P.z = texelFetch(source_depth, mipP, 0).r; - P.z = P.z * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); - -#endif - P.z = -P.z; - - } else { - //read from mipmaps - uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r; - P.z = -(float(d) / 65535.0) * camera_z_far; - } - - // Offset to pixel center - P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); - - return P; -} - -/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds - to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius - - Note that units of H() in the HPG12 paper are meters, not - unitless. The whole falloff/sampling function is therefore - unitless. In this implementation, we factor out (9 / radius). - - Four versions of the falloff function are implemented below -*/ -float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { - // Offset on the unit disk, spun for this pixel - float ssR; - vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); - ssR *= ssDiskRadius; - - // The occluding point in camera space - vec3 Q = getOffsetPosition(ssC, unitOffset, ssR); - - vec3 v = Q - C; - - float vv = dot(v, v); - float vn = dot(v, n_C); - - const float epsilon = 0.01; - float radius2 = p_radius * p_radius; - - // A: From the HPG12 paper - // Note large epsilon to avoid overdarkening within cracks - //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; - - // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] - float f = max(radius2 - vv, 0.0); - return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); - - // C: Medium contrast (which looks better at high radii), no division. Note that the - // contribution still falls off with radius^2, but we've adjusted the rate in a way that is - // more computationally efficient and happens to be aesthetically pleasing. - // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); - - // D: Low contrast, no division operation - // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); -} - -void main() { - // Pixel being shaded - ivec2 ssC = ivec2(gl_FragCoord.xy); - - // World space point being shaded - vec3 C = getPosition(ssC); - - /* - if (C.z <= -camera_z_far*0.999) { - // We're on the skybox - visibility=1.0; - return; - } - */ - - //visibility=-C.z/camera_z_far; - //return; -#if 0 - vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0; -#else - vec3 n_C = reconstructCSFaceNormal(C); - n_C = -n_C; -#endif - - // Hash function used in the HPG12 AlchemyAO paper - float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI); - - // Reconstruct normals from positions. These will lead to 1-pixel black lines - // at depth discontinuities, however the blur will wipe those out so they are not visible - // in the final image. - - // Choose the screen-space sample radius - // proportional to the projected area of the sphere -#ifdef USE_ORTHOGONAL_PROJECTION - float ssDiskRadius = -proj_scale * radius; -#else - float ssDiskRadius = -proj_scale * radius / C.z; -#endif - float sum = 0.0; - for (int i = 0; i < NUM_SAMPLES; ++i) { - sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius, i, randomPatternRotationAngle); - } - - float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / float(NUM_SAMPLES))); - -#ifdef ENABLE_RADIUS2 - - //go again for radius2 - randomPatternRotationAngle = mod(float((5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11), TWO_PI); - - // Reconstruct normals from positions. These will lead to 1-pixel black lines - // at depth discontinuities, however the blur will wipe those out so they are not visible - // in the final image. - - // Choose the screen-space sample radius - // proportional to the projected area of the sphere - ssDiskRadius = -proj_scale * radius2 / C.z; - - sum = 0.0; - for (int i = 0; i < NUM_SAMPLES; ++i) { - sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius2, i, randomPatternRotationAngle); - } - - A = min(A, max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES)))); -#endif - // Bilateral box-filter over a quad for free, respecting depth edges - // (the difference that this makes is subtle) - if (abs(dFdx(C.z)) < 0.02) { - A -= dFdx(A) * (float(ssC.x & 1) - 0.5); - } - if (abs(dFdy(C.z)) < 0.02) { - A -= dFdy(A) * (float(ssC.y & 1) - 0.5); - } - - visibility = A; -} diff --git a/drivers/gles2/shaders/ssao_blur.glsl b/drivers/gles2/shaders/ssao_blur.glsl deleted file mode 100644 index f065cd74eb..0000000000 --- a/drivers/gles2/shaders/ssao_blur.glsl +++ /dev/null @@ -1,116 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ - -void main() { - gl_Position = vertex_attrib; - gl_Position.z = 1.0; -} - -/* clang-format off */ -[fragment] - -uniform sampler2D source_ssao; //texunit:0 -/* clang-format on */ -uniform sampler2D source_depth; //texunit:1 -uniform sampler2D source_normal; //texunit:3 - -layout(location = 0) out float visibility; - -////////////////////////////////////////////////////////////////////////////////////////////// -// Tunable Parameters: - -/** Increase to make depth edges crisper. Decrease to reduce flicker. */ -uniform float edge_sharpness; - -/** Step in 2-pixel intervals since we already blurred against neighbors in the - first AO pass. This constant can be increased while R decreases to improve - performance at the expense of some dithering artifacts. - - Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was - unobjectionable after shading was applied but eliminated most temporal incoherence - from using small numbers of sample taps. - */ - -uniform int filter_scale; - -/** Filter radius in pixels. This will be multiplied by SCALE. */ -#define R (4) - -////////////////////////////////////////////////////////////////////////////////////////////// - -// Gaussian coefficients -const float gaussian[R + 1] = - //float[](0.356642, 0.239400, 0.072410, 0.009869); - //float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 - float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 -//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 - -/** (1, 0) or (0, 1)*/ -uniform ivec2 axis; - -uniform float camera_z_far; -uniform float camera_z_near; - -uniform ivec2 screen_size; - -void main() { - ivec2 ssC = ivec2(gl_FragCoord.xy); - - float depth = texelFetch(source_depth, ssC, 0).r; - //vec3 normal = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0; - - depth = depth * 2.0 - 1.0; - depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); - - float depth_divide = 1.0 / camera_z_far; - - //depth *= depth_divide; - - /* - if (depth > camera_z_far * 0.999) { - discard; //skybox - } - */ - - float sum = texelFetch(source_ssao, ssC, 0).r; - - // Base weight for depth falloff. Increase this for more blurriness, - // decrease it for better edge discrimination - float BASE = gaussian[0]; - float totalWeight = BASE; - sum *= totalWeight; - - ivec2 clamp_limit = screen_size - ivec2(1); - - for (int r = -R; r <= R; ++r) { - // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, - // so the IF statement has no runtime cost - if (r != 0) { - ivec2 ppos = ssC + axis * (r * filter_scale); - float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r; - ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit); - float temp_depth = texelFetch(source_depth, rpos, 0).r; - //vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0; - - temp_depth = temp_depth * 2.0 - 1.0; - temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near)); - // temp_depth *= depth_divide; - - // spatial domain: offset gaussian tap - float weight = 0.3 + gaussian[abs(r)]; - //weight *= max(0.0,dot(temp_normal,normal)); - - // range domain (the "bilateral" weight). As depth difference increases, decrease weight. - weight *= max(0.0, 1.0 - edge_sharpness * abs(temp_depth - depth)); - - sum += value * weight; - totalWeight += weight; - } - } - - const float epsilon = 0.0001; - visibility = sum / (totalWeight + epsilon); -} diff --git a/drivers/gles2/shaders/ssao_minify.glsl b/drivers/gles2/shaders/ssao_minify.glsl deleted file mode 100644 index f654e00a4f..0000000000 --- a/drivers/gles2/shaders/ssao_minify.glsl +++ /dev/null @@ -1,54 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ - -void main() { - gl_Position = vertex_attrib; -} - -/* clang-format off */ -[fragment] - -#ifdef MINIFY_START - -#define SDEPTH_TYPE highp sampler2D -uniform float camera_z_far; -uniform float camera_z_near; -/* clang-format on */ - -#else - -#define SDEPTH_TYPE mediump usampler2D - -#endif - -uniform SDEPTH_TYPE source_depth; //texunit:0 - -uniform ivec2 from_size; -uniform int source_mipmap; - -layout(location = 0) out mediump uint depth; - -void main() { - ivec2 ssP = ivec2(gl_FragCoord.xy); - - // Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling. - // On DX9, the bit-and can be implemented with floating-point modulo - -#ifdef MINIFY_START - float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; - fdepth = fdepth * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - fdepth = ((fdepth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near)); -#endif - fdepth /= camera_z_far; - depth = uint(clamp(fdepth * 65535.0, 0.0, 65535.0)); - -#else - depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; -#endif -} diff --git a/drivers/gles2/shaders/stdlib.glsl b/drivers/gles2/shaders/stdlib.glsl deleted file mode 100644 index 9c74418743..0000000000 --- a/drivers/gles2/shaders/stdlib.glsl +++ /dev/null @@ -1,420 +0,0 @@ - -vec2 select2(vec2 a, vec2 b, bvec2 c) { - vec2 ret; - - ret.x = c.x ? b.x : a.x; - ret.y = c.y ? b.y : a.y; - - return ret; -} - -vec3 select3(vec3 a, vec3 b, bvec3 c) { - vec3 ret; - - ret.x = c.x ? b.x : a.x; - ret.y = c.y ? b.y : a.y; - ret.z = c.z ? b.z : a.z; - - return ret; -} - -vec4 select4(vec4 a, vec4 b, bvec4 c) { - vec4 ret; - - ret.x = c.x ? b.x : a.x; - ret.y = c.y ? b.y : a.y; - ret.z = c.z ? b.z : a.z; - ret.w = c.w ? b.w : a.w; - - return ret; -} - -highp vec4 texel2DFetch(highp sampler2D tex, ivec2 size, ivec2 coord) { - float x_coord = float(2 * coord.x + 1) / float(size.x * 2); - float y_coord = float(2 * coord.y + 1) / float(size.y * 2); - - return texture2DLod(tex, vec2(x_coord, y_coord), 0.0); -} - -#if defined(SINH_USED) - -highp float sinh(highp float x) { - return 0.5 * (exp(x) - exp(-x)); -} - -highp vec2 sinh(highp vec2 x) { - return 0.5 * vec2(exp(x.x) - exp(-x.x), exp(x.y) - exp(-x.y)); -} - -highp vec3 sinh(highp vec3 x) { - return 0.5 * vec3(exp(x.x) - exp(-x.x), exp(x.y) - exp(-x.y), exp(x.z) - exp(-x.z)); -} - -highp vec4 sinh(highp vec4 x) { - return 0.5 * vec4(exp(x.x) - exp(-x.x), exp(x.y) - exp(-x.y), exp(x.z) - exp(-x.z), exp(x.w) - exp(-x.w)); -} - -#endif - -#if defined(COSH_USED) - -highp float cosh(highp float x) { - return 0.5 * (exp(x) + exp(-x)); -} - -highp vec2 cosh(highp vec2 x) { - return 0.5 * vec2(exp(x.x) + exp(-x.x), exp(x.y) + exp(-x.y)); -} - -highp vec3 cosh(highp vec3 x) { - return 0.5 * vec3(exp(x.x) + exp(-x.x), exp(x.y) + exp(-x.y), exp(x.z) + exp(-x.z)); -} - -highp vec4 cosh(highp vec4 x) { - return 0.5 * vec4(exp(x.x) + exp(-x.x), exp(x.y) + exp(-x.y), exp(x.z) + exp(-x.z), exp(x.w) + exp(-x.w)); -} - -#endif - -#if defined(TANH_USED) - -highp float tanh(highp float x) { - highp float exp2x = exp(2.0 * x); - return (exp2x - 1.0) / (exp2x + 1.0); -} - -highp vec2 tanh(highp vec2 x) { - highp float exp2x = exp(2.0 * x.x); - highp float exp2y = exp(2.0 * x.y); - return vec2((exp2x - 1.0) / (exp2x + 1.0), (exp2y - 1.0) / (exp2y + 1.0)); -} - -highp vec3 tanh(highp vec3 x) { - highp float exp2x = exp(2.0 * x.x); - highp float exp2y = exp(2.0 * x.y); - highp float exp2z = exp(2.0 * x.z); - return vec3((exp2x - 1.0) / (exp2x + 1.0), (exp2y - 1.0) / (exp2y + 1.0), (exp2z - 1.0) / (exp2z + 1.0)); -} - -highp vec4 tanh(highp vec4 x) { - highp float exp2x = exp(2.0 * x.x); - highp float exp2y = exp(2.0 * x.y); - highp float exp2z = exp(2.0 * x.z); - highp float exp2w = exp(2.0 * x.w); - return vec4((exp2x - 1.0) / (exp2x + 1.0), (exp2y - 1.0) / (exp2y + 1.0), (exp2z - 1.0) / (exp2z + 1.0), (exp2w - 1.0) / (exp2w + 1.0)); -} - -#endif - -#if defined(ASINH_USED) - -highp float asinh(highp float x) { - return sign(x) * log(abs(x) + sqrt(1.0 + x * x)); -} - -highp vec2 asinh(highp vec2 x) { - return vec2(sign(x.x) * log(abs(x.x) + sqrt(1.0 + x.x * x.x)), sign(x.y) * log(abs(x.y) + sqrt(1.0 + x.y * x.y))); -} - -highp vec3 asinh(highp vec3 x) { - return vec3(sign(x.x) * log(abs(x.x) + sqrt(1.0 + x.x * x.x)), sign(x.y) * log(abs(x.y) + sqrt(1.0 + x.y * x.y)), sign(x.z) * log(abs(x.z) + sqrt(1.0 + x.z * x.z))); -} - -highp vec4 asinh(highp vec4 x) { - return vec4(sign(x.x) * log(abs(x.x) + sqrt(1.0 + x.x * x.x)), sign(x.y) * log(abs(x.y) + sqrt(1.0 + x.y * x.y)), sign(x.z) * log(abs(x.z) + sqrt(1.0 + x.z * x.z)), sign(x.w) * log(abs(x.w) + sqrt(1.0 + x.w * x.w))); -} - -#endif - -#if defined(ACOSH_USED) - -highp float acosh(highp float x) { - return log(x + sqrt(x * x - 1.0)); -} - -highp vec2 acosh(highp vec2 x) { - return vec2(log(x.x + sqrt(x.x * x.x - 1.0)), log(x.y + sqrt(x.y * x.y - 1.0))); -} - -highp vec3 acosh(highp vec3 x) { - return vec3(log(x.x + sqrt(x.x * x.x - 1.0)), log(x.y + sqrt(x.y * x.y - 1.0)), log(x.z + sqrt(x.z * x.z - 1.0))); -} - -highp vec4 acosh(highp vec4 x) { - return vec4(log(x.x + sqrt(x.x * x.x - 1.0)), log(x.y + sqrt(x.y * x.y - 1.0)), log(x.z + sqrt(x.z * x.z - 1.0)), log(x.w + sqrt(x.w * x.w - 1.0))); -} - -#endif - -#if defined(ATANH_USED) - -highp float atanh(highp float x) { - return 0.5 * log((1.0 + x) / (1.0 - x)); -} - -highp vec2 atanh(highp vec2 x) { - return 0.5 * vec2(log((1.0 + x.x) / (1.0 - x.x)), log((1.0 + x.y) / (1.0 - x.y))); -} - -highp vec3 atanh(highp vec3 x) { - return 0.5 * vec3(log((1.0 + x.x) / (1.0 - x.x)), log((1.0 + x.y) / (1.0 - x.y)), log((1.0 + x.z) / (1.0 - x.z))); -} - -highp vec4 atanh(highp vec4 x) { - return 0.5 * vec4(log((1.0 + x.x) / (1.0 - x.x)), log((1.0 + x.y) / (1.0 - x.y)), log((1.0 + x.z) / (1.0 - x.z)), log((1.0 + x.w) / (1.0 - x.w))); -} - -#endif - -#if defined(ROUND_USED) - -highp float round(highp float x) { - return floor(x + 0.5); -} - -highp vec2 round(highp vec2 x) { - return floor(x + vec2(0.5)); -} - -highp vec3 round(highp vec3 x) { - return floor(x + vec3(0.5)); -} - -highp vec4 round(highp vec4 x) { - return floor(x + vec4(0.5)); -} - -#endif - -#if defined(ROUND_EVEN_USED) - -highp float roundEven(highp float x) { - highp float t = x + 0.5; - highp float f = floor(t); - highp float r; - if (t == f) { - if (x > 0) - r = f - mod(f, 2); - else - r = f + mod(f, 2); - } else - r = f; - return r; -} - -highp vec2 roundEven(highp vec2 x) { - return vec2(roundEven(x.x), roundEven(x.y)); -} - -highp vec3 roundEven(highp vec3 x) { - return vec3(roundEven(x.x), roundEven(x.y), roundEven(x.z)); -} - -highp vec4 roundEven(highp vec4 x) { - return vec4(roundEven(x.x), roundEven(x.y), roundEven(x.z), roundEven(x.w)); -} - -#endif - -#if defined(IS_INF_USED) - -bool isinf(highp float x) { - return (2 * x == x) && (x != 0); -} - -bvec2 isinf(highp vec2 x) { - return bvec2((2 * x.x == x.x) && (x.x != 0), (2 * x.y == x.y) && (x.y != 0)); -} - -bvec3 isinf(highp vec3 x) { - return bvec3((2 * x.x == x.x) && (x.x != 0), (2 * x.y == x.y) && (x.y != 0), (2 * x.z == x.z) && (x.z != 0)); -} - -bvec4 isinf(highp vec4 x) { - return bvec4((2 * x.x == x.x) && (x.x != 0), (2 * x.y == x.y) && (x.y != 0), (2 * x.z == x.z) && (x.z != 0), (2 * x.w == x.w) && (x.w != 0)); -} - -#endif - -#if defined(IS_NAN_USED) - -bool isnan(highp float x) { - return x != x; -} - -bvec2 isnan(highp vec2 x) { - return bvec2(x.x != x.x, x.y != x.y); -} - -bvec3 isnan(highp vec3 x) { - return bvec3(x.x != x.x, x.y != x.y, x.z != x.z); -} - -bvec4 isnan(highp vec4 x) { - return bvec4(x.x != x.x, x.y != x.y, x.z != x.z, x.w != x.w); -} - -#endif - -#if defined(TRUNC_USED) - -highp float trunc(highp float x) { - return x < 0 ? -floor(-x) : floor(x); -} - -highp vec2 trunc(highp vec2 x) { - return vec2(x.x < 0 ? -floor(-x.x) : floor(x.x), x.y < 0 ? -floor(-x.y) : floor(x.y)); -} - -highp vec3 trunc(highp vec3 x) { - return vec3(x.x < 0 ? -floor(-x.x) : floor(x.x), x.y < 0 ? -floor(-x.y) : floor(x.y), x.z < 0 ? -floor(-x.z) : floor(x.z)); -} - -highp vec4 trunc(highp vec4 x) { - return vec4(x.x < 0 ? -floor(-x.x) : floor(x.x), x.y < 0 ? -floor(-x.y) : floor(x.y), x.z < 0 ? -floor(-x.z) : floor(x.z), x.w < 0 ? -floor(-x.w) : floor(x.w)); -} - -#endif - -#if defined(DETERMINANT_USED) - -highp float determinant(highp mat2 m) { - return m[0].x * m[1].y - m[1].x * m[0].y; -} - -highp float determinant(highp mat3 m) { - return m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z); -} - -highp float determinant(highp mat4 m) { - highp float s00 = m[2].z * m[3].w - m[3].z * m[2].w; - highp float s01 = m[2].y * m[3].w - m[3].y * m[2].w; - highp float s02 = m[2].y * m[3].z - m[3].y * m[2].z; - highp float s03 = m[2].x * m[3].w - m[3].x * m[2].w; - highp float s04 = m[2].x * m[3].z - m[3].x * m[2].z; - highp float s05 = m[2].x * m[3].y - m[3].x * m[2].y; - highp vec4 c = vec4((m[1].y * s00 - m[1].z * s01 + m[1].w * s02), -(m[1].x * s00 - m[1].z * s03 + m[1].w * s04), (m[1].x * s01 - m[1].y * s03 + m[1].w * s05), -(m[1].x * s02 - m[1].y * s04 + m[1].z * s05)); - return m[0].x * c.x + m[0].y * c.y + m[0].z * c.z + m[0].w * c.w; -} - -#endif - -#if defined(INVERSE_USED) - -highp mat2 inverse(highp mat2 m) { - highp float d = 1.0 / (m[0].x * m[1].y - m[1].x * m[0].y); - return mat2( - vec2(m[1].y * d, -m[0].y * d), - vec2(-m[1].x * d, m[0].x * d)); -} - -highp mat3 inverse(highp mat3 m) { - highp float d = 1.0 / (m[0].x * (m[1].y * m[2].z - m[2].y * m[1].z) - m[1].x * (m[0].y * m[2].z - m[2].y * m[0].z) + m[2].x * (m[0].y * m[1].z - m[1].y * m[0].z)); - return mat3( - vec3((m[1].y * m[2].z - m[2].y * m[1].z), -(m[1].x * m[2].z - m[2].x * m[1].z), (m[1].x * m[2].y - m[2].x * m[1].y)) * d, - vec3(-(m[0].y * m[2].z - m[2].y * m[0].z), (m[0].x * m[2].z - m[2].x * m[0].z), -(m[0].x * m[2].y - m[2].x * m[0].y)) * d, - vec3((m[0].y * m[1].z - m[1].y * m[0].z), -(m[0].x * m[1].z - m[1].x * m[0].z), (m[0].x * m[1].y - m[1].x * m[0].y)) * d); -} - -highp mat4 inverse(highp mat4 m) { - highp float c00 = m[2].z * m[3].w - m[3].z * m[2].w; - highp float c02 = m[1].z * m[3].w - m[3].z * m[1].w; - highp float c03 = m[1].z * m[2].w - m[2].z * m[1].w; - - highp float c04 = m[2].y * m[3].w - m[3].y * m[2].w; - highp float c06 = m[1].y * m[3].w - m[3].y * m[1].w; - highp float c07 = m[1].y * m[2].w - m[2].y * m[1].w; - - highp float c08 = m[2].y * m[3].z - m[3].y * m[2].z; - highp float c10 = m[1].y * m[3].z - m[3].y * m[1].z; - highp float c11 = m[1].y * m[2].z - m[2].y * m[1].z; - - highp float c12 = m[2].x * m[3].w - m[3].x * m[2].w; - highp float c14 = m[1].x * m[3].w - m[3].x * m[1].w; - highp float c15 = m[1].x * m[2].w - m[2].x * m[1].w; - - highp float c16 = m[2].x * m[3].z - m[3].x * m[2].z; - highp float c18 = m[1].x * m[3].z - m[3].x * m[1].z; - highp float c19 = m[1].x * m[2].z - m[2].x * m[1].z; - - highp float c20 = m[2].x * m[3].y - m[3].x * m[2].y; - highp float c22 = m[1].x * m[3].y - m[3].x * m[1].y; - highp float c23 = m[1].x * m[2].y - m[2].x * m[1].y; - - vec4 f0 = vec4(c00, c00, c02, c03); - vec4 f1 = vec4(c04, c04, c06, c07); - vec4 f2 = vec4(c08, c08, c10, c11); - vec4 f3 = vec4(c12, c12, c14, c15); - vec4 f4 = vec4(c16, c16, c18, c19); - vec4 f5 = vec4(c20, c20, c22, c23); - - vec4 v0 = vec4(m[1].x, m[0].x, m[0].x, m[0].x); - vec4 v1 = vec4(m[1].y, m[0].y, m[0].y, m[0].y); - vec4 v2 = vec4(m[1].z, m[0].z, m[0].z, m[0].z); - vec4 v3 = vec4(m[1].w, m[0].w, m[0].w, m[0].w); - - vec4 inv0 = vec4(v1 * f0 - v2 * f1 + v3 * f2); - vec4 inv1 = vec4(v0 * f0 - v2 * f3 + v3 * f4); - vec4 inv2 = vec4(v0 * f1 - v1 * f3 + v3 * f5); - vec4 inv3 = vec4(v0 * f2 - v1 * f4 + v2 * f5); - - vec4 sa = vec4(+1, -1, +1, -1); - vec4 sb = vec4(-1, +1, -1, +1); - - mat4 inv = mat4(inv0 * sa, inv1 * sb, inv2 * sa, inv3 * sb); - - vec4 r0 = vec4(inv[0].x, inv[1].x, inv[2].x, inv[3].x); - vec4 d0 = vec4(m[0] * r0); - - highp float d1 = (d0.x + d0.y) + (d0.z + d0.w); - highp float d = 1.0 / d1; - - return inv * d; -} - -#endif - -#ifndef USE_GLES_OVER_GL - -#if defined(TRANSPOSE_USED) - -highp mat2 transpose(highp mat2 m) { - return mat2( - vec2(m[0].x, m[1].x), - vec2(m[0].y, m[1].y)); -} - -highp mat3 transpose(highp mat3 m) { - return mat3( - vec3(m[0].x, m[1].x, m[2].x), - vec3(m[0].y, m[1].y, m[2].y), - vec3(m[0].z, m[1].z, m[2].z)); -} - -#endif - -highp mat4 transpose(highp mat4 m) { - return mat4( - vec4(m[0].x, m[1].x, m[2].x, m[3].x), - vec4(m[0].y, m[1].y, m[2].y, m[3].y), - vec4(m[0].z, m[1].z, m[2].z, m[3].z), - vec4(m[0].w, m[1].w, m[2].w, m[3].w)); -} - -#if defined(OUTER_PRODUCT_USED) - -highp mat2 outerProduct(highp vec2 c, highp vec2 r) { - return mat2(c * r.x, c * r.y); -} - -highp mat3 outerProduct(highp vec3 c, highp vec3 r) { - return mat3(c * r.x, c * r.y, c * r.z); -} - -highp mat4 outerProduct(highp vec4 c, highp vec4 r) { - return mat4(c * r.x, c * r.y, c * r.z, c * r.w); -} - -#endif - -#endif diff --git a/drivers/gles2/shaders/subsurf_scattering.glsl b/drivers/gles2/shaders/subsurf_scattering.glsl deleted file mode 100644 index d0c34cf1b0..0000000000 --- a/drivers/gles2/shaders/subsurf_scattering.glsl +++ /dev/null @@ -1,171 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ -layout(location = 4) in vec2 uv_in; - -out vec2 uv_interp; - -void main() { - uv_interp = uv_in; - gl_Position = vertex_attrib; -} - -/* clang-format off */ -[fragment] - -//#define QUALIFIER uniform // some guy on the interweb says it may be faster with this -#define QUALIFIER const - -#ifdef USE_25_SAMPLES -const int kernel_size = 25; -/* clang-format on */ -QUALIFIER vec2 kernel[25] = vec2[]( - vec2(0.530605, 0.0), - vec2(0.000973794, -3.0), - vec2(0.00333804, -2.52083), - vec2(0.00500364, -2.08333), - vec2(0.00700976, -1.6875), - vec2(0.0094389, -1.33333), - vec2(0.0128496, -1.02083), - vec2(0.017924, -0.75), - vec2(0.0263642, -0.520833), - vec2(0.0410172, -0.333333), - vec2(0.0493588, -0.1875), - vec2(0.0402784, -0.0833333), - vec2(0.0211412, -0.0208333), - vec2(0.0211412, 0.0208333), - vec2(0.0402784, 0.0833333), - vec2(0.0493588, 0.1875), - vec2(0.0410172, 0.333333), - vec2(0.0263642, 0.520833), - vec2(0.017924, 0.75), - vec2(0.0128496, 1.02083), - vec2(0.0094389, 1.33333), - vec2(0.00700976, 1.6875), - vec2(0.00500364, 2.08333), - vec2(0.00333804, 2.52083), - vec2(0.000973794, 3.0)); -#endif //USE_25_SAMPLES - -#ifdef USE_17_SAMPLES -const int kernel_size = 17; -QUALIFIER vec2 kernel[17] = vec2[]( - vec2(0.536343, 0.0), - vec2(0.00317394, -2.0), - vec2(0.0100386, -1.53125), - vec2(0.0144609, -1.125), - vec2(0.0216301, -0.78125), - vec2(0.0347317, -0.5), - vec2(0.0571056, -0.28125), - vec2(0.0582416, -0.125), - vec2(0.0324462, -0.03125), - vec2(0.0324462, 0.03125), - vec2(0.0582416, 0.125), - vec2(0.0571056, 0.28125), - vec2(0.0347317, 0.5), - vec2(0.0216301, 0.78125), - vec2(0.0144609, 1.125), - vec2(0.0100386, 1.53125), - vec2(0.00317394, 2.0)); -#endif //USE_17_SAMPLES - -#ifdef USE_11_SAMPLES -const int kernel_size = 11; -QUALIFIER vec2 kernel[11] = vec2[]( - vec2(0.560479, 0.0), - vec2(0.00471691, -2.0), - vec2(0.0192831, -1.28), - vec2(0.03639, -0.72), - vec2(0.0821904, -0.32), - vec2(0.0771802, -0.08), - vec2(0.0771802, 0.08), - vec2(0.0821904, 0.32), - vec2(0.03639, 0.72), - vec2(0.0192831, 1.28), - vec2(0.00471691, 2.0)); -#endif //USE_11_SAMPLES - -uniform float max_radius; -uniform float camera_z_far; -uniform float camera_z_near; -uniform float unit_size; -uniform vec2 dir; -in vec2 uv_interp; - -uniform sampler2D source_diffuse; //texunit:0 -uniform sampler2D source_sss; //texunit:1 -uniform sampler2D source_depth; //texunit:2 - -layout(location = 0) out vec4 frag_color; - -void main() { - float strength = texture(source_sss, uv_interp).r; - strength *= strength; //stored as sqrt - - // Fetch color of current pixel: - vec4 base_color = texture(source_diffuse, uv_interp); - - if (strength > 0.0) { - // Fetch linear depth of current pixel: - float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; - float scale = unit_size; //remember depth is negative by default in OpenGL -#else - depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); - float scale = unit_size / depth; //remember depth is negative by default in OpenGL -#endif - - // Calculate the final step to fetch the surrounding pixels: - vec2 step = max_radius * scale * dir; - step *= strength; // Modulate it using the alpha channel. - step *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3. - - // Accumulate the center sample: - vec3 color_accum = base_color.rgb; - color_accum *= kernel[0].x; -#ifdef ENABLE_STRENGTH_WEIGHTING - float color_weight = kernel[0].x; -#endif - - // Accumulate the other samples: - for (int i = 1; i < kernel_size; i++) { - // Fetch color and depth for current sample: - vec2 offset = uv_interp + kernel[i].y * step; - vec3 color = texture(source_diffuse, offset).rgb; - -#ifdef ENABLE_FOLLOW_SURFACE - // If the difference in depth is huge, we lerp color back to "colorM": - float depth_cmp = texture(source_depth, offset).r * 2.0 - 1.0; - -#ifdef USE_ORTHOGONAL_PROJECTION - depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; -#else - depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near)); -#endif - - float s = clamp(300.0f * scale * max_radius * abs(depth - depth_cmp), 0.0, 1.0); - color = mix(color, base_color.rgb, s); -#endif - - // Accumulate: - color *= kernel[i].x; - -#ifdef ENABLE_STRENGTH_WEIGHTING - float color_s = texture(source_sss, offset).r; - color_weight += color_s * kernel[i].x; - color *= color_s; -#endif - color_accum += color; - } - -#ifdef ENABLE_STRENGTH_WEIGHTING - color_accum /= color_weight; -#endif - frag_color = vec4(color_accum, base_color.a); //keep alpha (used for SSAO) - } else { - frag_color = base_color; - } -} diff --git a/drivers/gles2/shaders/tonemap.glsl b/drivers/gles2/shaders/tonemap.glsl deleted file mode 100644 index 0117bdb3d3..0000000000 --- a/drivers/gles2/shaders/tonemap.glsl +++ /dev/null @@ -1,343 +0,0 @@ -/* clang-format off */ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif - -attribute vec2 vertex_attrib; // attrib:0 -/* clang-format on */ -attribute vec2 uv_in; // attrib:4 - -varying vec2 uv_interp; - -void main() { - gl_Position = vec4(vertex_attrib, 0.0, 1.0); - - uv_interp = uv_in; -} - -/* clang-format off */ -[fragment] - -// texture2DLodEXT and textureCubeLodEXT are fragment shader specific. -// Do not copy these defines in the vertex section. -#ifndef USE_GLES_OVER_GL -#ifdef GL_EXT_shader_texture_lod -#extension GL_EXT_shader_texture_lod : enable -#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) -#endif -#endif // !USE_GLES_OVER_GL - -#ifdef GL_ARB_shader_texture_lod -#extension GL_ARB_shader_texture_lod : enable -#endif - -#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) -#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) -#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) -#endif - -// Allows the use of bitshift operators for bicubic upscale -#ifdef GL_EXT_gpu_shader4 -#extension GL_EXT_gpu_shader4 : enable -#endif - -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -#if defined(USE_HIGHP_PRECISION) -precision highp float; -precision highp int; -#else -precision mediump float; -precision mediump int; -#endif -#endif - -#include "stdlib.glsl" - -varying vec2 uv_interp; -/* clang-format on */ - -uniform highp sampler2D source; //texunit:0 - -#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7) -#define USING_GLOW // only use glow when at least one glow level is selected - -#ifdef USE_MULTI_TEXTURE_GLOW -uniform highp sampler2D source_glow1; //texunit:2 -uniform highp sampler2D source_glow2; //texunit:3 -uniform highp sampler2D source_glow3; //texunit:4 -uniform highp sampler2D source_glow4; //texunit:5 -uniform highp sampler2D source_glow5; //texunit:6 -uniform highp sampler2D source_glow6; //texunit:7 -#ifdef USE_GLOW_LEVEL7 -uniform highp sampler2D source_glow7; //texunit:8 -#endif -#else -uniform highp sampler2D source_glow; //texunit:2 -#endif -uniform highp float glow_intensity; -#endif - -#ifdef USE_BCS -uniform vec3 bcs; -#endif - -#ifdef USE_FXAA -uniform vec2 pixel_size; -#endif - -#ifdef USE_COLOR_CORRECTION -uniform sampler2D color_correction; //texunit:1 -#endif - -#ifdef GL_EXT_gpu_shader4 -#ifdef USE_GLOW_FILTER_BICUBIC -// w0, w1, w2, and w3 are the four cubic B-spline basis functions -float w0(float a) { - return (1.0 / 6.0) * (a * (a * (-a + 3.0) - 3.0) + 1.0); -} - -float w1(float a) { - return (1.0 / 6.0) * (a * a * (3.0 * a - 6.0) + 4.0); -} - -float w2(float a) { - return (1.0 / 6.0) * (a * (a * (-3.0 * a + 3.0) + 3.0) + 1.0); -} - -float w3(float a) { - return (1.0 / 6.0) * (a * a * a); -} - -// g0 and g1 are the two amplitude functions -float g0(float a) { - return w0(a) + w1(a); -} - -float g1(float a) { - return w2(a) + w3(a); -} - -// h0 and h1 are the two offset functions -float h0(float a) { - return -1.0 + w1(a) / (w0(a) + w1(a)); -} - -float h1(float a) { - return 1.0 + w3(a) / (w2(a) + w3(a)); -} - -uniform ivec2 glow_texture_size; - -vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { - float lod = float(p_lod); - vec2 tex_size = vec2(glow_texture_size >> p_lod); - vec2 texel_size = vec2(1.0) / tex_size; - - uv = uv * tex_size + vec2(0.5); - - vec2 iuv = floor(uv); - vec2 fuv = fract(uv); - - float g0x = g0(fuv.x); - float g1x = g1(fuv.x); - float h0x = h0(fuv.x); - float h1x = h1(fuv.x); - float h0y = h0(fuv.y); - float h1y = h1(fuv.y); - - vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5)) * texel_size; - vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5)) * texel_size; - vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5)) * texel_size; - vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5)) * texel_size; - - return (g0(fuv.y) * (g0x * texture2DLod(tex, p0, lod) + g1x * texture2DLod(tex, p1, lod))) + - (g1(fuv.y) * (g0x * texture2DLod(tex, p2, lod) + g1x * texture2DLod(tex, p3, lod))); -} - -#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) -#else //!USE_GLOW_FILTER_BICUBIC -#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2DLod(m_tex, m_uv, float(m_lod)) -#endif //USE_GLOW_FILTER_BICUBIC - -#else //!GL_EXT_gpu_shader4 -#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2DLod(m_tex, m_uv, float(m_lod)) -#endif //GL_EXT_gpu_shader4 - -vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode -#ifdef USE_GLOW_REPLACE - color = glow; -#endif - -#ifdef USE_GLOW_SCREEN - color = max((color + glow) - (color * glow), vec3(0.0)); -#endif - -#ifdef USE_GLOW_SOFTLIGHT - glow = glow * vec3(0.5) + vec3(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) && !defined(USE_GLOW_REPLACE) // no other selected -> additive - color += glow; -#endif - - return color; -} - -vec3 apply_bcs(vec3 color, vec3 bcs) { - color = mix(vec3(0.0), color, bcs.x); - color = mix(vec3(0.5), color, bcs.y); - color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, bcs.z); - - return color; -} - -vec3 apply_color_correction(vec3 color, sampler2D correction_tex) { - color.r = texture2D(correction_tex, vec2(color.r, 0.0)).r; - color.g = texture2D(correction_tex, vec2(color.g, 0.0)).g; - color.b = texture2D(correction_tex, vec2(color.b, 0.0)).b; - - return color; -} - -vec3 apply_fxaa(vec3 color, vec2 uv_interp, vec2 pixel_size) { - const float FXAA_REDUCE_MIN = (1.0 / 128.0); - const float FXAA_REDUCE_MUL = (1.0 / 8.0); - const float FXAA_SPAN_MAX = 8.0; - - vec3 rgbNW = texture2DLod(source, uv_interp + vec2(-1.0, -1.0) * pixel_size, 0.0).xyz; - vec3 rgbNE = texture2DLod(source, uv_interp + vec2(1.0, -1.0) * pixel_size, 0.0).xyz; - vec3 rgbSW = texture2DLod(source, uv_interp + vec2(-1.0, 1.0) * pixel_size, 0.0).xyz; - vec3 rgbSE = texture2DLod(source, uv_interp + vec2(1.0, 1.0) * pixel_size, 0.0).xyz; - vec3 rgbM = color; - 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 * (texture2DLod(source, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + texture2DLod(source, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz); - vec3 rgbB = rgbA * 0.5 + 0.25 * (texture2DLod(source, uv_interp + dir * -0.5, 0.0).xyz + - texture2DLod(source, uv_interp + dir * 0.5, 0.0).xyz); - - float lumaB = dot(rgbB, luma); - if ((lumaB < lumaMin) || (lumaB > lumaMax)) { - return rgbA; - } else { - return rgbB; - } -} - -void main() { - vec3 color = texture2DLod(source, uv_interp, 0.0).rgb; - -#ifdef USE_FXAA - color = apply_fxaa(color, uv_interp, pixel_size); -#endif - - // Glow - -#ifdef USING_GLOW - vec3 glow = vec3(0.0); -#ifdef USE_MULTI_TEXTURE_GLOW -#ifdef USE_GLOW_LEVEL1 - glow += GLOW_TEXTURE_SAMPLE(source_glow1, uv_interp, 0).rgb; -#ifdef USE_GLOW_LEVEL2 - glow += GLOW_TEXTURE_SAMPLE(source_glow2, uv_interp, 0).rgb; -#ifdef USE_GLOW_LEVEL3 - glow += GLOW_TEXTURE_SAMPLE(source_glow3, uv_interp, 0).rgb; -#ifdef USE_GLOW_LEVEL4 - glow += GLOW_TEXTURE_SAMPLE(source_glow4, uv_interp, 0).rgb; -#ifdef USE_GLOW_LEVEL5 - glow += GLOW_TEXTURE_SAMPLE(source_glow5, uv_interp, 0).rgb; -#ifdef USE_GLOW_LEVEL6 - glow += GLOW_TEXTURE_SAMPLE(source_glow6, uv_interp, 0).rgb; -#ifdef USE_GLOW_LEVEL7 - glow += GLOW_TEXTURE_SAMPLE(source_glow7, uv_interp, 0).rgb; -#endif -#endif -#endif -#endif -#endif -#endif -#endif - -#else - -#ifdef USE_GLOW_LEVEL1 - glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 1).rgb; -#endif - -#ifdef USE_GLOW_LEVEL2 - glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 2).rgb; -#endif - -#ifdef USE_GLOW_LEVEL3 - glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 3).rgb; -#endif - -#ifdef USE_GLOW_LEVEL4 - glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 4).rgb; -#endif - -#ifdef USE_GLOW_LEVEL5 - glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 5).rgb; -#endif - -#ifdef USE_GLOW_LEVEL6 - glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 6).rgb; -#endif - -#ifdef USE_GLOW_LEVEL7 - glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 7).rgb; -#endif -#endif //USE_MULTI_TEXTURE_GLOW - - glow *= glow_intensity; - color = apply_glow(color, glow); -#endif - - // Additional effects - -#ifdef USE_BCS - color = apply_bcs(color, bcs); -#endif - -#ifdef USE_COLOR_CORRECTION - color = apply_color_correction(color, color_correction); -#endif - - gl_FragColor = vec4(color, 1.0); -} diff --git a/drivers/gles2/texture_loader_gles2.cpp b/drivers/gles2/texture_loader_gles2.cpp deleted file mode 100644 index 3878b40c19..0000000000 --- a/drivers/gles2/texture_loader_gles2.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************/ -/* texture_loader_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "texture_loader_gles2.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/io/file_access.h" -#include "core/string/print_string.h" - -#include <string.h> - -RES ResourceFormatGLES2Texture::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { - unsigned int width = 8; - unsigned int height = 8; - - //We just use some format - Image::Format fmt = Image::FORMAT_RGB8; - int rowsize = 3 * width; - - Vector<uint8_t> dstbuff; - - dstbuff.resize(rowsize * height); - - uint8_t **row_p = memnew_arr(uint8_t *, height); - - for (unsigned int i = 0; i < height; i++) { - row_p[i] = 0; //No colors any more, I want them to turn black - } - - memdelete_arr(row_p); - - Ref<Image> img = memnew(Image(width, height, 0, fmt, dstbuff)); - - Ref<ImageTexture> texture = memnew(ImageTexture); - texture->create_from_image(img); - - if (r_error) - *r_error = OK; - - return texture; -} - -void ResourceFormatGLES2Texture::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("bmp"); - p_extensions->push_back("dds"); - p_extensions->push_back("exr"); - p_extensions->push_back("jpeg"); - p_extensions->push_back("jpg"); - p_extensions->push_back("hdr"); - p_extensions->push_back("pkm"); - p_extensions->push_back("png"); - p_extensions->push_back("pvr"); - p_extensions->push_back("svg"); - p_extensions->push_back("svgz"); - p_extensions->push_back("tga"); - p_extensions->push_back("webp"); -} - -bool ResourceFormatGLES2Texture::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "Texture2D"); -} - -String ResourceFormatGLES2Texture::get_resource_type(const String &p_path) const { - String extension = p_path.get_extension().to_lower(); - if ( - extension == "bmp" || - extension == "dds" || - extension == "exr" || - extension == "jpeg" || - extension == "jpg" || - extension == "hdr" || - extension == "pkm" || - extension == "png" || - extension == "pvr" || - extension == "svg" || - extension == "svgz" || - extension == "tga" || - extension == "webp") { - return "ImageTexture"; - } - - return ""; -} - -#endif diff --git a/drivers/gles2/texture_loader_gles2.h b/drivers/gles2/texture_loader_gles2.h deleted file mode 100644 index 4e6e3c4ce2..0000000000 --- a/drivers/gles2/texture_loader_gles2.h +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************/ -/* texture_loader_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once - -#include "drivers/gles_common/rasterizer_platforms.h" -#ifdef GLES2_BACKEND_ENABLED - -#include "core/io/resource_loader.h" -#include "scene/resources/texture.h" - -class ResourceFormatGLES2Texture : public ResourceFormatLoader { -public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; - - virtual ~ResourceFormatGLES2Texture() {} -}; - -#endif |