diff options
Diffstat (limited to 'drivers/gles3')
32 files changed, 0 insertions, 27282 deletions
diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub deleted file mode 100644 index 2471dd3739..0000000000 --- a/drivers/gles3/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/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp deleted file mode 100644 index 0117d2b89b..0000000000 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ /dev/null @@ -1,2266 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_gles3.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_gles3.h" - -#include "core/os/os.h" -#include "core/project_settings.h" -#include "rasterizer_scene_gles3.h" -#include "servers/visual/visual_server_raster.h" - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf -#endif - -static _FORCE_INLINE_ void store_transform2d(const Transform2D &p_mtx, float *p_array) { - - p_array[0] = p_mtx.elements[0][0]; - p_array[1] = p_mtx.elements[0][1]; - p_array[2] = 0; - p_array[3] = 0; - p_array[4] = p_mtx.elements[1][0]; - p_array[5] = p_mtx.elements[1][1]; - p_array[6] = 0; - p_array[7] = 0; - p_array[8] = 0; - p_array[9] = 0; - p_array[10] = 1; - p_array[11] = 0; - p_array[12] = p_mtx.elements[2][0]; - p_array[13] = p_mtx.elements[2][1]; - p_array[14] = 0; - p_array[15] = 1; -} - -static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.elements[0][0]; - p_array[1] = p_mtx.basis.elements[1][0]; - p_array[2] = p_mtx.basis.elements[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.basis.elements[0][1]; - p_array[5] = p_mtx.basis.elements[1][1]; - p_array[6] = p_mtx.basis.elements[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.basis.elements[0][2]; - p_array[9] = p_mtx.basis.elements[1][2]; - p_array[10] = p_mtx.basis.elements[2][2]; - p_array[11] = 0; - p_array[12] = p_mtx.origin.x; - p_array[13] = p_mtx.origin.y; - p_array[14] = p_mtx.origin.z; - p_array[15] = 1; -} - -static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - - p_array[i * 4 + j] = p_mtx.matrix[i][j]; - } - } -} - -RID RasterizerCanvasGLES3::light_internal_create() { - - LightInternal *li = memnew(LightInternal); - - glGenBuffers(1, &li->ubo); - glBindBuffer(GL_UNIFORM_BUFFER, li->ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInternal::UBOData), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - return light_internal_owner.make_rid(li); -} - -void RasterizerCanvasGLES3::light_internal_update(RID p_rid, Light *p_light) { - - LightInternal *li = light_internal_owner.getornull(p_rid); - ERR_FAIL_COND(!li); - - store_transform2d(p_light->light_shader_xform, li->ubo_data.light_matrix); - store_transform2d(p_light->xform_cache.affine_inverse(), li->ubo_data.local_matrix); - store_camera(p_light->shadow_matrix_cache, li->ubo_data.shadow_matrix); - - for (int i = 0; i < 4; i++) { - - li->ubo_data.color[i] = p_light->color[i] * p_light->energy; - li->ubo_data.shadow_color[i] = p_light->shadow_color[i]; - } - - li->ubo_data.light_pos[0] = p_light->light_shader_pos.x; - li->ubo_data.light_pos[1] = p_light->light_shader_pos.y; - li->ubo_data.shadowpixel_size = (1.0 / p_light->shadow_buffer_size) * (1.0 + p_light->shadow_smooth); - li->ubo_data.light_outside_alpha = p_light->mode == VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0; - li->ubo_data.light_height = p_light->height; - if (p_light->radius_cache == 0) - li->ubo_data.shadow_gradient = 0; - else - li->ubo_data.shadow_gradient = p_light->shadow_gradient_length / (p_light->radius_cache * 1.1); - - li->ubo_data.shadow_distance_mult = (p_light->radius_cache * 1.1); - - glBindBuffer(GL_UNIFORM_BUFFER, li->ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInternal::UBOData), &li->ubo_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); -} - -void RasterizerCanvasGLES3::light_internal_free(RID p_rid) { - - LightInternal *li = light_internal_owner.getornull(p_rid); - ERR_FAIL_COND(!li); - - glDeleteBuffers(1, &li->ubo); - light_internal_owner.free(p_rid); - memdelete(li); -} - -void RasterizerCanvasGLES3::canvas_begin() { - - if (storage->frame.current_rt && storage->frame.clear_request) { - // a clear request may be pending, so do it - bool transparent = storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; - - glClearColor(storage->frame.clear_request_color.r, - storage->frame.clear_request_color.g, - storage->frame.clear_request_color.b, - transparent ? storage->frame.clear_request_color.a : 1.0); - glClear(GL_COLOR_BUFFER_BIT); - storage->frame.clear_request = false; - glColorMask(1, 1, 1, transparent ? 1 : 0); - } - - reset_canvas(); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false); - - state.canvas_shader.set_custom_shader(0); - state.canvas_shader.bind(); - state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, Color(1, 1, 1, 1)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, Transform2D()); - state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D()); - if (storage->frame.current_rt) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); - } - - //state.canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,state.vp); - //state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Transform()); - //state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Transform()); - - glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_item_ubo); - glBindVertexArray(data.canvas_quad_array); - state.using_texture_rect = true; - state.using_ninepatch = false; - state.using_skeleton = false; -} - -void RasterizerCanvasGLES3::canvas_end() { - - glBindVertexArray(0); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0); - glColorMask(1, 1, 1, 1); - - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - - state.using_texture_rect = false; - state.using_ninepatch = false; -} - -RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force) { - - RasterizerStorageGLES3::Texture *tex_return = NULL; - - if (p_texture == state.current_tex && !p_force) { - tex_return = state.current_tex_ptr; - } else if (p_texture.is_valid()) { - - RasterizerStorageGLES3::Texture *texture = storage->texture_owner.getornull(p_texture); - - if (!texture) { - state.current_tex = RID(); - state.current_tex_ptr = NULL; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - - } else { - - if (texture->redraw_if_visible) { //check before proxy, because this is usually used with proxies - VisualServerRaster::redraw_request(); - } - - texture = texture->get_ptr(); - - if (texture->render_target) - texture->render_target->used_in_frame = true; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - state.current_tex = p_texture; - state.current_tex_ptr = texture; - - tex_return = texture; - } - - } else { - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - state.current_tex = RID(); - state.current_tex_ptr = NULL; - } - - if (p_normal_map == state.current_normal && !p_force) { - //do none - state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid()); - - } else if (p_normal_map.is_valid()) { - - RasterizerStorageGLES3::Texture *normal_map = storage->texture_owner.getornull(p_normal_map); - - if (!normal_map) { - state.current_normal = RID(); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); - state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false); - - } else { - - if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies - VisualServerRaster::redraw_request(); - } - - normal_map = normal_map->get_ptr(); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); - state.current_normal = p_normal_map; - state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, true); - } - - } else { - - state.current_normal = RID(); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); - state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false); - } - - return tex_return; -} - -void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepatch) { - - if (state.using_texture_rect == p_enable && state.using_ninepatch == p_ninepatch) - return; - - if (p_enable) { - glBindVertexArray(data.canvas_quad_array); - - } else { - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, p_ninepatch && p_enable); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT, p_enable); - state.canvas_shader.bind(); - state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); - state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); - if (state.using_skeleton) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); - } - if (storage->frame.current_rt) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); - } - state.using_texture_rect = p_enable; - state.using_ninepatch = p_ninepatch; -} - -void RasterizerCanvasGLES3::_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 int *p_bones, const float *p_weights) { - - glBindVertexArray(data.polygon_buffer_pointer_array); - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - -#ifndef GLES_OVER_GL - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); -#endif - - uint32_t buffer_ofs = 0; - - //vertex - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Vector2) * p_vertex_count; - //color -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif - - if (p_singlecolor) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - Color m = *p_colors; - glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - } else { - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Color) * p_vertex_count; - } - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif - - if (p_uvs) { - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Vector2) * p_vertex_count; - - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif - - if (p_bones && p_weights) { - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones); - glEnableVertexAttribArray(VS::ARRAY_BONES); - //glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); - glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(int) * 4 * p_vertex_count; - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights); - glEnableVertexAttribArray(VS::ARRAY_WEIGHTS); - glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, false, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(float) * 4 * p_vertex_count; - - } else if (state.using_skeleton) { - glVertexAttribI4ui(VS::ARRAY_BONES, 0, 0, 0, 0); - glVertexAttrib4f(VS::ARRAY_WEIGHTS, 0, 0, 0, 0); - } - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif - - //bind the indices buffer. - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); -#ifndef GLES_OVER_GL - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW); -#endif - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); - - //draw the triangles. - glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0); - - storage->frame.canvas_draw_commands++; - - if (p_bones && p_weights) { - //not used so often, so disable when used - glDisableVertexAttribArray(VS::ARRAY_BONES); - glDisableVertexAttribArray(VS::ARRAY_WEIGHTS); - } - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { - - glBindVertexArray(data.polygon_buffer_pointer_array); - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - -#ifndef GLES_OVER_GL - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); -#endif - - uint32_t buffer_ofs = 0; - - //vertex - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Vector2) * p_vertex_count; - //color - - if (p_singlecolor) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - Color m = *p_colors; - glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - } else { - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Color) * p_vertex_count; - } - - if (p_uvs) { - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Vector2) * p_vertex_count; - - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - glDrawArrays(p_primitive, 0, p_vertex_count); - - storage->frame.canvas_draw_commands++; - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasGLES3::_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) { - - glBindVertexArray(data.polygon_buffer_pointer_array); - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - -#ifndef GLES_OVER_GL - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); -#endif - - uint32_t buffer_ofs = 0; - - //vertex - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Vector2) * p_vertex_count; - //color -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif - - if (p_singlecolor) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - Color m = *p_colors; - glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - } else { - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Color) * p_vertex_count; - } - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif - - if (p_uvs) { - - glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); - buffer_ofs += sizeof(Vector2) * p_vertex_count; - - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif - - //bind the indices buffer. - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); -#ifndef GLES_OVER_GL - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW); -#endif - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); - - //draw the triangles. - glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0); - - storage->frame.canvas_draw_commands++; - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) { - - static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; - - //#define GLES_USE_PRIMITIVE_BUFFER - - int version = 0; - int color_ofs = 0; - int uv_ofs = 0; - int stride = 2; - - if (p_colors) { //color - version |= 1; - color_ofs = stride; - stride += 4; - } - - if (p_uvs) { //uv - version |= 2; - uv_ofs = stride; - stride += 2; - } - - float b[(2 + 2 + 4) * 4]; - - for (int i = 0; i < p_points; i++) { - b[stride * i + 0] = p_vertices[i].x; - b[stride * i + 1] = p_vertices[i].y; - } - - if (p_colors) { - - for (int i = 0; i < p_points; i++) { - b[stride * i + color_ofs + 0] = p_colors[i].r; - b[stride * i + color_ofs + 1] = p_colors[i].g; - b[stride * i + color_ofs + 2] = p_colors[i].b; - b[stride * i + color_ofs + 3] = p_colors[i].a; - } - } - - if (p_uvs) { - - for (int i = 0; i < p_points; i++) { - b[stride * i + uv_ofs + 0] = p_uvs[i].x; - b[stride * i + uv_ofs + 1] = p_uvs[i].y; - } - } - - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); -#ifndef GLES_OVER_GL - // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData - glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); -#endif - //TODO the below call may need to be replaced with: glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), &b[0]); - glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4, &b[0]); - glBindVertexArray(data.polygon_buffer_quad_arrays[version]); - glDrawArrays(prim[p_points], 0, p_points); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - storage->frame.canvas_draw_commands++; -} - -static const GLenum gl_primitive[] = { - GL_POINTS, - GL_LINES, - GL_LINE_STRIP, - GL_LINE_LOOP, - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN -}; - -void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip) { - - int cc = p_item->commands.size(); - Item::Command **commands = p_item->commands.ptrw(); - - for (int i = 0; i < cc; i++) { - - Item::Command *c = commands[i]; - - switch (c->type) { - case Item::Command::TYPE_LINE: { - - Item::CommandLine *line = static_cast<Item::CommandLine *>(c); - _set_texture_rect_mode(false); - - _bind_canvas_texture(RID(), RID()); - - glVertexAttrib4f(VS::ARRAY_COLOR, line->color.r, line->color.g, line->color.b, line->color.a); - - 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 - //glLineWidth(line->width); - _draw_gui_primitive(2, verts, NULL, NULL); - -#ifdef GLES_OVER_GL - if (line->antialiased) - glDisable(GL_LINE_SMOOTH); -#endif - } else { - //thicker line - - 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, - }; - - //glLineWidth(line->width); - _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; - case Item::Command::TYPE_POLYLINE: { - - Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(c); - _set_texture_rect_mode(false); - - _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_RECT: { - - Item::CommandRect *rect = static_cast<Item::CommandRect *>(c); - - _set_texture_rect_mode(true); - - //set color - glVertexAttrib4f(VS::ARRAY_COLOR, rect->modulate.r, rect->modulate.g, rect->modulate.b, rect->modulate.a); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(rect->texture, rect->normal_map); - - if (texture) { - - bool untile = false; - - if (rect->flags & CANVAS_RECT_TILE && !(texture->flags & VS::TEXTURE_FLAG_REPEAT)) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - untile = true; - } - - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - Rect2 src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1); - Rect2 dst_rect = Rect2(rect->rect.position, rect->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 (rect->flags & CANVAS_RECT_FLIP_H) { - src_rect.size.x *= -1; - } - - if (rect->flags & CANVAS_RECT_FLIP_V) { - src_rect.size.y *= -1; - } - - if (rect->flags & CANVAS_RECT_TRANSPOSE) { - dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform - } - - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - - state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, rect->flags & CANVAS_RECT_CLIP_UV); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - if (untile) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - - } else { - Rect2 dst_rect = Rect2(rect->rect.position, rect->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(CanvasShaderGLES3::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - - storage->frame.canvas_draw_commands++; - - } break; - - case Item::Command::TYPE_NINEPATCH: { - - Item::CommandNinePatch *np = static_cast<Item::CommandNinePatch *>(c); - - _set_texture_rect_mode(true, true); - - glVertexAttrib4f(VS::ARRAY_COLOR, np->color.r, np->color.g, np->color.b, np->color.a); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(np->texture, np->normal_map); - - Size2 texpixel_size; - - if (!texture) { - - texpixel_size = Size2(1, 1); - - state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1)); - - } else { - - if (np->source != Rect2()) { - texpixel_size = Size2(1.0 / np->source.size.width, 1.0 / np->source.size.height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(np->source.position.x / texture->width, np->source.position.y / texture->height, np->source.size.x / texture->width, np->source.size.y / texture->height)); - } else { - texpixel_size = Size2(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1)); - } - } - - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); - state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_REPEAT_H, int(np->axis_x)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_REPEAT_V, int(np->axis_y)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_DRAW_CENTER, np->draw_center); - state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_MARGINS, Color(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM])); - state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y)); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - storage->frame.canvas_draw_commands++; - } break; - - case Item::Command::TYPE_PRIMITIVE: { - - Item::CommandPrimitive *primitive = static_cast<Item::CommandPrimitive *>(c); - _set_texture_rect_mode(false); - - ERR_CONTINUE(primitive->points.size() < 1); - - RasterizerStorageGLES3::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(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } - if (primitive->colors.size() == 1 && primitive->points.size() > 1) { - - Color col = primitive->colors[0]; - glVertexAttrib4f(VS::ARRAY_COLOR, col.r, col.g, col.b, col.a); - - } else if (primitive->colors.empty()) { - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - } - - _draw_gui_primitive(primitive->points.size(), primitive->points.ptr(), primitive->colors.ptr(), primitive->uvs.ptr()); - - } break; - case Item::Command::TYPE_POLYGON: { - - Item::CommandPolygon *polygon = static_cast<Item::CommandPolygon *>(c); - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } - - _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1, polygon->bones.ptr(), polygon->weights.ptr()); -#ifdef GLES_OVER_GL - if (polygon->antialiased) { - glEnable(GL_LINE_SMOOTH); - // FIXME: Removed during Vulkan rebase. - //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 - - } break; - case Item::Command::TYPE_MESH: { - - Item::CommandMesh *mesh = static_cast<Item::CommandMesh *>(c); - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::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(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } - - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform); - - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); - if (mesh_data) { - - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::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 - glBindVertexArray(s->array_id); - - glVertexAttrib4f(VS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a); - - if (s->index_array_len) { - 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); - } - - glBindVertexArray(0); - } - } - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); - - } break; - case Item::Command::TYPE_MULTIMESH: { - - Item::CommandMultiMesh *mmesh = static_cast<Item::CommandMultiMesh *>(c); - - RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); - - if (!multi_mesh) - break; - - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh); - - if (!mesh_data) - break; - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != VS::MULTIMESH_CUSTOM_DATA_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } - - int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); - - if (amount == -1) { - amount = multi_mesh->size; - } - - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; - // 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 - glBindVertexArray(s->instancing_array_id); - - glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer - - int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); - glVertexAttribDivisor(9, 1); - - int color_ofs; - - if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) { - glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); - glVertexAttribDivisor(10, 1); - color_ofs = 12 * 4; - } else { - glDisableVertexAttribArray(10); - glVertexAttrib4f(10, 0, 0, 1, 0); - color_ofs = 8 * 4; - } - - int custom_data_ofs = color_ofs; - - switch (multi_mesh->color_format) { - - case VS::MULTIMESH_COLOR_MAX: - case VS::MULTIMESH_COLOR_NONE: { - glDisableVertexAttribArray(11); - glVertexAttrib4f(11, 1, 1, 1, 1); - } break; - case VS::MULTIMESH_COLOR_8BIT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4; - - } break; - case VS::MULTIMESH_COLOR_FLOAT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4 * 4; - } break; - } - - switch (multi_mesh->custom_data_format) { - - case VS::MULTIMESH_CUSTOM_DATA_MAX: - case VS::MULTIMESH_CUSTOM_DATA_NONE: { - glDisableVertexAttribArray(12); - glVertexAttrib4f(12, 1, 1, 1, 1); - } break; - case VS::MULTIMESH_CUSTOM_DATA_8BIT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - - } break; - case VS::MULTIMESH_CUSTOM_DATA_FLOAT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - } break; - } - - if (s->index_array_len) { - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - } else { - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); - } - - glBindVertexArray(0); - } - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - } break; - case Item::Command::TYPE_PARTICLES: { - - Item::CommandParticles *particles_cmd = static_cast<Item::CommandParticles *>(c); - - RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles); - if (!particles) - break; - - if (particles->inactive && !particles->emitting) - break; - - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white - - VisualServerRaster::redraw_request(); - - storage->particles_request_process(particles_cmd->particles); - //enable instancing - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0)); - } - - if (!particles->use_local_coords) { - - Transform2D inv_xf; - inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y)); - inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y)); - inv_xf.set_origin(Vector2(particles->emission_transform.get_origin().x, particles->emission_transform.get_origin().y)); - inv_xf.affine_invert(); - - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf); - } - - glBindVertexArray(data.particle_quad_array); //use particle quad array - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer - - int stride = sizeof(float) * 4 * 6; - - int amount = particles->amount; - - if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) { - - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount); - } else { - //split - int split = int(Math::ceil(particles->phase * particles->amount)); - - if (amount - split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount - split); - } - - if (split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split); - } - } - - glBindVertexArray(0); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - } break; - case Item::Command::TYPE_CIRCLE: { - - _set_texture_rect_mode(false); - - Item::CommandCircle *circle = static_cast<Item::CommandCircle *>(c); - static const int numpoints = 32; - Vector2 points[numpoints + 1]; - points[numpoints] = circle->pos; - int indices[numpoints * 3]; - - for (int j = 0; j < numpoints; j++) { - - points[j] = circle->pos + Vector2(Math::sin(j * Math_PI * 2.0 / numpoints), Math::cos(j * Math_PI * 2.0 / numpoints)) * circle->radius; - indices[j * 3 + 0] = j; - indices[j * 3 + 1] = (j + 1) % numpoints; - indices[j * 3 + 2] = numpoints; - } - - _bind_canvas_texture(RID(), RID()); - _draw_polygon(indices, numpoints * 3, numpoints + 1, points, NULL, &circle->color, true, NULL, NULL); - - //_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); - //canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); - } break; - case Item::Command::TYPE_TRANSFORM: { - - Item::CommandTransform *transform = static_cast<Item::CommandTransform *>(c); - state.extra_matrix = transform->xform; - state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); - - } break; - case Item::Command::TYPE_CLIP_IGNORE: { - - Item::CommandClipIgnore *ci = static_cast<Item::CommandClipIgnore *>(c); - if (current_clip) { - - if (ci->ignore != reclip) { - if (ci->ignore) { - - glDisable(GL_SCISSOR_TEST); - reclip = true; - } else { - - glEnable(GL_SCISSOR_TEST); - //glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), - //current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); - int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) - y = current_clip->final_clip_rect.position.y; - - glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y); - - reclip = false; - } - } - } - - } break; - } - } -} - -void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) { - - ERR_FAIL_COND_MSG(storage->frame.current_rt->effects.mip_maps[0].sizes.size() == 0, "Can't use screen texture copying in a render target configured without copy buffers."); - - glDisable(GL_BLEND); - - state.canvas_texscreen_used = true; - //blur diffuse into effect mipmaps using separatable convolution - //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); - - Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); - - Color blur_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()) { - - scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, true); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, true); - } - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - - storage->shaders.copy.bind(); - storage->shaders.copy.set_uniform(CopyShaderGLES3::COPY_SECTION, blur_section); - - scene_render->_copy_screen(); - - for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) { - - int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; - int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; - glViewport(0, 0, vp_w, vp_h); - //horizontal pass - scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true); - scene_render->state.effect_blur_shader.bind(); - scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); - - scene_render->_copy_screen(); - - scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false); - - //vertical pass - scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true); - scene_render->state.effect_blur_shader.bind(); - scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger - - scene_render->_copy_screen(); - - scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false); - } - - scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, false); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - - // back to canvas, force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - _bind_canvas_texture(state.current_tex, state.current_normal, true); - - glEnable(GL_BLEND); -} - -void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform) { - - Item *current_clip = NULL; - RasterizerStorageGLES3::Shader *shader_cache = NULL; - - bool rebind_shader = true; - - glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - state.current_tex = RID(); - state.current_tex_ptr = NULL; - state.current_normal = RID(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - - int last_blend_mode = -1; - - RID canvas_last_material; - - bool prev_distance_field = false; - bool prev_use_skeleton = false; - - while (p_item_list) { - - Item *ci = p_item_list; - - if (prev_distance_field != ci->distance_field) { - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, ci->distance_field); - prev_distance_field = ci->distance_field; - rebind_shader = true; - } - - if (current_clip != ci->final_clip_owner) { - - current_clip = ci->final_clip_owner; - - //setup clip - if (current_clip) { - - glEnable(GL_SCISSOR_TEST); - int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) - y = current_clip->final_clip_rect.position.y; - - glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y); - - } else { - - glDisable(GL_SCISSOR_TEST); - } - } - - if (ci->copy_back_buffer) { - - if (ci->copy_back_buffer->full) { - - _copy_texscreen(Rect2()); - } else { - _copy_texscreen(ci->copy_back_buffer->rect); - } - } - - RasterizerStorageGLES3::Skeleton *skeleton = NULL; - - { - //skeleton handling - if (ci->skeleton.is_valid() && storage->skeleton_owner.owns(ci->skeleton)) { - skeleton = storage->skeleton_owner.getornull(ci->skeleton); - if (!skeleton->use_2d) { - skeleton = NULL; - } else { - state.skeleton_transform = p_transform * skeleton->base_transform_2d; - state.skeleton_transform_inverse = state.skeleton_transform.affine_inverse(); - } - } - - bool use_skeleton = skeleton != NULL; - if (prev_use_skeleton != use_skeleton) { - rebind_shader = true; - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, use_skeleton); - prev_use_skeleton = use_skeleton; - } - - if (skeleton) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, skeleton->texture); - state.using_skeleton = true; - } else { - state.using_skeleton = false; - } - } - - //begin rect - Item *material_owner = ci->material_owner ? ci->material_owner : ci; - - RID material = material_owner->material; - - if (material != canvas_last_material || rebind_shader) { - - RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.getornull(material); - RasterizerStorageGLES3::Shader *shader_ptr = NULL; - - if (material_ptr) { - - shader_ptr = material_ptr->shader; - - if (shader_ptr && shader_ptr->mode != VS::SHADER_CANVAS_ITEM) { - shader_ptr = NULL; //do not use non canvasitem shader - } - } - - if (shader_ptr) { - - if (shader_ptr->canvas_item.uses_screen_texture && !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 != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; - } - - if (shader_ptr != shader_cache || rebind_shader) { - - 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(); - } - - if (material_ptr->ubo_id) { - glBindBufferBase(GL_UNIFORM_BUFFER, 2, material_ptr->ubo_id); - } - - int tc = material_ptr->textures.size(); - 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_TEXTURE2 + i); - - RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]); - 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; - } - - //check hints - - continue; - } - - if (t->redraw_if_visible) { //check before proxy, because this is usually used with proxies - VisualServerRaster::redraw_request(); - } - - t = t->get_ptr(); - - if (storage->config.srgb_decode_supported && t->using_srgb) { - //no srgb in 2D - glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); - t->using_srgb = false; - } - - glBindTexture(t->target, t->tex_id); - } - - } else { - state.canvas_shader.set_custom_shader(0); - state.canvas_shader.bind(); - } - - shader_cache = shader_ptr; - - canvas_last_material = material; - rebind_shader = false; - } - - int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; - if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) { - blend_mode = RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; - } - bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || (blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX && blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA)); - bool reclip = false; - - if (last_blend_mode != blend_mode) { - if (last_blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) { - // re-enable it - glEnable(GL_BLEND); - } else if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) { - // disable it - glDisable(GL_BLEND); - } - - switch (blend_mode) { - - case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED: { - - // nothing to do here - - } break; - case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: { - - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - } - - } break; - case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: { - - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::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 RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: { - - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::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 RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::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 RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::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; - } - - last_blend_mode = blend_mode; - } - - 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.final_transform = ci->final_transform; - state.extra_matrix = Transform2D(); - - if (state.using_skeleton) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); - } - - state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); - state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); - if (storage->frame.current_rt) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); - } - if (unshaded || (state.canvas_item_modulate.a > 0.001 && (!shader_cache || shader_cache->canvas_item.light_mode != RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked)) - _canvas_item_render_commands(ci, current_clip, reclip); - - if ((blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) { - - Light *light = p_light; - bool light_used = false; - VS::CanvasLightMode mode = VS::CANVAS_LIGHT_MODE_ADD; - state.canvas_item_modulate = ci->final_modulate; // remove the canvas modulate - - while (light) { - - if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { - - //intersects this light - - if (!light_used || mode != light->mode) { - - mode = light->mode; - - switch (mode) { - - case VS::CANVAS_LIGHT_MODE_ADD: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - - } break; - case VS::CANVAS_LIGHT_MODE_SUB: { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case VS::CANVAS_LIGHT_MODE_MIX: - case VS::CANVAS_LIGHT_MODE_MASK: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - } break; - } - } - - if (!light_used) { - - state.canvas_shader.set_conditional(CanvasShaderGLES3::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(CanvasShaderGLES3::USE_SHADOWS, has_shadow); - if (has_shadow) { - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF3); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF5); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF7); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF9); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF13); - } - - bool light_rebind = state.canvas_shader.bind(); - - if (light_rebind) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); - state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D()); - if (storage->frame.current_rt) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); - } - if (state.using_skeleton) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); - } - } - - LightInternal *light_internal = light_internal_owner.getornull(light->light_internal); - - glBindBufferBase(GL_UNIFORM_BUFFER, 1, light_internal->ubo); - - if (has_shadow) { - - RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.getornull(light->shadow_buffer); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); - glBindTexture(GL_TEXTURE_2D, cls->distance); - - /*canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_MATRIX,light->shadow_matrix_cache); - canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); - canvas_shader.set_uniform(CanvasShaderGLES3::LIGHT_SHADOW_COLOR,light->shadow_color);*/ - } - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(light->texture); - if (!t) { - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - } else { - t = t->get_ptr(); - - glBindTexture(t->target, t->tex_id); - } - - glActiveTexture(GL_TEXTURE0); - _canvas_item_render_commands(ci, current_clip, reclip); //redraw using light - } - - light = light->next_ptr; - } - - if (light_used) { - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false); - - state.canvas_shader.bind(); - - last_blend_mode = -1; - - /* - //this is set again, so it should not be needed anyway? - state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( - ci->final_modulate.r * p_modulate.r, - ci->final_modulate.g * p_modulate.g, - ci->final_modulate.b * p_modulate.b, - ci->final_modulate.a * p_modulate.a ); - - - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform); - state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Transform2D()); - state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate); - - glBlendEquation(GL_FUNC_ADD); - - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - //@TODO RESET canvas_blend_mode - */ - } - } - - if (reclip) { - - glEnable(GL_SCISSOR_TEST); - int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) - y = current_clip->final_clip_rect.position.y; - glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.width, current_clip->final_clip_rect.size.height); - } - - p_item_list = p_item_list->next; - } - - if (current_clip) { - glDisable(GL_SCISSOR_TEST); - } - //disable states that may have been used - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false); -} - -void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { - - Light *light = p_lights_with_shadow; - - canvas_begin(); //reset - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - int h = 10; - int w = storage->frame.current_rt->width; - int ofs = h; - glDisable(GL_BLEND); - - while (light) { - if (light->shadow_buffer.is_valid()) { - - RasterizerStorageGLES3::CanvasLightShadow *sb = storage->canvas_light_shadow_owner.getornull(light->shadow_buffer); - if (sb) { - glBindTexture(GL_TEXTURE_2D, sb->distance); - draw_generic_textured_rect(Rect2(h, ofs, w - h * 2, h), Rect2(0, 0, 1, 1)); - ofs += h * 2; - } - } - - light = light->shadows_next_ptr; - } - - canvas_end(); -} - -void RasterizerCanvasGLES3::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) { - - RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.getornull(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.bind(); - - glViewport(0, 0, cls->size, cls->height); - glClearDepth(1.0f); - glClearColor(1, 1, 1, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - VS::CanvasOccluderPolygonCullMode cull = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; - - for (int i = 0; i < 4; i++) { - - //make sure it remains orthogonal, makes easy to read angle later - - Transform light; - light.origin[0] = p_light_xform[2][0]; - light.origin[1] = p_light_xform[2][1]; - light.basis[0][0] = p_light_xform[0][0]; - light.basis[0][1] = p_light_xform[1][0]; - light.basis[1][0] = p_light_xform[0][1]; - light.basis[1][1] = p_light_xform[1][1]; - - //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); - - //p_near=1; - CameraMatrix projection; - { - real_t fov = 90; - real_t nearp = p_near; - real_t farp = p_far; - real_t aspect = 1.0; - - real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5)); - real_t ymin = -ymax; - real_t xmin = ymin * aspect; - real_t xmax = ymax * aspect; - - projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); - } - - Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * (i / 4.0))).xform(Vector3(0, 1, 0)); - projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); - - state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::PROJECTION_MATRIX, projection); - state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::LIGHT_MATRIX, light); - state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::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) { - - RasterizerStorageGLES3::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(CanvasShadowShaderGLES3::WORLD_MATRIX, instance->xform_cache); - - VS::CanvasOccluderPolygonCullMode transformed_cull_cache = instance->cull_cache; - - if (transformed_cull_cache != VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED && - (p_light_xform.basis_determinant() * instance->xform_cache.basis_determinant()) < 0) { - transformed_cull_cache = - transformed_cull_cache == VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE ? - VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE : - VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE; - } - - if (cull != transformed_cull_cache) { - - cull = transformed_cull_cache; - switch (cull) { - case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { - - glDisable(GL_CULL_FACE); - - } break; - case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { - - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); - } break; - case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { - - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - } break; - } - } - - glBindVertexArray(cc->array_id); - glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, 0); - - instance = instance->next; - } - } - - glBindVertexArray(0); -} -void RasterizerCanvasGLES3::reset_canvas() { - - if (storage->frame.current_rt) { - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); - glColorMask(1, 1, 1, 1); //don't touch alpha - } - - glBindVertexArray(0); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DITHER); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); - //glLineWidth(1.0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - //use for reading from screen - if (storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING]) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - - Transform canvas_transform; - - if (storage->frame.current_rt) { - - float csy = 1.0; - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::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 { - Vector2 ssize = OS::get_singleton()->get_window_size(); - 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.vp = canvas_transform; - - store_transform(canvas_transform, state.canvas_item_ubo_data.projection_matrix); - state.canvas_item_ubo_data.time = storage->frame.time[0]; - - glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - state.canvas_texscreen_used = false; -} - -void RasterizerCanvasGLES3::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) { - - state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -} - -void RasterizerCanvasGLES3::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 *= 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(LensDistortedShaderGLES3::OFFSET, offset); - state.lens_shader.set_uniform(LensDistortedShaderGLES3::SCALE, scale); - state.lens_shader.set_uniform(LensDistortedShaderGLES3::K1, p_k1); - state.lens_shader.set_uniform(LensDistortedShaderGLES3::K2, p_k2); - state.lens_shader.set_uniform(LensDistortedShaderGLES3::EYE_CENTER, p_eye_center); - state.lens_shader.set_uniform(LensDistortedShaderGLES3::UPSCALE, p_oversample); - state.lens_shader.set_uniform(LensDistortedShaderGLES3::ASPECT_RATIO, aspect_ratio); - - glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_item_ubo); - glBindVertexArray(data.canvas_quad_array); - - // and draw - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBindVertexArray(0); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0); -} - -void RasterizerCanvasGLES3::draw_window_margins(int *black_margin, RID *black_image) { - - Vector2 window_size = OS::get_singleton()->get_window_size(); - int window_h = window_size.height; - int window_w = window_size.width; - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - glViewport(0, 0, window_size.width, window_size.height); - canvas_begin(); - - if (black_image[MARGIN_LEFT].is_valid()) { - _bind_canvas_texture(black_image[MARGIN_LEFT], RID()); - Size2 sz(storage->texture_get_width(black_image[MARGIN_LEFT]), storage->texture_get_height(black_image[MARGIN_LEFT])); - draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, sz.x, sz.y)); - } else if (black_margin[MARGIN_LEFT]) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, 1, 1)); - } - - if (black_image[MARGIN_RIGHT].is_valid()) { - _bind_canvas_texture(black_image[MARGIN_RIGHT], RID()); - Size2 sz(storage->texture_get_width(black_image[MARGIN_RIGHT]), storage->texture_get_height(black_image[MARGIN_RIGHT])); - draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, sz.x, sz.y)); - } else if (black_margin[MARGIN_RIGHT]) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, 1, 1)); - } - - if (black_image[MARGIN_TOP].is_valid()) { - _bind_canvas_texture(black_image[MARGIN_TOP], RID()); - - Size2 sz(storage->texture_get_width(black_image[MARGIN_TOP]), storage->texture_get_height(black_image[MARGIN_TOP])); - draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[MARGIN_TOP]), Rect2(0, 0, sz.x, sz.y)); - - } else if (black_margin[MARGIN_TOP]) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[MARGIN_TOP]), Rect2(0, 0, 1, 1)); - } - - if (black_image[MARGIN_BOTTOM].is_valid()) { - - _bind_canvas_texture(black_image[MARGIN_BOTTOM], RID()); - - Size2 sz(storage->texture_get_width(black_image[MARGIN_BOTTOM]), storage->texture_get_height(black_image[MARGIN_BOTTOM])); - draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, sz.x, sz.y)); - - } else if (black_margin[MARGIN_BOTTOM]) { - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); - - draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, 1, 1)); - } -} - -void RasterizerCanvasGLES3::initialize() { - - { - //quad buffers - - 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); //unbind - - glGenVertexArrays(1, &data.canvas_quad_array); - glBindVertexArray(data.canvas_quad_array); - glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); - glEnableVertexAttribArray(0); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - } - { - //particle quad buffers - - glGenBuffers(1, &data.particle_quad_vertices); - glBindBuffer(GL_ARRAY_BUFFER, data.particle_quad_vertices); - { - //quad of size 1, with pivot on the center for particles, then regular UVS. Color is general plus fetched from particle - const float qv[16] = { - -0.5, -0.5, - 0.0, 0.0, - -0.5, 0.5, - 0.0, 1.0, - 0.5, 0.5, - 1.0, 1.0, - 0.5, -0.5, - 1.0, 0.0 - }; - - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - glGenVertexArrays(1, &data.particle_quad_array); - glBindVertexArray(data.particle_quad_array); - glBindBuffer(GL_ARRAY_BUFFER, data.particle_quad_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8)); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - } - { - - uint32_t poly_size = GLOBAL_DEF_RST("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 *= 1024; //kb - poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float)); - glGenBuffers(1, &data.polygon_buffer); - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW); //allocate max size - glBindBuffer(GL_ARRAY_BUFFER, 0); - data.polygon_buffer_size = poly_size; - - //quad arrays - for (int i = 0; i < 4; i++) { - glGenVertexArrays(1, &data.polygon_buffer_quad_arrays[i]); - glBindVertexArray(data.polygon_buffer_quad_arrays[i]); - glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); - - int uv_ofs = 0; - int color_ofs = 0; - int stride = 2 * 4; - - if (i & 1) { //color - color_ofs = stride; - stride += 4 * 4; - } - - if (i & 2) { //uv - uv_ofs = stride; - stride += 2 * 4; - } - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride, NULL); - - if (i & 1) { - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - } - - if (i & 2) { - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(uv_ofs)); - } - - glBindVertexArray(0); - } - - glGenVertexArrays(1, &data.polygon_buffer_pointer_array); - - uint32_t index_size = GLOBAL_DEF_RST("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 *= 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); //allocate max size - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - data.polygon_index_buffer_size = index_size; - } - - store_transform(Transform(), state.canvas_item_ubo_data.projection_matrix); - - glGenBuffers(1, &state.canvas_item_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - state.canvas_shader.init(); - state.canvas_shader.set_base_material_tex_index(2); - state.canvas_shadow_shader.init(); - state.lens_shader.init(); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); - state.canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false)); -} - -void RasterizerCanvasGLES3::finalize() { - - glDeleteBuffers(1, &data.canvas_quad_vertices); - glDeleteVertexArrays(1, &data.canvas_quad_array); - - glDeleteBuffers(1, &data.canvas_quad_vertices); - glDeleteVertexArrays(1, &data.canvas_quad_array); - - glDeleteVertexArrays(1, &data.polygon_buffer_pointer_array); -} - -RasterizerCanvasGLES3::RasterizerCanvasGLES3() { -} diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h deleted file mode 100644 index 8e7a3ae873..0000000000 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ /dev/null @@ -1,158 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_gles3.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. */ -/*************************************************************************/ - -#ifndef RASTERIZERCANVASGLES3_H -#define RASTERIZERCANVASGLES3_H - -#include "rasterizer_storage_gles3.h" -#include "servers/visual/rasterizer.h" - -#include "shaders/canvas_shadow.glsl.gen.h" -#include "shaders/lens_distorted.glsl.gen.h" - -class RasterizerSceneGLES3; - -class RasterizerCanvasGLES3 : public RasterizerCanvas { -public: - struct CanvasItemUBO { - - float projection_matrix[16]; - float time; - uint8_t padding[12]; - }; - - RasterizerSceneGLES3 *scene_render; - - struct Data { - - GLuint canvas_quad_vertices; - GLuint canvas_quad_array; - - GLuint polygon_buffer; - GLuint polygon_buffer_quad_arrays[4]; - GLuint polygon_buffer_pointer_array; - GLuint polygon_index_buffer; - - GLuint particle_quad_vertices; - GLuint particle_quad_array; - - uint32_t polygon_buffer_size; - uint32_t polygon_index_buffer_size; - - } data; - - struct State { - CanvasItemUBO canvas_item_ubo_data; - GLuint canvas_item_ubo; - bool canvas_texscreen_used; - CanvasShaderGLES3 canvas_shader; - CanvasShadowShaderGLES3 canvas_shadow_shader; - LensDistortedShaderGLES3 lens_shader; - - bool using_texture_rect; - bool using_ninepatch; - - RID current_tex; - RID current_normal; - RasterizerStorageGLES3::Texture *current_tex_ptr; - - Transform vp; - - Color canvas_item_modulate; - Transform2D extra_matrix; - Transform2D final_transform; - bool using_skeleton; - Transform2D skeleton_transform; - Transform2D skeleton_transform_inverse; - - } state; - - RasterizerStorageGLES3 *storage; - - struct LightInternal { - - struct UBOData { - - float light_matrix[16]; - float local_matrix[16]; - float shadow_matrix[16]; - float color[4]; - float shadow_color[4]; - float light_pos[2]; - float shadowpixel_size; - float shadow_gradient; - float light_height; - float light_outside_alpha; - float shadow_distance_mult; - uint8_t padding[4]; - } ubo_data; - - GLuint ubo; - }; - - RID_PtrOwner<LightInternal> light_internal_owner; - - 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(); - - _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false); - _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force = false); - - _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); - _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights); - _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); - _FORCE_INLINE_ void _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); - - _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip); - _FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect); - - virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform); - virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow); - - 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 reset_canvas(); - - 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); - - void initialize(); - void finalize(); - - virtual void draw_window_margins(int *black_margin, RID *black_image); - - RasterizerCanvasGLES3(); -}; - -#endif // RASTERIZERCANVASGLES3_H diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp deleted file mode 100644 index ef6f2854bc..0000000000 --- a/drivers/gles3/rasterizer_gles3.cpp +++ /dev/null @@ -1,444 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles3.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_gles3.h" - -#include "core/os/os.h" -#include "core/project_settings.h" - -RasterizerStorage *RasterizerGLES3::get_storage() { - - return storage; -} - -RasterizerCanvas *RasterizerGLES3::get_canvas() { - - return canvas; -} - -RasterizerScene *RasterizerGLES3::get_scene() { - - return scene; -} - -#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 - -#if defined(MINGW_ENABLED) || defined(_MSC_VER) -#define strcpy strcpy_s -#endif - -#ifdef GLAD_ENABLED -// Restricting to GLAD as only used in initialize() with GLAD_GL_ARB_debug_output -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"); - - 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 // GLAD_ENABLED - -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); - -Error RasterizerGLES3::is_viable() { - -#ifdef GLAD_ENABLED - if (!gladLoadGL()) { - ERR_PRINT("Error initializing GLAD"); - return ERR_UNAVAILABLE; - } - -// GLVersion seems to be used for both GL and GL ES, so we need different version checks for them -#ifdef OPENGL_ENABLED // OpenGL 3.3 Core Profile required - if (GLVersion.major < 3 || (GLVersion.major == 3 && GLVersion.minor < 3)) { -#else // OpenGL ES 3.0 - if (GLVersion.major < 3) { -#endif - return ERR_UNAVAILABLE; - } - -#endif // GLAD_ENABLED - return OK; -} - -void RasterizerGLES3::initialize() { - - print_verbose("Using GLES3 video driver"); - -#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 - if (GLAD_GL_ARB_debug_output) { - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PORTABILITY_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PERFORMANCE_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_OTHER_ARB,GL_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"); - } - */ - - print_line("OpenGL ES 3.0 Renderer: " + VisualServer::get_singleton()->get_video_adapter_name()); - storage->initialize(); - canvas->initialize(); - scene->initialize(); -} - -void RasterizerGLES3::begin_frame(double frame_step) { - - time_total += frame_step; - - if (frame_step == 0) { - //to avoid hiccups - frame_step = 0.001; - } - - double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs"); - if (time_total > time_roll_over) - time_total = 0; //roll over every day (should be customz - - 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 RasterizerGLES3::set_current_render_target(RID p_render_target) { - - if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { - //handle pending clear request, if the framebuffer was not cleared - 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 (p_render_target.is_valid()) { - RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); - storage->frame.current_rt = rt; - ERR_FAIL_COND(!rt); - storage->frame.clear_request = false; - - glViewport(0, 0, rt->width, rt->height); - - } else { - storage->frame.current_rt = NULL; - storage->frame.clear_request = false; - glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - } -} - -void RasterizerGLES3::restore_render_target(bool p_3d_was_drawn) { - - ERR_FAIL_COND(storage->frame.current_rt == NULL); - RasterizerStorageGLES3::RenderTarget *rt = storage->frame.current_rt; - if (p_3d_was_drawn && rt->external.fbo != 0) { - // our external render buffer is now leading, render 2d into that. - glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); - } - glViewport(0, 0, rt->width, rt->height); -} - -void RasterizerGLES3::clear_render_target(const Color &p_color) { - - ERR_FAIL_COND(!storage->frame.current_rt); - - storage->frame.clear_request = true; - storage->frame.clear_request_color = p_color; -} - -void RasterizerGLES3::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->empty()) - return; - - begin_frame(0.0); - - int window_w = OS::get_singleton()->get_video_mode(0).width; - int window_h = OS::get_singleton()->get_video_mode(0).height; - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - glViewport(0, 0, window_w, window_h); - glDisable(GL_BLEND); - glDepthMask(GL_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_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(); - } - - RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(texture); - glActiveTexture(GL_TEXTURE0); - 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); // free since it's only one frame that stays there - - end_frame(true); -} - -void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen) { - - ERR_FAIL_COND(storage->frame.current_rt); - - RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - Size2 win_size = OS::get_singleton()->get_window_size(); - if (rt->external.fbo != 0) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo); - } else { - glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo); - } - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height - p_screen_rect.position.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); -} - -void RasterizerGLES3::output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) { - ERR_FAIL_COND(storage->frame.current_rt); - - RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - glDisable(GL_BLEND); - - // render to our framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - - // output our texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, rt->color); - - canvas->draw_lens_distortion_rect(p_screen_rect, p_k1, p_k2, p_eye_center, p_oversample); - - glBindTexture(GL_TEXTURE_2D, 0); -} - -void RasterizerGLES3::end_frame(bool p_swap_buffers) { - - if (OS::get_singleton()->is_layered_allowed()) { - if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) { -#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED) - Size2 wndsize = OS::get_singleton()->get_layered_buffer_size(); - uint8_t *data = OS::get_singleton()->get_layered_buffer_data(); - if (data) { - glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data); - OS::get_singleton()->swap_layered_buffer(); - - return; - } -#endif - } else { - //clear alpha - glColorMask(false, false, false, true); - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - glColorMask(true, true, true, true); - } - } - - if (p_swap_buffers) - OS::get_singleton()->swap_buffers(); - else - glFinish(); -} - -void RasterizerGLES3::finalize() { - - storage->finalize(); - canvas->finalize(); -} - -Rasterizer *RasterizerGLES3::_create_current() { - - return memnew(RasterizerGLES3); -} - -void RasterizerGLES3::make_current() { - _create_func = _create_current; -} - -void RasterizerGLES3::register_config() { - - GLOBAL_DEF("rendering/quality/filters/anisotropic_filter_level", 4); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/anisotropic_filter_level", PropertyInfo(Variant::INT, "rendering/quality/filters/anisotropic_filter_level", PROPERTY_HINT_RANGE, "1,16,1")); - GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::REAL, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); -} - -RasterizerGLES3::RasterizerGLES3() { - - storage = memnew(RasterizerStorageGLES3); - canvas = memnew(RasterizerCanvasGLES3); - scene = memnew(RasterizerSceneGLES3); - canvas->storage = storage; - canvas->scene_render = scene; - storage->canvas = canvas; - scene->storage = storage; - storage->scene = scene; - - time_total = 0; -} - -RasterizerGLES3::~RasterizerGLES3() { - - memdelete(storage); - memdelete(canvas); - memdelete(scene); -} diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h deleted file mode 100644 index de7c1ab7e1..0000000000 --- a/drivers/gles3/rasterizer_gles3.h +++ /dev/null @@ -1,76 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles3.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. */ -/*************************************************************************/ - -#ifndef RASTERIZERGLES3_H -#define RASTERIZERGLES3_H - -#include "rasterizer_canvas_gles3.h" -#include "rasterizer_scene_gles3.h" -#include "rasterizer_storage_gles3.h" -#include "servers/visual/rasterizer.h" - -class RasterizerGLES3 : public Rasterizer { - - static Rasterizer *_create_current(); - - RasterizerStorageGLES3 *storage; - RasterizerCanvasGLES3 *canvas; - RasterizerSceneGLES3 *scene; - - double time_total; - -public: - virtual RasterizerStorage *get_storage(); - virtual RasterizerCanvas *get_canvas(); - virtual RasterizerScene *get_scene(); - - virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true); - - virtual void initialize(); - virtual void begin_frame(double frame_step); - virtual void set_current_render_target(RID p_render_target); - virtual void restore_render_target(bool p_3d_was_drawn); - virtual void clear_render_target(const Color &p_color); - virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0); - virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); - virtual void end_frame(bool p_swap_buffers); - virtual void finalize(); - - static Error is_viable(); - static void make_current(); - static void register_config(); - - virtual bool is_low_end() const { return false; } - - RasterizerGLES3(); - ~RasterizerGLES3(); -}; - -#endif // RASTERIZERGLES3_H diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp deleted file mode 100644 index ec8701af31..0000000000 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ /dev/null @@ -1,5346 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_gles3.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_scene_gles3.h" - -#include "core/math/math_funcs.h" -#include "core/os/os.h" -#include "core/project_settings.h" -#include "rasterizer_canvas_gles3.h" -#include "servers/camera/camera_feed.h" -#include "servers/visual/visual_server_raster.h" - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf -#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, - -}; - -static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.elements[0][0]; - p_array[1] = p_mtx.basis.elements[1][0]; - p_array[2] = p_mtx.basis.elements[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.basis.elements[0][1]; - p_array[5] = p_mtx.basis.elements[1][1]; - p_array[6] = p_mtx.basis.elements[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.basis.elements[0][2]; - p_array[9] = p_mtx.basis.elements[1][2]; - p_array[10] = p_mtx.basis.elements[2][2]; - p_array[11] = 0; - p_array[12] = p_mtx.origin.x; - p_array[13] = p_mtx.origin.y; - p_array[14] = p_mtx.origin.z; - p_array[15] = 1; -} - -static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - - p_array[i * 4 + j] = p_mtx.matrix[i][j]; - } - } -} - -/* SHADOW ATLAS API */ - -RID RasterizerSceneGLES3::shadow_atlas_create() { - - ShadowAtlas *shadow_atlas = memnew(ShadowAtlas); - shadow_atlas->fbo = 0; - shadow_atlas->depth = 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 RasterizerSceneGLES3::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; - - // erasing atlas - if (shadow_atlas->fbo) { - glDeleteTextures(1, &shadow_atlas->depth); - glDeleteFramebuffers(1, &shadow_atlas->fbo); - - shadow_atlas->depth = 0; - shadow_atlas->fbo = 0; - } - for (int i = 0; i < 4; i++) { - //clear subdivisions - shadow_atlas->quadrants[i].shadows.resize(0); - shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision); - } - - //erase shadow atlas reference 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); - } - - //clear owners - 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 texture for storing the depth - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &shadow_atlas->depth); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadow_atlas->size, shadow_atlas->size, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - - 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); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, shadow_atlas->depth, 0); - - glViewport(0, 0, shadow_atlas->size, shadow_atlas->size); - glClearDepth(0.0f); - glClear(GL_DEPTH_BUFFER_BIT); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } -} - -void RasterizerSceneGLES3::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)); - - //obtain the number that will be x*x - - if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) - return; - - //erase all data from 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 * subdiv); - shadow_atlas->quadrants[p_quadrant].subdivision = subdiv; - - //cache the smallest subdiv (for faster allocation in light update) - - 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; - } - - //resort the size orders, simple bublesort for 4 elements.. - - 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 RasterizerSceneGLES3::_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 existing one, must steal it - uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion) - - 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 RasterizerSceneGLES3::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; //best size found - int best_subdiv = -1; //subdiv for the best size - - //find the quadrants this fits into, and the best possible size it can fit into - 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; //unused - - int max_fit = quad_size / sd; - - if (best_size != -1 && max_fit > best_size) - break; //too large - - valid_quadrants[valid_quadrant_count++] = q; - best_subdiv = sd; - - if (max_fit >= desired_fit) { - best_size = max_fit; - } - } - - ERR_FAIL_COND_V(valid_quadrant_count == 0, false); - - uint64_t tick = OS::get_singleton()->get_ticks_msec(); - - //see if it already exists - - if (shadow_atlas->shadow_owners.has(p_light_intance)) { - //it does! - 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; - //already existing, see if it should redraw or it's just OK - return should_redraw; - } - - int new_quadrant, 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()) { - //is taken, but is invalid, erasing it - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.getornull(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 new key - key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; - //update it in map - shadow_atlas->shadow_owners[p_light_intance] = key; - //make it dirty, as it should redraw anyway - return true; - } - - //no better place for this shadow found, keep current - - //already existing, see if it should redraw or it's just OK - - shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; - - return should_redraw; - } - - int new_quadrant, new_shadow; - - //find a better place - 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()) { - //is taken, but is invalid, erasing it - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.getornull(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 new key - uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; - //update it in map - shadow_atlas->shadow_owners[p_light_intance] = key; - //make it dirty, as it should redraw anyway - - return true; - } - - //no place to allocate this light, apologies - - return false; -} - -void RasterizerSceneGLES3::set_directional_shadow_count(int p_count) { - - directional_shadow.light_count = p_count; - directional_shadow.current_light = 0; -} - -int RasterizerSceneGLES3::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 VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: - break; //none - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break; - } - - return shadow_size; -} -////////////////////////////////////////////////////// - -RID RasterizerSceneGLES3::reflection_atlas_create() { - - ReflectionAtlas *reflection_atlas = memnew(ReflectionAtlas); - reflection_atlas->subdiv = 0; - reflection_atlas->color = 0; - reflection_atlas->size = 0; - for (int i = 0; i < 6; i++) { - reflection_atlas->fbo[i] = 0; - } - - return reflection_atlas_owner.make_rid(reflection_atlas); -} - -void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_size) { - - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas); - ERR_FAIL_COND(!reflection_atlas); - - int size = next_power_of_2(p_size); - - if (size == reflection_atlas->size) - return; - if (reflection_atlas->size) { - for (int i = 0; i < 6; i++) { - glDeleteFramebuffers(1, &reflection_atlas->fbo[i]); - reflection_atlas->fbo[i] = 0; - } - glDeleteTextures(1, &reflection_atlas->color); - reflection_atlas->color = 0; - } - - reflection_atlas->size = size; - - for (int i = 0; i < reflection_atlas->reflections.size(); i++) { - //erase probes reference to this - if (reflection_atlas->reflections[i].owner.is_valid()) { - ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner); - reflection_atlas->reflections.write[i].owner = RID(); - - ERR_CONTINUE(!reflection_probe_instance); - reflection_probe_instance->reflection_atlas_index = -1; - reflection_probe_instance->atlas = RID(); - reflection_probe_instance->render_step = -1; - } - } - - if (reflection_atlas->size) { - - bool use_float = true; - - GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; - GLenum format = GL_RGBA; - GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - - // Create a texture for storing the color - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &reflection_atlas->color); - glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); - - int mmsize = reflection_atlas->size; - glTexStorage2DCustom(GL_TEXTURE_2D, 6, internal_format, mmsize, mmsize, format, type); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); - - for (int i = 0; i < 6; i++) { - glGenFramebuffers(1, &reflection_atlas->fbo[i]); - glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reflection_atlas->color, i); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); - - glDisable(GL_SCISSOR_TEST); - glViewport(0, 0, mmsize, mmsize); - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); //it needs to be cleared, to avoid generating garbage - - mmsize >>= 1; - } - } -} - -void RasterizerSceneGLES3::reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) { - - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas); - ERR_FAIL_COND(!reflection_atlas); - - int subdiv = next_power_of_2(p_subdiv); - if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer - subdiv <<= 1; - } - - subdiv = int(Math::sqrt((float)subdiv)); - - if (reflection_atlas->subdiv == subdiv) - return; - - if (subdiv) { - - for (int i = 0; i < reflection_atlas->reflections.size(); i++) { - //erase probes reference to this - if (reflection_atlas->reflections[i].owner.is_valid()) { - ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner); - reflection_atlas->reflections.write[i].owner = RID(); - - ERR_CONTINUE(!reflection_probe_instance); - reflection_probe_instance->reflection_atlas_index = -1; - reflection_probe_instance->atlas = RID(); - reflection_probe_instance->render_step = -1; - } - } - } - - reflection_atlas->subdiv = subdiv; - - reflection_atlas->reflections.resize(subdiv * subdiv); -} - -//////////////////////////////////////////////////// - -RID RasterizerSceneGLES3::reflection_probe_instance_create(RID p_probe) { - - RasterizerStorageGLES3::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; - - return rpi->self; -} - -void RasterizerSceneGLES3::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!rpi); - rpi->transform = p_transform; -} - -void RasterizerSceneGLES3::reflection_probe_release_atlas_index(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!rpi); - if (rpi->reflection_atlas_index == -1) - return; - - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(rpi->atlas); - ERR_FAIL_COND(!reflection_atlas); - - ERR_FAIL_INDEX(rpi->reflection_atlas_index, reflection_atlas->reflections.size()); - - ERR_FAIL_COND(reflection_atlas->reflections[rpi->reflection_atlas_index].owner != rpi->self); - - reflection_atlas->reflections.write[rpi->reflection_atlas_index].owner = RID(); - - rpi->reflection_atlas_index = -1; - rpi->atlas = RID(); - rpi->render_step = -1; -} - -bool RasterizerSceneGLES3::reflection_probe_instance_needs_redraw(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - return rpi->reflection_atlas_index == -1 || rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS; -} - -bool RasterizerSceneGLES3::reflection_probe_instance_has_reflection(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - return rpi->reflection_atlas_index != -1; -} - -bool RasterizerSceneGLES3::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->reflection_atlas_index != -1) { - return true; //got one already - } - - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); - ERR_FAIL_COND_V(!reflection_atlas, false); - - if (reflection_atlas->size == 0 || reflection_atlas->subdiv == 0) { - return false; - } - - int best_free = -1; - int best_used = -1; - uint64_t best_used_frame = 0; - - for (int i = 0; i < reflection_atlas->reflections.size(); i++) { - if (reflection_atlas->reflections[i].owner == RID()) { - best_free = i; - break; - } - - if (rpi->render_step < 0 && reflection_atlas->reflections[i].last_frame < storage->frame.count && - (best_used == -1 || reflection_atlas->reflections[i].last_frame < best_used_frame)) { - best_used = i; - best_used_frame = reflection_atlas->reflections[i].last_frame; - } - } - - if (best_free == -1 && best_used == -1) { - return false; // sorry, can not do. Try again next frame. - } - - if (best_free == -1) { - //find best from what is used - best_free = best_used; - - ReflectionProbeInstance *victim_rpi = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[best_free].owner); - ERR_FAIL_COND_V(!victim_rpi, false); - victim_rpi->atlas = RID(); - victim_rpi->reflection_atlas_index = -1; - } - - reflection_atlas->reflections.write[best_free].owner = p_instance; - reflection_atlas->reflections.write[best_free].last_frame = storage->frame.count; - - rpi->reflection_atlas_index = best_free; - rpi->atlas = p_reflection_atlas; - rpi->render_step = 0; - - return true; -} - -bool RasterizerSceneGLES3::reflection_probe_instance_postprocess_step(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, true); - - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(rpi->atlas); - ERR_FAIL_COND_V(!reflection_atlas, false); - - ERR_FAIL_COND_V(rpi->render_step >= 6, true); - - glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[rpi->render_step]); - state.cube_to_dp_shader.bind(); - - int target_size = reflection_atlas->size / reflection_atlas->subdiv; - - int cubemap_index = reflection_cubemaps.size() - 1; - - for (int i = reflection_cubemaps.size() - 1; i >= 0; i--) { - //find appropriate cubemap to render to - if (reflection_cubemaps[i].size > target_size * 2) - break; - - cubemap_index = i; - } - - glDisable(GL_BLEND); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, reflection_cubemaps[cubemap_index].cubemap); - glDisable(GL_CULL_FACE); - - storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); - storage->shaders.cubemap_filter.bind(); - - int cell_size = reflection_atlas->size / reflection_atlas->subdiv; - for (int i = 0; i < rpi->render_step; i++) { - cell_size >>= 1; //mipmaps! - } - int x = (rpi->reflection_atlas_index % reflection_atlas->subdiv) * cell_size; - int y = (rpi->reflection_atlas_index / reflection_atlas->subdiv) * cell_size; - int width = cell_size; - int height = cell_size; - - storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE, rpi->render_step == 0); - storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS); - for (int i = 0; i < 2; i++) { - - storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i == 0); - storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, rpi->render_step / 5.0); - - uint32_t local_width = width, local_height = height; - uint32_t local_x = x, local_y = y; - - local_height /= 2; - local_y += i * local_height; - - glViewport(local_x, local_y, local_width, local_height); - - _copy_screen(); - } - storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE, false); - storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, false); - - rpi->render_step++; - - return rpi->render_step == 6; -} - -/* ENVIRONMENT API */ - -RID RasterizerSceneGLES3::environment_create() { - - Environment *env = memnew(Environment); - - return environment_owner.make_rid(env); -} - -void RasterizerSceneGLES3::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) { - - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->bg_mode = p_bg; -} - -void RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, 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 RasterizerSceneGLES3::environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, 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 RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, 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 RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) { -} - -void RasterizerSceneGLES3::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); - - env->ssr_enabled = p_enable; - env->ssr_max_steps = p_max_steps; - env->ssr_fade_in = p_fade_in; - env->ssr_fade_out = p_fade_out; - env->ssr_depth_tolerance = p_depth_tolerance; - env->ssr_roughness = p_roughness; -} - -void RasterizerSceneGLES3::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, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { - - Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->ssao_enabled = p_enable; - env->ssao_radius = p_radius; - env->ssao_intensity = p_intensity; - env->ssao_radius2 = p_radius2; - env->ssao_intensity2 = p_intensity2; - env->ssao_bias = p_bias; - env->ssao_light_affect = p_light_affect; - env->ssao_ao_channel_affect = p_ao_channel_affect; - env->ssao_color = p_color; - env->ssao_filter = p_blur; - env->ssao_quality = p_quality; - env->ssao_bilateral_sharpness = p_bilateral_sharpness; -} - -void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, 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); - - env->tone_mapper = p_tone_mapper; - env->tone_mapper_exposure = p_exposure; - env->tone_mapper_exposure_white = p_white; - env->auto_exposure = p_auto_exposure; - env->auto_exposure_speed = p_auto_exp_speed; - env->auto_exposure_min = p_min_luminance; - env->auto_exposure_max = p_max_luminance; - env->auto_exposure_grey = p_auto_exp_scale; -} - -void RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::is_environment(RID p_env) { - - return environment_owner.owns(p_env); -} - -VS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) { - - const Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); - - return env->bg_mode; -} - -int RasterizerSceneGLES3::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 RasterizerSceneGLES3::light_instance_create(RID p_light) { - - LightInstance *light_instance = memnew(LightInstance); - - light_instance->last_pass = 0; - light_instance->last_scene_pass = 0; - light_instance->last_scene_shadow_pass = 0; - - light_instance->light = p_light; - light_instance->light_ptr = storage->light_owner.getornull(p_light); - - 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 RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) { - - LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->transform = p_transform; -} - -void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &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 != 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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::gi_probe_instance_create() { - - GIProbeInstance *gipi = memnew(GIProbeInstance); - - return gi_probe_instance_owner.make_rid(gipi); -} - -void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) { - - GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); - ERR_FAIL_COND(!gipi); - gipi->data = p_data; - gipi->probe = storage->gi_probe_owner.getornull(p_base); - if (p_data.is_valid()) { - RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data); - ERR_FAIL_COND(!gipd); - - gipi->tex_cache = gipd->tex_id; - gipi->cell_size_cache.x = 1.0 / gipd->width; - gipi->cell_size_cache.y = 1.0 / gipd->height; - gipi->cell_size_cache.z = 1.0 / gipd->depth; - } -} -void RasterizerSceneGLES3::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { - - GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); - ERR_FAIL_COND(!gipi); - gipi->transform_to_data = p_xform; -} - -void RasterizerSceneGLES3::gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) { - - GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); - ERR_FAIL_COND(!gipi); - gipi->bounds = p_bounds; -} - -//////////////////////////// -//////////////////////////// -//////////////////////////// - -bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_alpha_pass) { - - /* this is handled outside - if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_DISABLED) { - glDisable(GL_CULL_FACE); - } else { - glEnable(GL_CULL_FACE); - } */ - - if (state.current_line_width != p_material->line_width) { - //glLineWidth(MAX(p_material->line_width,1.0)); - state.current_line_width = p_material->line_width; - } - - if (state.current_depth_test != (!p_material->shader->spatial.no_depth_test)) { - if (p_material->shader->spatial.no_depth_test) { - glDisable(GL_DEPTH_TEST); - - } else { - glEnable(GL_DEPTH_TEST); - } - - state.current_depth_test = !p_material->shader->spatial.no_depth_test; - } - - if (state.current_depth_draw != p_material->shader->spatial.depth_draw_mode) { - switch (p_material->shader->spatial.depth_draw_mode) { - case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: { - glDepthMask(p_depth_pass); - // If some transparent objects write to depth, we need to re-copy depth texture when we need it - if (p_alpha_pass && !state.used_depth_prepass) { - state.prepared_depth_texture = false; - } - } break; - case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_OPAQUE: { - - glDepthMask(!p_alpha_pass); - } break; - case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALWAYS: { - glDepthMask(GL_TRUE); - // If some transparent objects write to depth, we need to re-copy depth texture when we need it - if (p_alpha_pass) { - state.prepared_depth_texture = false; - } - } break; - case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER: { - glDepthMask(GL_FALSE); - } break; - } - - state.current_depth_draw = p_material->shader->spatial.depth_draw_mode; - } - - //material parameters - - state.scene_shader.set_custom_shader(p_material->shader->custom_code_id); - bool rebind = state.scene_shader.bind(); - - if (p_material->ubo_id) { - - glBindBufferBase(GL_UNIFORM_BUFFER, 1, p_material->ubo_id); - } - - int tc = p_material->textures.size(); - RID *textures = p_material->textures.ptrw(); - ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptrw(); - const ShaderLanguage::DataType *texture_types = p_material->shader->texture_types.ptr(); - - state.current_main_tex = 0; - - for (int i = 0; i < tc; i++) { - - glActiveTexture(GL_TEXTURE0 + i); - - GLenum target = GL_TEXTURE_2D; - GLuint tex = 0; - - RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]); - - if (t) { - - if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies - VisualServerRaster::redraw_request(); - } - - t = t->get_ptr(); //resolve for proxies - -#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; - - target = t->target; - tex = t->tex_id; - } else { - - switch (texture_types[i]) { - case ShaderLanguage::TYPE_ISAMPLER2D: - case ShaderLanguage::TYPE_USAMPLER2D: - case ShaderLanguage::TYPE_SAMPLER2D: { - target = GL_TEXTURE_2D; - - switch (texture_hints[i]) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { - tex = storage->resources.black_tex; - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - tex = storage->resources.aniso_tex; - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - tex = storage->resources.normal_tex; - - } break; - default: { - tex = storage->resources.white_tex; - } break; - } - - } break; - - case ShaderLanguage::TYPE_SAMPLERCUBE: { - // TODO - } break; - - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: - case ShaderLanguage::TYPE_SAMPLER3D: { - - target = GL_TEXTURE_3D; - tex = storage->resources.white_tex_3d; - - //switch (texture_hints[i]) { - // TODO - //} - - } break; - - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: - case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - - target = GL_TEXTURE_2D_ARRAY; - tex = storage->resources.white_tex_array; - - //switch (texture_hints[i]) { - // TODO - //} - - } break; - - default: { - } - } - } - - glBindTexture(target, tex); - - if (t && storage->config.srgb_decode_supported) { - //if SRGB decode extension is present, simply switch the texture to whathever is needed - bool must_srgb = false; - - if (t->srgb && (texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) { - must_srgb = true; - } - - if (t->using_srgb != must_srgb) { - if (must_srgb) { - glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); -#ifdef TOOLS_ENABLED - if (t->detect_srgb) { - t->detect_srgb(t->detect_srgb_ud); - } -#endif - - } else { - glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); - } - t->using_srgb = must_srgb; - } - } - - if (i == 0) { - state.current_main_tex = tex; - } - } - - return rebind; -} - -struct RasterizerGLES3Particle { - - float color[4]; - float velocity_active[4]; - float custom[4]; - float xform_1[4]; - float xform_2[4]; - float xform_3[4]; -}; - -struct RasterizerGLES3ParticleSort { - - Vector3 z_dir; - bool operator()(const RasterizerGLES3Particle &p_a, const RasterizerGLES3Particle &p_b) const { - - return z_dir.dot(Vector3(p_a.xform_1[3], p_a.xform_2[3], p_a.xform_3[3])) < z_dir.dot(Vector3(p_b.xform_1[3], p_b.xform_2[3], p_b.xform_3[3])); - } -}; - -void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transform &p_view_transform) { - - switch (e->instance->base_type) { - - case VS::INSTANCE_MESH: { - - RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); - - if (s->blend_shapes.size() && e->instance->blend_values.size()) { - //blend shapes, use transform feedback - storage->mesh_render_blend_shapes(s, e->instance->blend_values.ptr()); - //rebind shader - state.scene_shader.bind(); -#ifdef DEBUG_ENABLED - } else if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { - glBindVertexArray(s->array_wireframe_id); // everything is so easy nowadays -#endif - } else { - glBindVertexArray(s->array_id); // everything is so easy nowadays - } - - } break; - - case VS::INSTANCE_MULTIMESH: { - - RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES3::MultiMesh *>(e->owner); - RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); -#ifdef DEBUG_ENABLED - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { - - glBindVertexArray(s->instancing_array_wireframe_id); // use the instancing array ID - } else -#endif - { - glBindVertexArray(s->instancing_array_id); // use the instancing array ID - } - - glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer - - int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, NULL); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); - glVertexAttribDivisor(9, 1); - - int color_ofs; - - if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) { - glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); - glVertexAttribDivisor(10, 1); - color_ofs = 12 * 4; - } else { - glDisableVertexAttribArray(10); - glVertexAttrib4f(10, 0, 0, 1, 0); - color_ofs = 8 * 4; - } - - int custom_data_ofs = color_ofs; - - switch (multi_mesh->color_format) { - - case VS::MULTIMESH_COLOR_MAX: - case VS::MULTIMESH_COLOR_NONE: { - glDisableVertexAttribArray(11); - glVertexAttrib4f(11, 1, 1, 1, 1); - } break; - case VS::MULTIMESH_COLOR_8BIT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4; - - } break; - case VS::MULTIMESH_COLOR_FLOAT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4 * 4; - } break; - } - - switch (multi_mesh->custom_data_format) { - - case VS::MULTIMESH_CUSTOM_DATA_MAX: - case VS::MULTIMESH_CUSTOM_DATA_NONE: { - glDisableVertexAttribArray(12); - glVertexAttrib4f(12, 1, 1, 1, 1); - } break; - case VS::MULTIMESH_CUSTOM_DATA_8BIT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - - } break; - case VS::MULTIMESH_CUSTOM_DATA_FLOAT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - } break; - } - - } break; - case VS::INSTANCE_PARTICLES: { - - RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner); - RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); - - if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) { - - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing - RasterizerGLES3Particle *particle_array; -#ifndef __EMSCRIPTEN__ - particle_array = static_cast<RasterizerGLES3Particle *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); -#else - PoolVector<RasterizerGLES3Particle> particle_vector; - particle_vector.resize(particles->amount); - PoolVector<RasterizerGLES3Particle>::Write particle_writer = particle_vector.write(); - particle_array = particle_writer.ptr(); - glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), particle_array); -#endif - - SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter; - - if (particles->use_local_coords) { - sorter.compare.z_dir = e->instance->transform.affine_inverse().xform(p_view_transform.basis.get_axis(2)).normalized(); - } else { - sorter.compare.z_dir = p_view_transform.basis.get_axis(2).normalized(); - } - - sorter.sort(particle_array, particles->amount); - -#ifndef __EMSCRIPTEN__ - glUnmapBuffer(GL_ARRAY_BUFFER); -#else - particle_writer.release(); - particle_array = NULL; - { - PoolVector<RasterizerGLES3Particle>::Read r = particle_vector.read(); - glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), r.ptr()); - } - particle_vector = PoolVector<RasterizerGLES3Particle>(); -#endif -#ifdef DEBUG_ENABLED - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { - glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID - } else -#endif - { - - glBindVertexArray(s->instancing_array_id); // use the instancing array ID - } - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer - - } else { -#ifdef DEBUG_ENABLED - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { - glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID - } else -#endif - { - glBindVertexArray(s->instancing_array_id); // use the instancing array ID - } - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer - } - - int stride = sizeof(float) * 4 * 6; - - //transform - - if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) { - - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - } - - } 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 RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { - - switch (e->instance->base_type) { - - case VS::INSTANCE_MESH: { - - RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); - -#ifdef DEBUG_ENABLED - - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { - - glDrawElements(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0); - storage->info.render.vertices_count += s->index_array_len; - } else -#endif - 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 VS::INSTANCE_MULTIMESH: { - - RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES3::MultiMesh *>(e->owner); - RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); - - int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); - - if (amount == -1) { - amount = multi_mesh->size; - } -#ifdef DEBUG_ENABLED - - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { - - glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount); - storage->info.render.vertices_count += s->index_array_len * amount; - } else -#endif - if (s->index_array_len > 0) { - - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - - storage->info.render.vertices_count += s->index_array_len * amount; - - } else { - - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); - - storage->info.render.vertices_count += s->array_len * amount; - } - - } break; - case VS::INSTANCE_IMMEDIATE: { - - bool restore_tex = false; - const RasterizerStorageGLES3::Immediate *im = static_cast<const RasterizerStorageGLES3::Immediate *>(e->geometry); - - if (im->building) { - return; - } - - glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer); - glBindVertexArray(state.immediate_array); - - for (const List<RasterizerStorageGLES3::Immediate::Chunk>::Element *E = im->chunks.front(); E; E = E->next()) { - - const RasterizerStorageGLES3::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)) { - - RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(c.texture); - - if (t->redraw_if_visible) { - VisualServerRaster::redraw_request(); - } - t = t->get_ptr(); //resolve for proxies - -#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(VS::ARRAY_NORMAL); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr()); - glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Vector3) * vertices; - - } else { - - glDisableVertexAttribArray(VS::ARRAY_NORMAL); - } - - if (!c.tangents.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_TANGENT); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr()); - glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false, sizeof(Plane), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Plane) * vertices; - - } else { - - glDisableVertexAttribArray(VS::ARRAY_TANGENT); - } - - if (!c.colors.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr()); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Color) * vertices; - - } else { - - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - } - - if (!c.uvs.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs.ptr()); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Vector2) * vertices; - - } else { - - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - if (!c.uvs2.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs2.ptr()); - glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); - buf_ofs += sizeof(Vector2) * vertices; - - } else { - - glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); - } - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr()); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, 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; - case VS::INSTANCE_PARTICLES: { - - RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner); - RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); - - if (!particles->use_local_coords) //not using local coordinates? then clear transform.. - state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, Transform()); - - int amount = particles->amount; - - if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_LIFETIME) { - //split - - int stride = sizeof(float) * 4 * 6; - int split = int(Math::ceil(particles->phase * particles->amount)); - - if (amount - split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); -#ifdef DEBUG_ENABLED - - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { - - glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount - split); - storage->info.render.vertices_count += s->index_array_len * (amount - split); - } else -#endif - if (s->index_array_len > 0) { - - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount - split); - - storage->info.render.vertices_count += s->index_array_len * (amount - split); - - } else { - - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount - split); - - storage->info.render.vertices_count += s->array_len * (amount - split); - } - } - - if (split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); -#ifdef DEBUG_ENABLED - - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { - - glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, split); - storage->info.render.vertices_count += s->index_array_len * split; - } else -#endif - if (s->index_array_len > 0) { - - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, split); - - storage->info.render.vertices_count += s->index_array_len * split; - - } else { - - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, split); - - storage->info.render.vertices_count += s->array_len * split; - } - } - - } else { - -#ifdef DEBUG_ENABLED - - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { - - glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount); - storage->info.render.vertices_count += s->index_array_len * amount; - } else -#endif - - if (s->index_array_len > 0) { - - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - - storage->info.render.vertices_count += s->index_array_len * amount; - - } else { - - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); - - storage->info.render.vertices_count += s->array_len * amount; - } - } - - } break; - default: { - } - } -} - -void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform &p_view_transform) { - - int omni_indices[16]; - int omni_count = 0; - int spot_indices[16]; - int spot_count = 0; - int reflection_indices[16]; - int reflection_count = 0; - - int maxobj = MIN(16, state.max_forward_lights_per_object); - - int lc = e->instance->light_instances.size(); - if (lc) { - - const RID *lights = e->instance->light_instances.ptr(); - - for (int i = 0; i < lc; i++) { - LightInstance *li = light_instance_owner.getornull(lights[i]); - if (!li || li->last_pass != render_pass) //not visible - continue; - - if (li && li->light_ptr->type == VS::LIGHT_OMNI) { - if (omni_count < maxobj && e->instance->layer_mask & li->light_ptr->cull_mask) { - omni_indices[omni_count++] = li->light_index; - } - } - - if (li && li->light_ptr->type == VS::LIGHT_SPOT) { - if (spot_count < maxobj && e->instance->layer_mask & li->light_ptr->cull_mask) { - spot_indices[spot_count++] = li->light_index; - } - } - } - } - - state.scene_shader.set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, omni_count); - - if (omni_count) { - glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES), omni_count, omni_indices); - } - - state.scene_shader.set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, spot_count); - if (spot_count) { - glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES), spot_count, spot_indices); - } - - int rc = e->instance->reflection_probe_instances.size(); - - if (rc) { - - const RID *reflections = e->instance->reflection_probe_instances.ptr(); - - for (int i = 0; i < rc; i++) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(reflections[i]); - if (rpi->last_pass != render_pass) //not visible - continue; - - if (reflection_count < maxobj) { - reflection_indices[reflection_count++] = rpi->reflection_index; - } - } - } - - state.scene_shader.set_uniform(SceneShaderGLES3::REFLECTION_COUNT, reflection_count); - if (reflection_count) { - glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::REFLECTION_INDICES), reflection_count, reflection_indices); - } - - int gi_probe_count = e->instance->gi_probe_instances.size(); - if (gi_probe_count) { - const RID *ridp = e->instance->gi_probe_instances.ptr(); - - GIProbeInstance *gipi = gi_probe_instance_owner.getornull(ridp[0]); - - float bias_scale = e->instance->baked_light ? 1 : 0; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9); - glBindTexture(GL_TEXTURE_3D, gipi->tex_cache); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER1, gipi->probe ? gipi->probe->dynamic_range * gipi->probe->energy : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS1, gipi->probe ? gipi->probe->bias * bias_scale : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_NORMAL_BIAS1, gipi->probe ? gipi->probe->normal_bias * bias_scale : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT1, gipi->probe ? !gipi->probe->interior : false); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache); - if (gi_probe_count > 1) { - - GIProbeInstance *gipi2 = gi_probe_instance_owner.getornull(ridp[1]); - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10); - glBindTexture(GL_TEXTURE_3D, gipi2->tex_cache); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER2, gipi2->probe ? gipi2->probe->dynamic_range * gipi2->probe->energy : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS2, gipi2->probe ? gipi2->probe->bias * bias_scale : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_NORMAL_BIAS2, gipi2->probe ? gipi2->probe->normal_bias * bias_scale : 0.0); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT2, gipi2->probe ? !gipi2->probe->interior : false); - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true); - } else { - - state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, false); - } - } else if (!e->instance->lightmap_capture_data.empty()) { - - glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES3::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr()); - state.scene_shader.set_uniform(SceneShaderGLES3::LIGHTMAP_CAPTURE_SKY, false); - - } else if (e->instance->lightmap.is_valid()) { - RasterizerStorageGLES3::Texture *lightmap = storage->texture_owner.getornull(e->instance->lightmap); - RasterizerStorageGLES3::LightmapCapture *capture = storage->lightmap_capture_data_owner.getornull(e->instance->lightmap_capture->base); - - if (lightmap && capture) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9); - glBindTexture(GL_TEXTURE_2D, lightmap->tex_id); - state.scene_shader.set_uniform(SceneShaderGLES3::LIGHTMAP_ENERGY, capture->energy); - } - } -} - -void RasterizerSceneGLES3::_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; - } -} - -void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RasterizerStorageGLES3::Sky *p_sky, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) { - - glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.scene_ubo); //bind globals ubo - - bool use_radiance_map = false; - if (!p_shadow && !p_directional_add) { - glBindBufferBase(GL_UNIFORM_BUFFER, 2, state.env_radiance_ubo); //bind environment radiance info - - if (p_sky != NULL) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2); - if (storage->config.use_texture_array_environment) { - glBindTexture(GL_TEXTURE_2D_ARRAY, p_sky->radiance); - } else { - glBindTexture(GL_TEXTURE_2D, p_sky->radiance); - } - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); - glBindTexture(GL_TEXTURE_2D, p_sky->irradiance); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, true); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, storage->config.use_texture_array_environment); - use_radiance_map = true; - } else { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false); - } - } else { - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false); - } - - state.cull_front = false; - state.cull_disabled = false; - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - - state.current_depth_test = true; - glEnable(GL_DEPTH_TEST); - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, false); - - state.current_blend_mode = -1; - state.current_line_width = -1; - state.current_depth_draw = -1; - - RasterizerStorageGLES3::Material *prev_material = NULL; - RasterizerStorageGLES3::Geometry *prev_geometry = NULL; - RasterizerStorageGLES3::GeometryOwner *prev_owner = NULL; - VS::InstanceType prev_base_type = VS::INSTANCE_MAX; - - int current_blend_mode = -1; - - int prev_shading = -1; - RasterizerStorageGLES3::Skeleton *prev_skeleton = NULL; - - state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true); //by default unshaded (easier to set) - - bool first = true; - bool prev_use_instancing = false; - - storage->info.render.draw_call_count += p_element_count; - bool prev_opaque_prepass = false; - - for (int i = 0; i < p_element_count; i++) { - - RenderList::Element *e = p_elements[i]; - RasterizerStorageGLES3::Material *material = e->material; - RasterizerStorageGLES3::Skeleton *skeleton = NULL; - if (e->instance->skeleton.is_valid()) { - skeleton = storage->skeleton_owner.getornull(e->instance->skeleton); - } - - bool rebind = first; - - int shading = (e->sort_key >> RenderList::SORT_KEY_SHADING_SHIFT) & RenderList::SORT_KEY_SHADING_MASK; - - if (!p_shadow) { - - if (p_directional_add) { - if (e->sort_key & SORT_KEY_UNSHADED_FLAG || !(e->instance->layer_mask & directional_light->light_ptr->cull_mask)) { - continue; - } - - shading &= ~1; //ignore the ignore directional for base pass - } - - if (shading != prev_shading) { - - if (e->sort_key & SORT_KEY_UNSHADED_FLAG) { - - state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); - state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, false); - state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP_CAPTURE, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false); - - //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); - } else { - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, e->instance->gi_probe_instances.size() > 0); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP, e->instance->lightmap.is_valid() && e->instance->gi_probe_instances.size() == 0); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP_CAPTURE, !e->instance->lightmap_capture_data.empty() && !e->instance->lightmap.is_valid() && e->instance->gi_probe_instances.size() == 0); - - state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, false); - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, !p_directional_add); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, (e->sort_key & SORT_KEY_VERTEX_LIT_FLAG)); - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); - state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); - state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, use_radiance_map); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, state.used_contact_shadows); - - if (p_directional_add || (directional_light && (e->sort_key & SORT_KEY_NO_DIRECTIONAL_FLAG) == 0)) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, true); - - if (p_directional_shadows && directional_light->light_ptr->shadow) { - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, true); - - switch (directional_light->light_ptr->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: - break; //none - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, true); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits); - break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, true); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits); - break; - } - } - } - } - - rebind = true; - } - - if (p_alpha_pass || p_directional_add) { - int desired_blend_mode; - if (p_directional_add) { - desired_blend_mode = RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD; - } else { - desired_blend_mode = material->shader->spatial.blend_mode; - } - - if (desired_blend_mode != current_blend_mode) { - - switch (desired_blend_mode) { - - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: { - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(p_alpha_pass ? GL_SRC_ALPHA : GL_ONE, GL_ONE); - - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: { - - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::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; - } - - current_blend_mode = desired_blend_mode; - } - } - } - - bool use_opaque_prepass = e->sort_key & RenderList::SORT_KEY_OPAQUE_PRE_PASS; - - if (use_opaque_prepass != prev_opaque_prepass) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, use_opaque_prepass); - rebind = true; - } - - bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES; - - if (use_instancing != prev_use_instancing) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, use_instancing); - rebind = true; - } - - if (prev_skeleton != skeleton) { - if ((prev_skeleton == NULL) != (skeleton == NULL)) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, skeleton != NULL); - rebind = true; - } - - if (skeleton) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, skeleton->texture); - } - } - - if (material != prev_material || rebind) { - - storage->info.render.material_switch_count++; - - rebind = _setup_material(material, use_opaque_prepass, p_alpha_pass); - - if (rebind) { - storage->info.render.shader_rebind_count++; - } - } - - if (!(e->sort_key & SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { - _setup_light(e, p_view_transform); - } - - if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry != e->geometry) { - - _setup_geometry(e, p_view_transform); - storage->info.render.surface_switch_count++; - } - - _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, e->sort_key & RenderList::SORT_KEY_CULL_DISABLED_FLAG, p_reverse_cull); - - state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform); - - _render_geometry(e); - - prev_material = material; - prev_base_type = e->instance->base_type; - prev_geometry = e->geometry; - prev_owner = e->owner; - prev_shading = shading; - prev_skeleton = skeleton; - prev_use_instancing = use_instancing; - prev_opaque_prepass = use_opaque_prepass; - first = false; - } - - glBindVertexArray(0); - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); - state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, false); - state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, false); - state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP_CAPTURE, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, false); -} - -void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass) { - - RasterizerStorageGLES3::Material *m = NULL; - RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : (p_material >= 0 ? p_instance->materials[p_material] : p_geometry->material); - - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { - m_src = default_overdraw_material; - } - - /* -#ifdef DEBUG_ENABLED - if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) { - m_src=overdraw_material; - } - -#endif -*/ - - if (m_src.is_valid()) { - m = storage->material_owner.getornull(m_src); - - if (!m->shader || !m->shader->valid) { - m = NULL; - } - } - - if (!m) { - m = storage->material_owner.getornull(default_material); - } - - ERR_FAIL_COND(!m); - - _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass); - - while (m->next_pass.is_valid()) { - m = storage->material_owner.getornull(m->next_pass); - if (!m || !m->shader || !m->shader->valid) - break; - _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass); - } -} - -void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::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 != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX; - bool has_alpha = has_base_alpha || has_blend_alpha; - - bool mirror = p_instance->mirror; - bool no_cull = false; - - if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_DISABLED) { - no_cull = true; - mirror = false; - } else if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::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_material->shader->spatial.uses_depth_texture) { - state.used_depth_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 != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test || p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) - 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 != RasterizerStorageGLES3::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 == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { - p_material = storage->material_owner.getornull(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material_twosided : default_material_twosided); - no_cull = true; - mirror = false; - } else { - p_material = storage->material_owner.getornull(!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; - - if (e->geometry->last_pass != render_pass) { - e->geometry->last_pass = render_pass; - e->geometry->index = current_geometry_index++; - } - - if (!p_depth_pass && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) { - e->sort_key |= SORT_KEY_NO_DIRECTIONAL_FLAG; - } - - e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT; - e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT; - - if (e->material->last_pass != render_pass) { - e->material->last_pass = render_pass; - e->material->index = current_material_index++; - } - - e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT; - e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT; - - if (!p_depth_pass) { - - if (e->instance->gi_probe_instances.size()) { - e->sort_key |= SORT_KEY_GI_PROBES_FLAG; - } - - if (e->instance->lightmap.is_valid()) { - e->sort_key |= SORT_KEY_LIGHTMAP_FLAG; - } - - if (!e->instance->lightmap_capture_data.empty()) { - e->sort_key |= SORT_KEY_LIGHTMAP_CAPTURE_FLAG; - } - - e->sort_key |= (uint64_t(p_material->render_priority) + 128) << RenderList::SORT_KEY_PRIORITY_SHIFT; - } - - /* - if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE) - e->sort_flags|=RenderList::SORT_FLAG_INSTANCING; - */ - - if (mirror) { - e->sort_key |= RenderList::SORT_KEY_MIRROR_FLAG; - } - - if (no_cull) { - e->sort_key |= RenderList::SORT_KEY_CULL_DISABLED_FLAG; - } - - //e->light_type=0xFF; // no lights! - - if (p_depth_pass || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { - e->sort_key |= SORT_KEY_UNSHADED_FLAG; - } - - if (p_depth_pass && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { - e->sort_key |= RenderList::SORT_KEY_OPAQUE_PRE_PASS; - } - - if (!p_depth_pass && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) { - - e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG; - } - - if (p_material->shader->spatial.uses_time) { - VisualServerRaster::redraw_request(); - } -} - -void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation) { - - ERR_FAIL_COND(!p_sky); - - RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_sky->panorama); - - ERR_FAIL_COND(!tex); - glActiveTexture(GL_TEXTURE0); - - tex = tex->get_ptr(); //resolve for proxies - - glBindTexture(tex->target, tex->tex_id); - - if (storage->config.srgb_decode_supported && tex->srgb && !tex->using_srgb) { - - glTexParameteri(tex->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); - tex->using_srgb = true; -#ifdef TOOLS_ENABLED - if (!(tex->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - tex->flags |= VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; - //notify that texture must be set to linear beforehand, so it works in other platforms when exported - } -#endif - } - - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - - // 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); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - glBindVertexArray(state.sky_array); - - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, asymmetrical); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, !asymmetrical); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, true); - storage->shaders.copy.bind(); - - storage->shaders.copy.set_uniform(CopyShaderGLES3::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(CopyShaderGLES3::SKY_TRANSFORM, Transform(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(CopyShaderGLES3::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(CopyShaderGLES3::PANO_TRANSFORM, p_transform); - } - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBindVertexArray(0); - glColorMask(1, 1, 1, 1); - - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false); -} - -void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) { - Transform sky_orientation; - - //store camera into ubo - store_camera(p_cam_projection, state.ubo_data.projection_matrix); - store_camera(p_cam_projection.inverse(), state.ubo_data.inv_projection_matrix); - store_transform(p_cam_transform, state.ubo_data.camera_matrix); - store_transform(p_cam_transform.affine_inverse(), state.ubo_data.camera_inverse_matrix); - - //time global variables - state.ubo_data.time = storage->frame.time[0]; - - state.ubo_data.z_far = p_cam_projection.get_z_far(); - //bg and ambient - if (env) { - state.ubo_data.bg_energy = env->bg_energy; - state.ubo_data.ambient_energy = env->ambient_energy; - Color linear_ambient_color = env->ambient_color.to_linear(); - state.ubo_data.ambient_light_color[0] = linear_ambient_color.r; - state.ubo_data.ambient_light_color[1] = linear_ambient_color.g; - state.ubo_data.ambient_light_color[2] = linear_ambient_color.b; - state.ubo_data.ambient_light_color[3] = linear_ambient_color.a; - - Color bg_color; - - switch (env->bg_mode) { - case VS::ENV_BG_CLEAR_COLOR: { - bg_color = storage->frame.clear_request_color.to_linear(); - } break; - case VS::ENV_BG_COLOR: { - bg_color = env->bg_color.to_linear(); - } break; - default: { - bg_color = Color(0, 0, 0, 1); - } break; - } - - state.ubo_data.bg_color[0] = bg_color.r; - state.ubo_data.bg_color[1] = bg_color.g; - state.ubo_data.bg_color[2] = bg_color.b; - state.ubo_data.bg_color[3] = bg_color.a; - - //use the inverse of our sky_orientation, we may need to skip this if we're using a reflection probe? - sky_orientation = Transform(env->sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse(); - - state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution; - state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect; - state.ubo_data.ambient_occlusion_affect_ssao = env->ssao_ao_channel_affect; - - //fog - - Color linear_fog = env->fog_color.to_linear(); - state.ubo_data.fog_color_enabled[0] = linear_fog.r; - state.ubo_data.fog_color_enabled[1] = linear_fog.g; - state.ubo_data.fog_color_enabled[2] = linear_fog.b; - state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0; - state.ubo_data.fog_density = linear_fog.a; - - Color linear_sun = env->fog_sun_color.to_linear(); - state.ubo_data.fog_sun_color_amount[0] = linear_sun.r; - state.ubo_data.fog_sun_color_amount[1] = linear_sun.g; - state.ubo_data.fog_sun_color_amount[2] = linear_sun.b; - state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount; - state.ubo_data.fog_depth_enabled = env->fog_depth_enabled; - state.ubo_data.fog_depth_begin = env->fog_depth_begin; - state.ubo_data.fog_depth_end = env->fog_depth_end; - state.ubo_data.fog_depth_curve = env->fog_depth_curve; - state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled; - state.ubo_data.fog_transmit_curve = env->fog_transmit_curve; - state.ubo_data.fog_height_enabled = env->fog_height_enabled; - state.ubo_data.fog_height_min = env->fog_height_min; - state.ubo_data.fog_height_max = env->fog_height_max; - state.ubo_data.fog_height_curve = env->fog_height_curve; - - } else { - state.ubo_data.bg_energy = 1.0; - state.ubo_data.ambient_energy = 1.0; - //use from clear color instead, since there is no ambient - Color linear_ambient_color = storage->frame.clear_request_color.to_linear(); - state.ubo_data.ambient_light_color[0] = linear_ambient_color.r; - state.ubo_data.ambient_light_color[1] = linear_ambient_color.g; - state.ubo_data.ambient_light_color[2] = linear_ambient_color.b; - state.ubo_data.ambient_light_color[3] = linear_ambient_color.a; - - state.ubo_data.bg_color[0] = linear_ambient_color.r; - state.ubo_data.bg_color[1] = linear_ambient_color.g; - state.ubo_data.bg_color[2] = linear_ambient_color.b; - state.ubo_data.bg_color[3] = linear_ambient_color.a; - - state.env_radiance_data.ambient_contribution = 0; - state.ubo_data.ambient_occlusion_affect_light = 0; - - state.ubo_data.fog_color_enabled[3] = 0.0; - } - - { - //directional shadow - - state.ubo_data.shadow_directional_pixel_size[0] = 1.0 / directional_shadow.size; - state.ubo_data.shadow_directional_pixel_size[1] = 1.0 / directional_shadow.size; - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); - } - - glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.ubo_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - //fill up environment - - store_transform(sky_orientation * p_cam_transform, state.env_radiance_data.transform); - - glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); -} - -void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows) { - - LightInstance *li = directional_lights[p_index]; - - LightDataUBO ubo_data; //used for filling - - float sign = li->light_ptr->negative ? -1 : 1; - - Color linear_col = li->light_ptr->color.to_linear(); - //compensate normalized diffuse range by multiplying by PI - ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[3] = 0; - - //omni, keep at 0 - ubo_data.light_pos_inv_radius[0] = 0.0; - ubo_data.light_pos_inv_radius[1] = 0.0; - ubo_data.light_pos_inv_radius[2] = 0.0; - ubo_data.light_pos_inv_radius[3] = 0.0; - - Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0, 0, -1))).normalized(); - ubo_data.light_direction_attenuation[0] = direction.x; - ubo_data.light_direction_attenuation[1] = direction.y; - ubo_data.light_direction_attenuation[2] = direction.z; - ubo_data.light_direction_attenuation[3] = 1.0; - - ubo_data.light_params[0] = 0; - ubo_data.light_params[1] = 0; - ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - ubo_data.light_params[3] = 0; - - Color shadow_color = li->light_ptr->shadow_color.to_linear(); - ubo_data.light_shadow_color_contact[0] = shadow_color.r; - ubo_data.light_shadow_color_contact[1] = shadow_color.g; - ubo_data.light_shadow_color_contact[2] = shadow_color.b; - ubo_data.light_shadow_color_contact[3] = li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE]; - - if (p_use_shadows && li->light_ptr->shadow) { - - int shadow_count = 0; - - switch (li->light_ptr->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { - shadow_count = 1; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { - shadow_count = 2; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { - shadow_count = 4; - } break; - } - - for (int j = 0; j < shadow_count; j++) { - - uint32_t x = li->directional_rect.position.x; - uint32_t y = li->directional_rect.position.y; - uint32_t width = li->directional_rect.size.x; - uint32_t height = li->directional_rect.size.y; - - if (li->light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - - width /= 2; - height /= 2; - - if (j == 1) { - x += width; - } else if (j == 2) { - y += height; - } else if (j == 3) { - x += width; - y += height; - } - - } else if (li->light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - - height /= 2; - - if (j != 0) { - y += height; - } - } - - ubo_data.shadow_split_offsets[j] = li->shadow_transform[j].split; - - Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].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 * li->shadow_transform[j].camera * modelview; - - store_camera(shadow_mtx, &ubo_data.shadow.matrix[16 * j]); - - ubo_data.light_clamp[0] = atlas_rect.position.x; - ubo_data.light_clamp[1] = atlas_rect.position.y; - ubo_data.light_clamp[2] = atlas_rect.size.x; - ubo_data.light_clamp[3] = atlas_rect.size.y; - } - } - - glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDataUBO), &ubo_data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - directional_light = li; - - glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.directional_ubo); -} - -void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas) { - - state.omni_light_count = 0; - state.spot_light_count = 0; - state.directional_light_count = 0; - - directional_light = NULL; - - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - - for (int i = 0; i < p_light_cull_count; i++) { - - ERR_BREAK(i >= render_list.max_lights); - - LightInstance *li = light_instance_owner.getornull(p_light_cull_result[i]); - - LightDataUBO ubo_data; //used for filling - - switch (li->light_ptr->type) { - - case VS::LIGHT_DIRECTIONAL: { - - if (state.directional_light_count < RenderList::MAX_DIRECTIONAL_LIGHTS) { - directional_lights[state.directional_light_count++] = li; - } - - } break; - case VS::LIGHT_OMNI: { - - float sign = li->light_ptr->negative ? -1 : 1; - - Color linear_col = li->light_ptr->color.to_linear(); - ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[3] = 0; - - Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); - - //directional, keep at 0 - ubo_data.light_pos_inv_radius[0] = pos.x; - ubo_data.light_pos_inv_radius[1] = pos.y; - ubo_data.light_pos_inv_radius[2] = pos.z; - ubo_data.light_pos_inv_radius[3] = 1.0 / MAX(0.001, li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); - - ubo_data.light_direction_attenuation[0] = 0; - ubo_data.light_direction_attenuation[1] = 0; - ubo_data.light_direction_attenuation[2] = 0; - ubo_data.light_direction_attenuation[3] = li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - - ubo_data.light_params[0] = 0; - ubo_data.light_params[1] = 0; - ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - ubo_data.light_params[3] = 0; - - Color shadow_color = li->light_ptr->shadow_color.to_linear(); - ubo_data.light_shadow_color_contact[0] = shadow_color.r; - ubo_data.light_shadow_color_contact[1] = shadow_color.g; - ubo_data.light_shadow_color_contact[2] = shadow_color.b; - ubo_data.light_shadow_color_contact[3] = li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE]; - - if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { - // fill in the shadow information - - uint32_t key = shadow_atlas->shadow_owners[li->self]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_CONTINUE(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 (li->light_ptr->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { - - height /= 2; - } else { - width /= 2; - } - - Transform proj = (p_camera_inverse_transform * li->transform).inverse(); - - store_transform(proj, ubo_data.shadow.matrix1); - - ubo_data.light_params[3] = 1.0; //means it has shadow - ubo_data.light_clamp[0] = float(x) / atlas_size; - ubo_data.light_clamp[1] = float(y) / atlas_size; - ubo_data.light_clamp[2] = float(width) / atlas_size; - ubo_data.light_clamp[3] = float(height) / atlas_size; - } - - li->light_index = state.omni_light_count; - copymem(&state.omni_array_tmp[li->light_index * state.ubo_light_size], &ubo_data, state.ubo_light_size); - state.omni_light_count++; - - } break; - case VS::LIGHT_SPOT: { - - float sign = li->light_ptr->negative ? -1 : 1; - - Color linear_col = li->light_ptr->color.to_linear(); - ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI; - ubo_data.light_color_energy[3] = 0; - - Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); - - //directional, keep at 0 - ubo_data.light_pos_inv_radius[0] = pos.x; - ubo_data.light_pos_inv_radius[1] = pos.y; - ubo_data.light_pos_inv_radius[2] = pos.z; - ubo_data.light_pos_inv_radius[3] = 1.0 / MAX(0.001, li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); - - Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0, 0, -1))).normalized(); - ubo_data.light_direction_attenuation[0] = direction.x; - ubo_data.light_direction_attenuation[1] = direction.y; - ubo_data.light_direction_attenuation[2] = direction.z; - ubo_data.light_direction_attenuation[3] = li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - - ubo_data.light_params[0] = li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; - ubo_data.light_params[1] = Math::cos(Math::deg2rad(li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE])); - ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - ubo_data.light_params[3] = 0; - - Color shadow_color = li->light_ptr->shadow_color.to_linear(); - ubo_data.light_shadow_color_contact[0] = shadow_color.r; - ubo_data.light_shadow_color_contact[1] = shadow_color.g; - ubo_data.light_shadow_color_contact[2] = shadow_color.b; - ubo_data.light_shadow_color_contact[3] = li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE]; - - if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { - // fill in the shadow information - - uint32_t key = shadow_atlas->shadow_owners[li->self]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_CONTINUE(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); - - ubo_data.light_params[3] = 1.0; //means it has shadow - ubo_data.light_clamp[0] = rect.position.x; - ubo_data.light_clamp[1] = rect.position.y; - ubo_data.light_clamp[2] = rect.size.x; - ubo_data.light_clamp[3] = rect.size.y; - - Transform modelview = (p_camera_inverse_transform * li->transform).inverse(); - - CameraMatrix bias; - bias.set_light_bias(); - CameraMatrix rectm; - rectm.set_light_atlas_rect(rect); - - CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview; - - store_camera(shadow_mtx, ubo_data.shadow.matrix1); - } - - li->light_index = state.spot_light_count; - copymem(&state.spot_array_tmp[li->light_index * state.ubo_light_size], &ubo_data, state.ubo_light_size); - state.spot_light_count++; - } break; - } - - li->last_pass = render_pass; - - //update UBO for forward rendering, blit to texture for clustered - } - - if (state.omni_light_count) { - - glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, state.omni_light_count * state.ubo_light_size, state.omni_array_tmp); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } - - glBindBufferBase(GL_UNIFORM_BUFFER, 4, state.omni_array_ubo); - - if (state.spot_light_count) { - - glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, state.spot_light_count * state.ubo_light_size, state.spot_array_tmp); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } - - glBindBufferBase(GL_UNIFORM_BUFFER, 5, state.spot_array_ubo); -} - -void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env) { - - state.reflection_probe_count = 0; - - 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); - - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); - ERR_CONTINUE(!reflection_atlas); - - ERR_CONTINUE(rpi->reflection_atlas_index < 0); - - if (state.reflection_probe_count >= state.max_ubo_reflections) - break; - - rpi->last_pass = render_pass; - - ReflectionProbeDataUBO reflection_ubo; - - reflection_ubo.box_extents[0] = rpi->probe_ptr->extents.x; - reflection_ubo.box_extents[1] = rpi->probe_ptr->extents.y; - reflection_ubo.box_extents[2] = rpi->probe_ptr->extents.z; - reflection_ubo.box_extents[3] = 0; - - reflection_ubo.box_ofs[0] = rpi->probe_ptr->origin_offset.x; - reflection_ubo.box_ofs[1] = rpi->probe_ptr->origin_offset.y; - reflection_ubo.box_ofs[2] = rpi->probe_ptr->origin_offset.z; - reflection_ubo.box_ofs[3] = 0; - - reflection_ubo.params[0] = rpi->probe_ptr->intensity; - reflection_ubo.params[1] = 0; - reflection_ubo.params[2] = rpi->probe_ptr->interior ? 1.0 : 0.0; - reflection_ubo.params[3] = rpi->probe_ptr->box_projection ? 1.0 : 0.0; - - if (rpi->probe_ptr->interior) { - Color ambient_linear = rpi->probe_ptr->interior_ambient.to_linear(); - reflection_ubo.ambient[0] = ambient_linear.r * rpi->probe_ptr->interior_ambient_energy; - reflection_ubo.ambient[1] = ambient_linear.g * rpi->probe_ptr->interior_ambient_energy; - reflection_ubo.ambient[2] = ambient_linear.b * rpi->probe_ptr->interior_ambient_energy; - reflection_ubo.ambient[3] = rpi->probe_ptr->interior_ambient_probe_contrib; - } else { - Color ambient_linear; - if (p_env) { - ambient_linear = p_env->ambient_color.to_linear(); - ambient_linear.r *= p_env->ambient_energy; - ambient_linear.g *= p_env->ambient_energy; - ambient_linear.b *= p_env->ambient_energy; - } - - reflection_ubo.ambient[0] = ambient_linear.r; - reflection_ubo.ambient[1] = ambient_linear.g; - reflection_ubo.ambient[2] = ambient_linear.b; - reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light - } - - int cell_size = reflection_atlas->size / reflection_atlas->subdiv; - int x = (rpi->reflection_atlas_index % reflection_atlas->subdiv) * cell_size; - int y = (rpi->reflection_atlas_index / reflection_atlas->subdiv) * cell_size; - int width = cell_size; - int height = cell_size; - - reflection_ubo.atlas_clamp[0] = float(x) / reflection_atlas->size; - reflection_ubo.atlas_clamp[1] = float(y) / reflection_atlas->size; - reflection_ubo.atlas_clamp[2] = float(width) / reflection_atlas->size; - reflection_ubo.atlas_clamp[3] = float(height) / reflection_atlas->size; - - Transform proj = (p_camera_inverse_transform * rpi->transform).inverse(); - store_transform(proj, reflection_ubo.local_matrix); - - rpi->reflection_index = state.reflection_probe_count; - copymem(&state.reflection_array_tmp[rpi->reflection_index * sizeof(ReflectionProbeDataUBO)], &reflection_ubo, sizeof(ReflectionProbeDataUBO)); - state.reflection_probe_count++; - } - - if (state.reflection_probe_count) { - - glBindBuffer(GL_UNIFORM_BUFFER, state.reflection_array_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, state.reflection_probe_count * sizeof(ReflectionProbeDataUBO), state.reflection_array_tmp); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } - - glBindBufferBase(GL_UNIFORM_BUFFER, 6, state.reflection_array_ubo); -} - -void RasterizerSceneGLES3::_copy_screen(bool p_invalidate_color, bool p_invalidate_depth) { - -#ifndef GLES_OVER_GL - if (p_invalidate_color) { - - GLenum attachments[2] = { - GL_COLOR_ATTACHMENT0, - GL_DEPTH_ATTACHMENT - }; - - glInvalidateFramebuffer(GL_FRAMEBUFFER, p_invalidate_depth ? 2 : 1, attachments); - } -#endif - - glBindVertexArray(storage->resources.quadie_array); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindVertexArray(0); -} - -void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) { - - //copy to front buffer - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); - - 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 * 0.5, storage->frame.current_rt->height * 0.5); - - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); - storage->shaders.copy.bind(); - - _copy_screen(); - - //turn off everything used - storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); -} - -void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) { - - current_geometry_index = 0; - current_material_index = 0; - state.used_sss = false; - state.used_screen_texture = false; - state.used_depth_texture = false; - - //fill list - - for (int i = 0; i < p_cull_count; i++) { - - InstanceBase *inst = p_cull_result[i]; - switch (inst->base_type) { - - case VS::INSTANCE_MESH: { - - RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(inst->base); - ERR_CONTINUE(!mesh); - - int ssize = mesh->surfaces.size(); - - for (int j = 0; j < ssize; j++) { - - int mat_idx = inst->materials[j].is_valid() ? j : -1; - RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; - _add_geometry(s, inst, NULL, mat_idx, p_depth_pass, p_shadow_pass); - } - - //mesh->last_pass=frame; - - } break; - case VS::INSTANCE_MULTIMESH: { - - RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(inst->base); - ERR_CONTINUE(!multi_mesh); - - if (multi_mesh->size == 0 || multi_mesh->visible_instances == 0) - continue; - - RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(multi_mesh->mesh); - if (!mesh) - continue; //mesh not assigned - - int ssize = mesh->surfaces.size(); - - for (int j = 0; j < ssize; j++) { - - RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; - _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass); - } - - } break; - case VS::INSTANCE_IMMEDIATE: { - - RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); - ERR_CONTINUE(!immediate); - - _add_geometry(immediate, inst, NULL, -1, p_depth_pass, p_shadow_pass); - - } break; - case VS::INSTANCE_PARTICLES: { - - RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(inst->base); - ERR_CONTINUE(!particles); - - for (int j = 0; j < particles->draw_passes.size(); j++) { - - RID pmesh = particles->draw_passes[j]; - if (!pmesh.is_valid()) - continue; - RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(pmesh); - if (!mesh) - continue; //mesh not assigned - - int ssize = mesh->surfaces.size(); - - for (int k = 0; k < ssize; k++) { - - RasterizerStorageGLES3::Surface *s = mesh->surfaces[k]; - _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass); - } - } - - } break; - default: { - } - } - } -} - -void RasterizerSceneGLES3::_blur_effect_buffer() { - - //blur diffuse into effect mipmaps using separatable convolution - //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); - for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) { - - int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; - int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; - glViewport(0, 0, vp_w, vp_h); - //horizontal pass - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); - _copy_screen(true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false); - - //vertical pass - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger - _copy_screen(true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false); - } -} - -void RasterizerSceneGLES3::_prepare_depth_texture() { - if (!state.prepared_depth_texture) { - //resolve depth buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.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_DEPTH_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - state.prepared_depth_texture = true; - } -} - -void RasterizerSceneGLES3::_bind_depth_texture() { - if (!state.bound_depth_texture) { - ERR_FAIL_COND(!state.prepared_depth_texture); - //bind depth for read - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - state.bound_depth_texture = true; - } -} - -void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_cam_projection) { - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - - _prepare_depth_texture(); - - if (env->ssao_enabled || env->ssr_enabled) { - - //copy normal and roughness to effect buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT2); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_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_NEAREST); - } - - if (env->ssao_enabled) { - //copy diffuse to front buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.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); - - //copy from depth, convert to linear - GLint ss[2]; - ss[0] = storage->frame.current_rt->width; - ss[1] = storage->frame.current_rt->height; - - for (int i = 0; i < storage->frame.current_rt->effects.ssao.depth_mipmap_fbos.size(); i++) { - - state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::MINIFY_START, i == 0); - state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - state.ssao_minify_shader.bind(); - state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::SOURCE_MIPMAP, MAX(0, i - 1)); - glUniform2iv(state.ssao_minify_shader.get_uniform(SsaoMinifyShaderGLES3::FROM_SIZE), 1, ss); - ss[0] >>= 1; - ss[1] >>= 1; - - glActiveTexture(GL_TEXTURE0); - if (i == 0) { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.linear_depth); - } - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.depth_mipmap_fbos[i]); //copy to front first - glViewport(0, 0, ss[0], ss[1]); - - _copy_screen(true); - } - ss[0] = storage->frame.current_rt->width; - ss[1] = storage->frame.current_rt->height; - - glViewport(0, 0, ss[0], ss[1]); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_GREATER); - // do SSAO! - state.ssao_shader.set_conditional(SsaoShaderGLES3::ENABLE_RADIUS2, env->ssao_radius2 > 0.001); - state.ssao_shader.set_conditional(SsaoShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - state.ssao_shader.set_conditional(SsaoShaderGLES3::SSAO_QUALITY_LOW, env->ssao_quality == VS::ENV_SSAO_QUALITY_LOW); - state.ssao_shader.set_conditional(SsaoShaderGLES3::SSAO_QUALITY_HIGH, env->ssao_quality == VS::ENV_SSAO_QUALITY_HIGH); - state.ssao_shader.bind(); - state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - glUniform2iv(state.ssao_shader.get_uniform(SsaoShaderGLES3::SCREEN_SIZE), 1, ss); - float radius = env->ssao_radius; - state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS, radius); - float intensity = env->ssao_intensity; - state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R6, intensity / pow(radius, 6.0f)); - - if (env->ssao_radius2 > 0.001) { - - float radius2 = env->ssao_radius2; - state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS2, radius2); - float intensity2 = env->ssao_intensity2; - state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R62, intensity2 / pow(radius2, 6.0f)); - } - - float proj_info[4] = { - -2.0f / (ss[0] * p_cam_projection.matrix[0][0]), - -2.0f / (ss[1] * p_cam_projection.matrix[1][1]), - (1.0f - p_cam_projection.matrix[0][2]) / p_cam_projection.matrix[0][0], - (1.0f + p_cam_projection.matrix[1][2]) / p_cam_projection.matrix[1][1] - }; - - glUniform4fv(state.ssao_shader.get_uniform(SsaoShaderGLES3::PROJ_INFO), 1, proj_info); - float pixels_per_meter = float(p_cam_projection.get_pixels_per_meter(ss[0])); - - state.ssao_shader.set_uniform(SsaoShaderGLES3::PROJ_SCALE, pixels_per_meter); - state.ssao_shader.set_uniform(SsaoShaderGLES3::BIAS, env->ssao_bias); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.linear_depth); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first - Color white(1, 1, 1, 1); - glClearBufferfv(GL_COLOR, 0, white.components); // specular - - _copy_screen(true); - - //do the batm, i mean blur - - state.ssao_blur_shader.bind(); - - if (env->ssao_filter) { - for (int i = 0; i < 2; i++) { - - state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::EDGE_SHARPNESS, env->ssao_bilateral_sharpness); - state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::FILTER_SCALE, int(env->ssao_filter)); - - GLint axis[2] = { i, 1 - i }; - glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::AXIS), 1, axis); - glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::SCREEN_SIZE), 1, ss); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[i]); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[1 - i]); - if (i == 0) { - glClearBufferfv(GL_COLOR, 0, white.components); // specular - } - _copy_screen(true); - } - } - - glDisable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - - // just copy diffuse while applying SSAO - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR, env->ssao_color); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); //previous level, since mipmaps[0] starts one level bigger - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level - _copy_screen(true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE, false); - - } else { - - //copy diffuse to effect buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].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); - } - - if (state.used_sss) { //sss enabled - //copy diffuse while performing sss - - Plane p = p_cam_projection.xform4(Plane(1, 0, -1, 1)); - p.normal /= p.d; - float unit_size = p.normal.x; - - //copy normal and roughness to effect buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT3); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[0]); - 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_LINEAR); - - state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_LOW); - state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_MEDIUM); - state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_25_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_HIGH); - state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::ENABLE_FOLLOW_SURFACE, subsurface_scatter_follow_surface); - state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::ENABLE_STRENGTH_WEIGHTING, subsurface_scatter_weight_samples); - state.sss_shader.bind(); - state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::MAX_RADIUS, subsurface_scatter_size); - state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::UNIT_SIZE, unit_size); - state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR, Vector2(1, 0)); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //disable filter (fixes bugs on AMD) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first - - _copy_screen(true); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR, Vector2(0, 1)); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level - _copy_screen(true); - - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //restore filter - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - - if (env->ssr_enabled) { - - //blur diffuse into effect mipmaps using separatable convolution - //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); - _blur_effect_buffer(); - - //perform SSR - - state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS, env->ssr_roughness); - state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - - state.ssr_shader.bind(); - - int ssr_w = storage->frame.current_rt->effects.mip_maps[1].sizes[0].width; - int ssr_h = storage->frame.current_rt->effects.mip_maps[1].sizes[0].height; - - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PIXEL_SIZE, Vector2(1.0 / (ssr_w * 0.5), 1.0 / (ssr_h * 0.5))); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PROJECTION, p_cam_projection); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::INVERSE_PROJECTION, p_cam_projection.inverse()); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::VIEWPORT_SIZE, Size2(ssr_w, ssr_h)); - //state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FRAME_INDEX,int(render_pass)); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FILTER_MIPMAP_LEVELS, float(storage->frame.current_rt->effects.mip_maps[0].sizes.size())); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::NUM_STEPS, env->ssr_max_steps); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DEPTH_TOLERANCE, env->ssr_depth_tolerance); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE, env->ssr_fade_out); - state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CURVE_FADE_IN, env->ssr_fade_in); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo); - glViewport(0, 0, ssr_w, ssr_h); - - _copy_screen(true); - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - } - - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT1); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); - //glDrawBuffer(GL_COLOR_ATTACHMENT0); - 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_NEAREST); - glReadBuffer(GL_COLOR_ATTACHMENT0); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - - //copy reflection over diffuse, resolving SSR if needed - state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR, env->ssr_enabled); - state.resolve_shader.bind(); - state.resolve_shader.set_uniform(ResolveShaderGLES3::PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - if (env->ssr_enabled) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); - } - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); //use additive to accumulate one over the other - - _copy_screen(true); - - glDisable(GL_BLEND); //end additive - - if (state.used_screen_texture) { - _blur_effect_buffer(); - //restored framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - } - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(0)); - - { - GLuint db = GL_COLOR_ATTACHMENT0; - glDrawBuffers(1, &db); - } - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - - _copy_screen(true); - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY, false); -} - -void RasterizerSceneGLES3::_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); - - //turn off everything used - - //copy specular to front buffer - //copy diffuse to effect buffer - - if (storage->frame.current_rt->buffers.active) { - //transfer to effect buffer if using buffers, also resolve MSAA - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].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_NEAREST); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - } - - if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets - //no environment or transparent render, simply return and convert to SRGB - 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); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]); - storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]); - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]); - storage->shaders.copy.bind(); - - _copy_screen(true); - - storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); //compute luminance - storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, false); - - return; - } - - //order of operation - //1) DOF Blur (first blur, then copy to buffer applying the blur) - //2) Motion Blur - //3) Bloom - //4) Tonemap - //5) Adjustments - - GLuint composite_from = storage->frame.current_rt->effects.mip_maps[0].color; - - if (env->dof_blur_far_enabled) { - - //blur diffuse into effect mipmaps using separatable convolution - //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); - - int vp_h = storage->frame.current_rt->height; - int vp_w = storage->frame.current_rt->width; - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_LOW); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, env->dof_blur_far_quality == 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(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_far_distance); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_far_distance + env->dof_blur_far_transition); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(1, 0)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, composite_from); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first - - _copy_screen(true); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(0, 1)); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level - _copy_screen(); - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false); - - composite_from = storage->frame.current_rt->effects.mip_maps[0].color; - } - - if (env->dof_blur_near_enabled) { - - //blur diffuse into effect mipmaps using separatable convolution - //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); - - int vp_h = storage->frame.current_rt->height; - int vp_w = storage->frame.current_rt->width; - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, true); - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_LOW); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, env->dof_blur_near_quality == 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(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_near_distance); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(1, 0)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far()); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, composite_from); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first - - _copy_screen(); - //manually do the blend if this is the first operation resolving from the diffuse buffer - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE, composite_from == storage->frame.current_rt->buffers.diffuse); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, false); - state.effect_blur_shader.bind(); - - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_near_distance); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(0, 1)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::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->effects.mip_maps[0].sizes[0].fbo); // copy to base level - - if (composite_from != storage->frame.current_rt->buffers.diffuse) { - - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - } else { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse); - } - - _copy_screen(true); - - if (composite_from != storage->frame.current_rt->buffers.diffuse) { - - glDisable(GL_BLEND); - } - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false); - - composite_from = storage->frame.current_rt->effects.mip_maps[0].color; - } - - if (env->dof_blur_near_enabled || env->dof_blur_far_enabled) { - //these needed to disable filtering, reenamble - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - - if (env->auto_exposure) { - - //compute auto exposure - //first step, copy from image to luminance buffer - state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN, true); - state.exposure_shader.bind(); - int ss[2] = { - storage->frame.current_rt->width, - storage->frame.current_rt->height, - }; - int ds[2] = { - exposure_shrink_size, - exposure_shrink_size, - }; - - glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE), 1, ss); - glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE), 1, ds); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, composite_from); - - glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[0].fbo); - glViewport(0, 0, exposure_shrink_size, exposure_shrink_size); - - _copy_screen(true); - - //second step, shrink to 2x2 pixels - state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN, false); - state.exposure_shader.bind(); - //shrink from second to previous to last level - - int s_size = exposure_shrink_size / 3; - for (int i = 1; i < exposure_shrink.size() - 1; i++) { - - glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[i].fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, exposure_shrink[i - 1].color); - - _copy_screen(); - - glViewport(0, 0, s_size, s_size); - - s_size /= 3; - } - //third step, shrink to 1x1 pixel taking in consideration the previous exposure - state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END, true); - - uint64_t tick = OS::get_singleton()->get_ticks_usec(); - uint64_t tick_diff = storage->frame.current_rt->last_exposure_tick == 0 ? 0 : tick - storage->frame.current_rt->last_exposure_tick; - storage->frame.current_rt->last_exposure_tick = tick; - - if (tick_diff == 0 || tick_diff > 1000000) { - state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET, true); - } - - state.exposure_shader.bind(); - - glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[exposure_shrink.size() - 1].fbo); - glViewport(0, 0, 1, 1); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, exposure_shrink[exposure_shrink.size() - 2].color); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color); //read from previous - - state.exposure_shader.set_uniform(ExposureShaderGLES3::EXPOSURE_ADJUST, env->auto_exposure_speed * (tick_diff / 1000000.0)); - state.exposure_shader.set_uniform(ExposureShaderGLES3::MAX_LUMINANCE, env->auto_exposure_max); - state.exposure_shader.set_uniform(ExposureShaderGLES3::MIN_LUMINANCE, env->auto_exposure_min); - - _copy_screen(true); - - state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET, false); - state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END, false); - - //last step, swap with the framebuffer exposure, so the right exposure is kept int he framebuffer - SWAP(exposure_shrink.write[exposure_shrink.size() - 1].fbo, storage->frame.current_rt->exposure.fbo); - SWAP(exposure_shrink.write[exposure_shrink.size() - 1].color, storage->frame.current_rt->exposure.color); - - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - - VisualServerRaster::redraw_request(); //if using auto exposure, redraw must happen - } - - int max_glow_level = -1; - int glow_mask = 0; - - if (env->glow_enabled) { - - for (int i = 0; i < VS::MAX_GLOW_LEVELS; i++) { - if (env->glow_levels & (1 << i)) { - - if (i >= storage->frame.current_rt->effects.mip_maps[1].sizes.size()) { - max_glow_level = storage->frame.current_rt->effects.mip_maps[1].sizes.size() - 1; - glow_mask |= 1 << max_glow_level; - - } else { - max_glow_level = i; - glow_mask |= (1 << i); - } - } - } - - //blur diffuse into effect mipmaps using separatable convolution - //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); - - for (int i = 0; i < (max_glow_level + 1); i++) { - - int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; - int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; - glViewport(0, 0, vp_w, vp_h); - //horizontal pass - if (i == 0) { - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS, true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE, env->auto_exposure); - } - - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_HORIZONTAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH, env->glow_strength); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LUMINANCE_CAP, env->glow_hdr_luminance_cap); - - glActiveTexture(GL_TEXTURE0); - if (i == 0) { - glBindTexture(GL_TEXTURE_2D, composite_from); - - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::EXPOSURE, env->tone_mapper_exposure); - if (env->auto_exposure) { - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::AUTO_EXPOSURE_GREY, env->auto_exposure_grey); - } - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color); - - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_BLOOM, env->glow_bloom); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_THRESHOLD, env->glow_hdr_bleed_threshold); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_SCALE, env->glow_hdr_bleed_scale); - - } else { - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger - } - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); - _copy_screen(true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_HORIZONTAL, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE, false); - - //vertical pass - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_VERTICAL, true); - state.effect_blur_shader.bind(); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); - state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH, env->glow_strength); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger - _copy_screen(); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::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); - glBindTexture(GL_TEXTURE_2D, composite_from); - - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_FILMIC); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_ACES); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINHARD_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_REINHARD); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::KEEP_3D_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]); - - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, env->auto_exposure); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, env->glow_bicubic_upscale); - - if (max_glow_level >= 0) { - - for (int i = 0; i < (max_glow_level + 1); i++) { - - if (glow_mask & (1 << i)) { - if (i == 0) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL1, true); - } - if (i == 1) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2, true); - } - if (i == 2) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3, true); - } - if (i == 3) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL4, true); - } - if (i == 4) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL5, true); - } - if (i == 5) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL6, true); - } - if (i == 6) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL7, true); - } - } - } - - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_SCREEN); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_SOFTLIGHT); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_REPLACE); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - } - - if (env->adjustments_enabled) { - - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, true); - RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(env->color_correction); - if (tex) { - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, true); - glActiveTexture(GL_TEXTURE3); - glBindTexture(tex->target, tex->tex_id); - } - } - - state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]); - state.tonemap_shader.bind(); - - state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE, env->tone_mapper_exposure); - state.tonemap_shader.set_uniform(TonemapShaderGLES3::WHITE, env->tone_mapper_exposure_white); - - if (max_glow_level >= 0) { - - state.tonemap_shader.set_uniform(TonemapShaderGLES3::GLOW_INTENSITY, env->glow_intensity); - int ss[2] = { - storage->frame.current_rt->width, - storage->frame.current_rt->height, - }; - glUniform2iv(state.tonemap_shader.get_uniform(TonemapShaderGLES3::GLOW_TEXTURE_SIZE), 1, ss); - } - - if (env->auto_exposure) { - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color); - state.tonemap_shader.set_uniform(TonemapShaderGLES3::AUTO_EXPOSURE_GREY, env->auto_exposure_grey); - } - - if (env->adjustments_enabled) { - - state.tonemap_shader.set_uniform(TonemapShaderGLES3::BCS, Vector3(env->adjustments_brightness, env->adjustments_contrast, env->adjustments_saturation)); - } - - _copy_screen(true, true); - - //turn off everything used - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINHARD_TONEMAPPER, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL1, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL4, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL5, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL6, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL7, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, false); -} - -void RasterizerSceneGLES3::render_scene(const Transform &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) { - - //first of all, make a new render pass - render_pass++; - - //fill up ubo - - storage->info.render.object_count += p_cull_count; - - Environment *env = environment_owner.getornull(p_environment); - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); - - bool use_shadows = shadow_atlas && shadow_atlas->size; - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_SHADOW, use_shadows); - - if (use_shadows) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); - state.ubo_data.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size; - state.ubo_data.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size; - } - - if (reflection_atlas && reflection_atlas->size) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); - } - - if (p_reflection_probe.is_valid()) { - state.ubo_data.reflection_multiplier = 0.0; - } else { - state.ubo_data.reflection_multiplier = 1.0; - } - - state.ubo_data.subsurface_scatter_width = subsurface_scatter_size; - - state.ubo_data.z_offset = 0; - state.ubo_data.z_slope_scale = 0; - state.ubo_data.shadow_dual_paraboloid_render_side = 0; - state.ubo_data.shadow_dual_paraboloid_render_zfar = 0; - state.ubo_data.opaque_prepass_threshold = 0.99; - - if (storage->frame.current_rt) { - int viewport_width_pixels = storage->frame.current_rt->width; - int viewport_height_pixels = storage->frame.current_rt->height; - - state.ubo_data.viewport_size[0] = viewport_width_pixels; - state.ubo_data.viewport_size[1] = viewport_height_pixels; - - state.ubo_data.screen_pixel_size[0] = 1.0 / viewport_width_pixels; - state.ubo_data.screen_pixel_size[1] = 1.0 / viewport_height_pixels; - } - - _setup_environment(env, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid()); - - bool fb_cleared = false; - - glDepthFunc(GL_LEQUAL); - - state.used_contact_shadows = false; - state.prepared_depth_texture = false; - state.bound_depth_texture = false; - - for (int i = 0; i < p_light_cull_count; i++) { - - ERR_BREAK(i >= render_list.max_lights); - - LightInstance *li = light_instance_owner.getornull(p_light_cull_result[i]); - if (li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] > CMP_EPSILON) { - state.used_contact_shadows = true; - } - } - - // Do depth prepass if it's explicitly enabled - bool use_depth_prepass = storage->config.use_depth_prepass; - - // If contact shadows are used then we need to do depth prepass even if it's otherwise disabled - use_depth_prepass = use_depth_prepass || state.used_contact_shadows; - - // Never do depth prepass if effects are disabled or if we render overdraws - use_depth_prepass = use_depth_prepass && storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; - use_depth_prepass = use_depth_prepass && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW; - - if (use_depth_prepass) { - //pre z pass - - glDisable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glDrawBuffers(0, NULL); - - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - - glColorMask(0, 0, 0, 0); - glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); - - render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, true, false); - render_list.sort_by_key(false); - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true); - _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, NULL, false, false, true, false, false); - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false); - - glColorMask(1, 1, 1, 1); - - if (state.used_contact_shadows) { - - _prepare_depth_texture(); - _bind_depth_texture(); - } - - fb_cleared = true; - render_pass++; - state.used_depth_prepass = true; - } else { - state.used_depth_prepass = false; - } - - _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_shadow_atlas); - _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_reflection_atlas, env); - - bool use_mrt = false; - - render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, false, false); - // - - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - - //rendering to a probe cubemap side - ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe); - GLuint current_fbo; - - if (probe) { - - ReflectionAtlas *ref_atlas = reflection_atlas_owner.getornull(probe->atlas); - ERR_FAIL_COND(!ref_atlas); - - int target_size = ref_atlas->size / ref_atlas->subdiv; - - int cubemap_index = reflection_cubemaps.size() - 1; - - for (int i = reflection_cubemaps.size() - 1; i >= 0; i--) { - //find appropriate cubemap to render to - if (reflection_cubemaps[i].size > target_size * 2) - break; - - cubemap_index = i; - } - - current_fbo = reflection_cubemaps[cubemap_index].fbo_id[p_reflection_probe_pass]; - use_mrt = false; - state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false); - - glViewport(0, 0, reflection_cubemaps[cubemap_index].size, reflection_cubemaps[cubemap_index].size); - glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); - - } else { - - use_mrt = env && (state.used_sss || env->ssao_enabled || env->ssr_enabled || env->dof_blur_far_enabled || env->dof_blur_near_enabled); //only enable MRT rendering if any of these is enabled - //effects disabled and transparency also prevent using MRTs - use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; - use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; - use_mrt = use_mrt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW; - use_mrt = use_mrt && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS); - - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - - if (use_mrt) { - - current_fbo = storage->frame.current_rt->buffers.fbo; - - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, true); - - Vector<GLenum> draw_buffers; - draw_buffers.push_back(GL_COLOR_ATTACHMENT0); - draw_buffers.push_back(GL_COLOR_ATTACHMENT1); - draw_buffers.push_back(GL_COLOR_ATTACHMENT2); - if (state.used_sss) { - draw_buffers.push_back(GL_COLOR_ATTACHMENT3); - } - glDrawBuffers(draw_buffers.size(), draw_buffers.ptr()); - - Color black(0, 0, 0, 0); - glClearBufferfv(GL_COLOR, 1, black.components); // specular - glClearBufferfv(GL_COLOR, 2, black.components); // normal metal rough - if (state.used_sss) { - glClearBufferfv(GL_COLOR, 3, black.components); // normal metal rough - } - - } else { - - if (storage->frame.current_rt->buffers.active) { - current_fbo = storage->frame.current_rt->buffers.fbo; - } else { - if (storage->frame.current_rt->effects.mip_maps[0].sizes.size() == 0) { - ERR_PRINT_ONCE("Can't use canvas background mode in a render target configured without sampling"); - return; - } - current_fbo = storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo; - } - - glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false); - - Vector<GLenum> draw_buffers; - draw_buffers.push_back(GL_COLOR_ATTACHMENT0); - glDrawBuffers(draw_buffers.size(), draw_buffers.ptr()); - } - } - - if (!fb_cleared) { - glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); - } - - Color clear_color(0, 0, 0, 0); - - RasterizerStorageGLES3::Sky *sky = NULL; - Ref<CameraFeed> feed; - - if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { - clear_color = Color(0, 0, 0, 0); - storage->frame.clear_request = false; - } else if (!probe && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - clear_color = Color(0, 0, 0, 0); - storage->frame.clear_request = false; - - } else if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) { - - if (storage->frame.clear_request) { - - clear_color = storage->frame.clear_request_color.to_linear(); - storage->frame.clear_request = false; - } - - } else if (env->bg_mode == VS::ENV_BG_CANVAS) { - - clear_color = env->bg_color.to_linear(); - storage->frame.clear_request = false; - } else if (env->bg_mode == VS::ENV_BG_COLOR) { - - clear_color = env->bg_color.to_linear(); - storage->frame.clear_request = false; - } else if (env->bg_mode == VS::ENV_BG_SKY) { - - storage->frame.clear_request = false; - - } else if (env->bg_mode == VS::ENV_BG_COLOR_SKY) { - - clear_color = env->bg_color.to_linear(); - storage->frame.clear_request = false; - - } else if (env->bg_mode == 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 != VS::ENV_BG_KEEP) { - glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular - } - - VS::EnvironmentBG bg_mode = (!env || (probe && env->bg_mode == VS::ENV_BG_CANVAS)) ? VS::ENV_BG_CLEAR_COLOR : env->bg_mode; //if no environment, or canvas while rendering a probe (invalid use case), use color. - - if (env) { - switch (bg_mode) { - case VS::ENV_BG_COLOR_SKY: - case VS::ENV_BG_SKY: - - sky = storage->sky_owner.getornull(env->sky); - - break; - case VS::ENV_BG_CANVAS: - //copy canvas to 3d buffer and convert it to linear - - glDisable(GL_BLEND); - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); - - storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true); - - storage->shaders.copy.bind(); - - _copy_screen(true, true); - - //turn off everything used - storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); - - //restore - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - break; - case 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(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, true); - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); - storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, 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(CopyShaderGLES3::YCBCR_TO_SRGB, 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(CopyShaderGLES3::SEP_CBCR_TEXTURE, true); - storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true); - }; - - storage->shaders.copy.bind(); - storage->shaders.copy.set_uniform(CopyShaderGLES3::DISPLAY_TRANSFORM, feed->get_transform()); - - _copy_screen(true, true); - - //turn off everything used - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, false); - storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, 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; - default: { - } - } - } - - if (probe && probe->probe_ptr->interior) { - sky = NULL; //for rendering probe interiors, radiance must not be used. - } - - state.texscreen_copied = false; - - glBlendEquation(GL_FUNC_ADD); - - if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_BLEND); - } - - render_list.sort_by_key(false); - - if (state.directional_light_count == 0) { - directional_light = NULL; - _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, false, use_shadows); - } else { - for (int i = 0; i < state.directional_light_count; i++) { - directional_light = directional_lights[i]; - if (i > 0) { - glEnable(GL_BLEND); - } - _setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows); - _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, i > 0, use_shadows); - } - } - - state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false); - - if (use_mrt) { - GLenum gldb = GL_COLOR_ATTACHMENT0; - glDrawBuffers(1, &gldb); - } - - if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || (!storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW))) { - - /* - if (use_mrt) { - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters - */ - - if (sky && sky->panorama.is_valid()) - _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); - } - - //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); - //glColorMask(1,1,1,1); - - //state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false); - - if (use_mrt) { - - _render_mrts(env, p_cam_projection); - } else { - // Here we have to do the blits/resolves that otherwise are done in the MRT rendering, in particular - // - prepare screen texture for any geometry that uses a shader with screen texture - // - prepare depth texture for any geometry that uses a shader with depth texture - - bool framebuffer_dirty = false; - - if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_screen_texture) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].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); - _blur_effect_buffer(); - framebuffer_dirty = true; - } - - if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_depth_texture) { - _prepare_depth_texture(); - framebuffer_dirty = true; - } - - if (framebuffer_dirty) { - // Restore framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - } - } - - if (storage->frame.current_rt && state.used_depth_texture && storage->frame.current_rt->buffers.active) { - _bind_depth_texture(); - } - - if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - } - - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - - render_list.sort_by_reverse_depth_and_priority(true); - - if (state.directional_light_count == 0) { - directional_light = NULL; - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, false, use_shadows); - } else { - for (int i = 0; i < state.directional_light_count; i++) { - directional_light = directional_lights[i]; - _setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows); - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, i > 0, use_shadows); - } - } - - if (probe) { - //rendering a probe, do no more! - return; - } - - if (env && (env->dof_blur_far_enabled || env->dof_blur_near_enabled) && storage->frame.current_rt && storage->frame.current_rt->buffers.active) - _prepare_depth_texture(); - _post_process(env, p_cam_projection); - // Needed only for debugging - /* if (shadow_atlas && storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if (storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color); - //glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1)); - } - - if (reflection_atlas && storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if (directional_shadow.fbo) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if ( env_radiance_tex) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, env_radiance_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - }*/ - //disable all stuff -} - -void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { - - render_pass++; - - directional_light = NULL; - - LightInstance *light_instance = light_instance_owner.getornull(p_light); - ERR_FAIL_COND(!light_instance); - RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light); - ERR_FAIL_COND(!light); - - uint32_t x, y, width, height; - - float dp_direction = 0.0; - float zfar = 0; - bool flip_facing = false; - int custom_vp_size = 0; - GLuint fbo; - int current_cubemap = -1; - float bias = 0; - float normal_bias = 0; - - state.used_depth_prepass = false; - - CameraMatrix light_projection; - Transform light_transform; - - if (light->type == VS::LIGHT_DIRECTIONAL) { - //set pssm stuff - if (light_instance->last_scene_shadow_pass != scene_pass) { - //assign rect if unassigned - 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.x; - height = light_instance->directional_rect.size.y; - - if (light->directional_shadow_mode == 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 == 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 { - //set from shadow atlas - - 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) & 0x3; - 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 == VS::LIGHT_OMNI) { - - if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE) { - - int cubemap_index = shadow_cubemaps.size() - 1; - - for (int i = shadow_cubemaps.size() - 1; i >= 0; i--) { - //find appropriate cubemap to render to - if (shadow_cubemaps[i].size > shadow_size * 2) - break; - - cubemap_index = i; - } - - fbo = shadow_cubemaps[cubemap_index].fbo_id[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 { - - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - if (light->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { - - height /= 2; - y += p_pass * height; - } else { - width /= 2; - x += p_pass * width; - } - - dp_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.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID, true); - } - - } else if (light->type == VS::LIGHT_SPOT) { - - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - dp_direction = 1.0; - 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); //shadow is front to back for performance - - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glEnable(GL_DEPTH_TEST); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glDepthMask(true); - 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); - glDisable(GL_SCISSOR_TEST); - - state.ubo_data.z_offset = bias; - state.ubo_data.z_slope_scale = normal_bias; - state.ubo_data.shadow_dual_paraboloid_render_side = dp_direction; - state.ubo_data.shadow_dual_paraboloid_render_zfar = zfar; - state.ubo_data.opaque_prepass_threshold = 0.1; - - _setup_environment(NULL, light_projection, light_transform); - - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true); - - if (light->reverse_cull) { - flip_facing = !flip_facing; - } - _render_list(render_list.elements, render_list.element_count, light_transform, light_projection, NULL, flip_facing, false, true, false, false); - - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false); - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID, false); - - if (light->type == VS::LIGHT_OMNI && light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && p_pass == 5) { - //convert the chosen cubemap to dual paraboloid! - - 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); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glDisable(GL_CULL_FACE); - - for (int i = 0; i < 2; i++) { - - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FLIP, i == 1); - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_NEAR, light_projection.get_z_near()); - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FAR, light_projection.get_z_far()); - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::BIAS, light->param[VS::LIGHT_PARAM_SHADOW_BIAS]); - - uint32_t local_width = width, local_height = height; - uint32_t local_x = x, local_y = y; - if (light->omni_shadow_detail == 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_DEPTH_TEST); - glDisable(GL_BLEND); - - _copy_screen(); - } - } - - glColorMask(1, 1, 1, 1); -} - -void RasterizerSceneGLES3::set_scene_pass(uint64_t p_pass) { - scene_pass = p_pass; -} - -bool RasterizerSceneGLES3::free(RID p_rid) { - - if (light_instance_owner.owns(p_rid)) { - - LightInstance *light_instance = light_instance_owner.getornull(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.getornull(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.getornull(p_rid); - shadow_atlas_set_size(p_rid, 0); - shadow_atlas_owner.free(p_rid); - memdelete(shadow_atlas); - } else if (reflection_atlas_owner.owns(p_rid)) { - - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_rid); - reflection_atlas_set_size(p_rid, 0); - reflection_atlas_owner.free(p_rid); - memdelete(reflection_atlas); - } else if (reflection_probe_instance_owner.owns(p_rid)) { - - ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.getornull(p_rid); - - reflection_probe_release_atlas_index(p_rid); - reflection_probe_instance_owner.free(p_rid); - memdelete(reflection_instance); - - } else if (environment_owner.owns(p_rid)) { - - Environment *environment = environment_owner.getornull(p_rid); - - environment_owner.free(p_rid); - memdelete(environment); - - } else if (gi_probe_instance_owner.owns(p_rid)) { - - GIProbeInstance *gi_probe_instance = gi_probe_instance_owner.getornull(p_rid); - - gi_probe_instance_owner.free(p_rid); - memdelete(gi_probe_instance); - - } else { - return false; - } - - return true; -} - -void RasterizerSceneGLES3::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) { - - state.debug_draw = p_debug_draw; -} - -void RasterizerSceneGLES3::initialize() { - - render_pass = 0; - - state.scene_shader.init(); - - { - //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 for shaders using world coordinates (typical for triplanar) - - 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.scene_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - glGenBuffers(1, &state.env_radiance_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_ubo, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,1000000,1")); - render_list.max_lights = GLOBAL_DEF("rendering/limits/rendering/max_renderable_lights", (int)RenderList::DEFAULT_MAX_LIGHTS); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_lights", PROPERTY_HINT_RANGE, "16,4096,1")); - render_list.max_reflections = GLOBAL_DEF("rendering/limits/rendering/max_renderable_reflections", (int)RenderList::DEFAULT_MAX_REFLECTIONS); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_reflections", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_reflections", PROPERTY_HINT_RANGE, "8,1024,1")); - - { - //quad buffers - - 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); //unbind - - glGenVertexArrays(1, &state.sky_array); - glBindVertexArray(state.sky_array); - glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, CAST_INT_TO_UCHAR_PTR(sizeof(Vector3))); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - } - render_list.init(); - state.cube_to_dp_shader.init(); - - shadow_atlas_realloc_tolerance_msec = 500; - - 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); - //gen cubemap first - for (int i = 0; i < 6; i++) { - - glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT24, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - } - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // Remove artifact on the edges of the shadowmap - 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); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - //gen renderbuffers second, because it needs a complete cubemap - for (int i = 0; i < 6; i++) { - - glGenFramebuffers(1, &cube.fbo_id[i]); - glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo_id[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _cube_side_enum[i], cube.cubemap, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); - } - - shadow_cubemaps.push_back(cube); - - cube_size >>= 1; - } - - { - //directional light shadow - 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); - glGenTextures(1, &directional_shadow.depth); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - 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); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, 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"); - } - } - - { - //spot and omni ubos - - int max_ubo_size; - glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_ubo_size); - const int ubo_light_size = 160; - state.ubo_light_size = ubo_light_size; - state.max_ubo_lights = MIN(render_list.max_lights, max_ubo_size / ubo_light_size); - - state.spot_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights); - state.omni_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights); - - glGenBuffers(1, &state.spot_array_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo); - glBufferData(GL_UNIFORM_BUFFER, ubo_light_size * state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - glGenBuffers(1, &state.omni_array_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo); - glBufferData(GL_UNIFORM_BUFFER, ubo_light_size * state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - glGenBuffers(1, &state.directional_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDataUBO), NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - state.max_forward_lights_per_object = 8; - - state.scene_shader.add_custom_define("#define MAX_LIGHT_DATA_STRUCTS " + itos(state.max_ubo_lights) + "\n"); - state.scene_shader.add_custom_define("#define MAX_FORWARD_LIGHTS " + itos(state.max_forward_lights_per_object) + "\n"); - - state.max_ubo_reflections = MIN(render_list.max_reflections, max_ubo_size / (int)sizeof(ReflectionProbeDataUBO)); - - state.reflection_array_tmp = (uint8_t *)memalloc(sizeof(ReflectionProbeDataUBO) * state.max_ubo_reflections); - - glGenBuffers(1, &state.reflection_array_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, state.reflection_array_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeDataUBO) * state.max_ubo_reflections, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - state.scene_shader.add_custom_define("#define MAX_REFLECTION_DATA_STRUCTS " + itos(state.max_ubo_reflections) + "\n"); - - state.max_skeleton_bones = MIN(2048, max_ubo_size / (12 * sizeof(float))); - state.scene_shader.add_custom_define("#define MAX_SKELETON_BONES " + itos(state.max_skeleton_bones) + "\n"); - } - - shadow_filter_mode = SHADOW_FILTER_NEAREST; - - { //reflection cubemaps - int max_reflection_cubemap_sampler_size = 512; - - int rcube_size = max_reflection_cubemap_sampler_size; - - glActiveTexture(GL_TEXTURE0); - - bool use_float = true; - - GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; - GLenum format = GL_RGBA; - GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - - while (rcube_size >= 32) { - - ReflectionCubeMap cube; - cube.size = rcube_size; - - glGenTextures(1, &cube.depth); - glBindTexture(GL_TEXTURE_2D, cube.depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 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); - - glGenTextures(1, &cube.cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap); - //gen cubemap first - for (int i = 0; i < 6; i++) { - - glTexImage2D(_cube_side_enum[i], 0, internal_format, cube.size, cube.size, 0, format, type, NULL); - } - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // Remove artifact on the edges of the reflectionmap - 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); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - //gen renderbuffers second, because it needs a complete cubemap - for (int i = 0; i < 6; i++) { - - glGenFramebuffers(1, &cube.fbo_id[i]); - glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo_id[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], cube.cubemap, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, cube.depth, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); - } - - reflection_cubemaps.push_back(cube); - - rcube_size >>= 1; - } - } - - { - - 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); - - glGenVertexArrays(1, &state.immediate_array); - } - -#ifdef GLES_OVER_GL - //"desktop" opengl needs this. - glEnable(GL_PROGRAM_POINT_SIZE); - -#endif - - state.resolve_shader.init(); - state.ssr_shader.init(); - state.effect_blur_shader.init(); - state.sss_shader.init(); - state.ssao_minify_shader.init(); - state.ssao_shader.init(); - state.ssao_blur_shader.init(); - state.exposure_shader.init(); - state.tonemap_shader.init(); - - { - GLOBAL_DEF("rendering/quality/subsurface_scattering/quality", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/quality", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/quality", PROPERTY_HINT_ENUM, "Low,Medium,High")); - GLOBAL_DEF("rendering/quality/subsurface_scattering/scale", 1.0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/scale", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/scale", PROPERTY_HINT_RANGE, "0.01,8,0.01")); - GLOBAL_DEF("rendering/quality/subsurface_scattering/follow_surface", false); - GLOBAL_DEF("rendering/quality/subsurface_scattering/weight_samples", true); - - GLOBAL_DEF("rendering/quality/voxel_cone_tracing/high_quality", false); - } - - exposure_shrink_size = 243; - int max_exposure_shrink_size = exposure_shrink_size; - - while (max_exposure_shrink_size > 0) { - - RasterizerStorageGLES3::RenderTarget::Exposure e; - - glGenFramebuffers(1, &e.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, e.fbo); - - glGenTextures(1, &e.color); - glBindTexture(GL_TEXTURE_2D, e.color); - - if (storage->config.framebuffer_float_supported) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); - } else if (storage->config.framebuffer_half_float_supported) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_HALF_FLOAT, NULL); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_UNSIGNED_INT_2_10_10_10_REV, NULL); - } - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e.color, 0); - 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); - - exposure_shrink.push_back(e); - max_exposure_shrink_size /= 3; - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); - } - - state.debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; - - glFrontFace(GL_CW); -} - -void RasterizerSceneGLES3::iteration() { - - shadow_filter_mode = ShadowFilterMode(int(GLOBAL_GET("rendering/quality/shadows/filter_mode"))); - subsurface_scatter_follow_surface = GLOBAL_GET("rendering/quality/subsurface_scattering/follow_surface"); - subsurface_scatter_weight_samples = GLOBAL_GET("rendering/quality/subsurface_scattering/weight_samples"); - subsurface_scatter_quality = SubSurfaceScatterQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/quality"))); - subsurface_scatter_size = GLOBAL_GET("rendering/quality/subsurface_scattering/scale"); - - state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH, GLOBAL_GET("rendering/quality/voxel_cone_tracing/high_quality")); -} - -void RasterizerSceneGLES3::finalize() { - - storage->free(default_material); - storage->free(default_material_twosided); - storage->free(default_shader); - storage->free(default_shader_twosided); - - storage->free(default_worldcoord_material); - storage->free(default_worldcoord_material_twosided); - storage->free(default_worldcoord_shader); - storage->free(default_worldcoord_shader_twosided); - - storage->free(default_overdraw_material); - storage->free(default_overdraw_shader); -} - -RasterizerSceneGLES3::RasterizerSceneGLES3() { -} - -RasterizerSceneGLES3::~RasterizerSceneGLES3() { - - memfree(state.spot_array_tmp); - memfree(state.omni_array_tmp); - memfree(state.reflection_array_tmp); -} diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h deleted file mode 100644 index abf6bb24cf..0000000000 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ /dev/null @@ -1,878 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_gles3.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. */ -/*************************************************************************/ - -#ifndef RASTERIZERSCENEGLES3_H -#define RASTERIZERSCENEGLES3_H - -/* Must come before shaders or the Windows build fails... */ -#include "rasterizer_storage_gles3.h" - -#include "drivers/gles3/shaders/cube_to_dp.glsl.gen.h" -#include "drivers/gles3/shaders/effect_blur.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" -#include "drivers/gles3/shaders/tonemap.glsl.gen.h" - -class RasterizerSceneGLES3 : public RasterizerScene { -public: - enum ShadowFilterMode { - SHADOW_FILTER_NEAREST, - SHADOW_FILTER_PCF5, - SHADOW_FILTER_PCF13, - }; - - ShadowFilterMode shadow_filter_mode; - - uint64_t shadow_atlas_realloc_tolerance_msec; - - enum SubSurfaceScatterQuality { - SSS_QUALITY_LOW, - SSS_QUALITY_MEDIUM, - SSS_QUALITY_HIGH, - }; - - SubSurfaceScatterQuality subsurface_scatter_quality; - float subsurface_scatter_size; - bool subsurface_scatter_follow_surface; - bool subsurface_scatter_weight_samples; - - uint64_t render_pass; - uint64_t scene_pass; - uint32_t current_material_index; - uint32_t current_geometry_index; - - 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; - - RasterizerStorageGLES3 *storage; - - Vector<RasterizerStorageGLES3::RenderTarget::Exposure> exposure_shrink; - int exposure_shrink_size; - - 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; - - SceneShaderGLES3 scene_shader; - CubeToDpShaderGLES3 cube_to_dp_shader; - 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; - TonemapShaderGLES3 tonemap_shader; - - struct SceneDataUBO { - //this is a std140 compatible struct. Please read the OpenGL 3.3 Specification 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; - float ambient_occlusion_affect_ssao; - float opaque_prepass_threshold; - - uint32_t fog_depth_enabled; - float fog_depth_begin; - float fog_depth_end; - float fog_density; - 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 - float pad[2]; - - } 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_verts; - 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 cull_front; - bool cull_disabled; - bool used_sss; - bool used_screen_texture; - - bool used_depth_prepass; - - bool used_depth_texture; - bool prepared_depth_texture; - bool bound_depth_texture; - - VS::ViewportDebugDraw debug_draw; - } state; - - /* SHADOW ATLAS API */ - - struct ShadowAtlas { - - 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; //not in use - } - - } quadrants[4]; - - int size_order[4]; - uint32_t smallest_subdiv; - - int size; - - GLuint fbo; - GLuint depth; - - Map<RID, uint32_t> shadow_owners; - }; - - struct ShadowCubeMap { - - GLuint fbo_id[6]; - GLuint cubemap; - uint32_t size; - }; - - Vector<ShadowCubeMap> shadow_cubemaps; - - RID_PtrOwner<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; - 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 */ - - struct ReflectionAtlas { - - int subdiv; - int size; - - struct Reflection { - RID owner; - uint64_t last_frame; - }; - - GLuint fbo[6]; - GLuint color; - - Vector<Reflection> reflections; - }; - - mutable RID_PtrOwner<ReflectionAtlas> reflection_atlas_owner; - - virtual RID reflection_atlas_create(); - virtual void reflection_atlas_configure(RID p_ref_atlas, int p_size, int p_count); - - /* REFLECTION CUBEMAPS */ - - struct ReflectionCubeMap { - - GLuint fbo_id[6]; - GLuint cubemap; - GLuint depth; - int size; - }; - - Vector<ReflectionCubeMap> reflection_cubemaps; - - /* REFLECTION PROBE INSTANCE */ - - struct ReflectionProbeInstance { - - RasterizerStorageGLES3::ReflectionProbe *probe_ptr; - RID probe; - RID self; - RID atlas; - - int reflection_atlas_index; - - int render_step; - - uint64_t last_pass; - int reflection_index; - - Transform transform; - }; - - struct ReflectionProbeDataUBO { - - float box_extents[4]; - float box_ofs[4]; - float params[4]; // intensity, 0, 0, boxproject - float ambient[4]; //color, probe contrib - float atlas_clamp[4]; - float local_matrix[16]; //up to here for spot and omni, rest is for directional - //notes: for ambientblend, use distance to edge to blend between already existing global environment - }; - - mutable RID_PtrOwner<ReflectionProbeInstance> reflection_probe_instance_owner; - - virtual RID reflection_probe_instance_create(RID p_probe); - virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &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 { - - 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 ssr_enabled; - int ssr_max_steps; - float ssr_fade_in; - float ssr_fade_out; - float ssr_depth_tolerance; - bool ssr_roughness; - - bool ssao_enabled; - float ssao_intensity; - float ssao_radius; - float ssao_intensity2; - float ssao_radius2; - float ssao_bias; - float ssao_light_affect; - float ssao_ao_channel_affect; - Color ssao_color; - VS::EnvironmentSSAOQuality ssao_quality; - float ssao_bilateral_sharpness; - VS::EnvironmentSSAOBlur ssao_filter; - - 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; - - VS::EnvironmentToneMapper tone_mapper; - float tone_mapper_exposure; - float tone_mapper_exposure_white; - bool auto_exposure; - float auto_exposure_speed; - float auto_exposure_min; - float auto_exposure_max; - float auto_exposure_grey; - - 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(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), - ssr_enabled(false), - ssr_max_steps(64), - ssr_fade_in(0.15), - ssr_fade_out(2.0), - ssr_depth_tolerance(0.2), - ssr_roughness(true), - ssao_enabled(false), - ssao_intensity(1.0), - ssao_radius(1.0), - ssao_intensity2(1.0), - ssao_radius2(0.0), - ssao_bias(0.01), - ssao_light_affect(0), - ssao_ao_channel_affect(0), - ssao_quality(VS::ENV_SSAO_QUALITY_LOW), - ssao_bilateral_sharpness(4), - ssao_filter(VS::ENV_SSAO_BLUR_3x3), - glow_enabled(false), - glow_levels((1 << 2) | (1 << 4)), - glow_intensity(0.8), - glow_strength(1.0), - glow_bloom(0.0), - glow_blend_mode(VS::ENV_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), - tone_mapper(VS::ENV_TONE_MAPPER_LINEAR), - tone_mapper_exposure(1.0), - tone_mapper_exposure_white(1.0), - auto_exposure(false), - auto_exposure_speed(0.5), - auto_exposure_min(0.05), - auto_exposure_max(8), - auto_exposure_grey(0.4), - 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(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(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) { - } - }; - - RID_PtrOwner<Environment> environment_owner; - - virtual RID environment_create(); - - virtual void environment_set_background(RID p_env, 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, 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, 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, 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, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); - - virtual void environment_set_tonemap(RID p_env, 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 VS::EnvironmentBG environment_get_background(RID p_env); - virtual int environment_get_canvas_max_layer(RID p_env); - - /* LIGHT INSTANCE */ - - struct LightDataUBO { - - float light_pos_inv_radius[4]; - float light_direction_attenuation[4]; - float light_color_energy[4]; - float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled - float light_clamp[4]; - float light_shadow_color_contact[4]; - union { - struct { - float matrix1[16]; //up to here for spot and omni, rest is for directional - float matrix2[16]; - float matrix3[16]; - float matrix4[16]; - }; - float matrix[4 * 16]; - } shadow; - float shadow_split_offsets[4]; - }; - - struct LightInstance { - - struct ShadowTransform { - - CameraMatrix camera; - Transform transform; - float farplane; - float split; - float bias_scale; - }; - - ShadowTransform shadow_transform[4]; - - RID self; - RID light; - RasterizerStorageGLES3::Light *light_ptr; - Transform transform; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - uint64_t shadow_pass; - uint64_t last_scene_pass; - uint64_t last_scene_shadow_pass; - uint64_t last_pass; - uint16_t light_index; - uint16_t light_directional_index; - - uint32_t current_shadow_atlas_key; - - Vector2 dp; - - Rect2 directional_rect; - - Set<RID> shadow_atlases; //shadow atlases where this light is registered - - LightInstance() {} - }; - - mutable RID_PtrOwner<LightInstance> light_instance_owner; - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform); - virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &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); - - /* REFLECTION INSTANCE */ - - struct GIProbeInstance { - RID data; - RasterizerStorageGLES3::GIProbe *probe; - GLuint tex_cache; - Vector3 cell_size_cache; - Vector3 bounds; - Transform transform_to_data; - - GIProbeInstance() : - probe(NULL), - tex_cache(0) { - } - }; - - mutable RID_PtrOwner<GIProbeInstance> gi_probe_instance_owner; - - 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 Transform &p_xform); - virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds); - - /* RENDER LIST */ - - struct RenderList { - - enum { - DEFAULT_MAX_ELEMENTS = 65536, - SORT_FLAG_SKELETON = 1, - SORT_FLAG_INSTANCING = 2, - MAX_DIRECTIONAL_LIGHTS = 16, - DEFAULT_MAX_LIGHTS = 4096, - DEFAULT_MAX_REFLECTIONS = 1024, - - SORT_KEY_PRIORITY_SHIFT = 56, - SORT_KEY_PRIORITY_MASK = 0xFF, - //depth layer for opaque (56-52) - SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT = 52, - SORT_KEY_OPAQUE_DEPTH_LAYER_MASK = 0xF, -//64 bits unsupported in MSVC -#define SORT_KEY_UNSHADED_FLAG (uint64_t(1) << 49) -#define SORT_KEY_NO_DIRECTIONAL_FLAG (uint64_t(1) << 48) -#define SORT_KEY_LIGHTMAP_CAPTURE_FLAG (uint64_t(1) << 47) -#define SORT_KEY_LIGHTMAP_FLAG (uint64_t(1) << 46) -#define SORT_KEY_GI_PROBES_FLAG (uint64_t(1) << 45) -#define SORT_KEY_VERTEX_LIT_FLAG (uint64_t(1) << 44) - SORT_KEY_SHADING_SHIFT = 44, - SORT_KEY_SHADING_MASK = 63, - //44-28 material index - SORT_KEY_MATERIAL_INDEX_SHIFT = 28, - //28-8 geometry index - SORT_KEY_GEOMETRY_INDEX_SHIFT = 8, - //bits 5-7 geometry type - SORT_KEY_GEOMETRY_TYPE_SHIFT = 5, - //bits 0-5 for flags - SORT_KEY_OPAQUE_PRE_PASS = 8, - SORT_KEY_CULL_DISABLED_FLAG = 4, - SORT_KEY_SKELETON_FLAG = 2, - SORT_KEY_MIRROR_FLAG = 1 - - }; - - int max_elements; - int max_lights; - int max_reflections; - - struct Element { - - RasterizerScene::InstanceBase *instance; - RasterizerStorageGLES3::Geometry *geometry; - RasterizerStorageGLES3::Material *material; - RasterizerStorageGLES3::GeometryOwner *owner; - 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; - } - - //should eventually be replaced by radix - - struct SortByKey { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - return A->sort_key < B->sort_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 { - uint32_t layer_A = uint32_t(A->sort_key >> SORT_KEY_PRIORITY_SHIFT); - uint32_t layer_B = uint32_t(B->sort_key >> SORT_KEY_PRIORITY_SHIFT); - if (layer_A == layer_B) { - return A->instance->depth > B->instance->depth; - } else { - return layer_A < layer_B; - } - } - }; - - 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); - } - } - - _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]; // assign elements - } - - RenderList() { - - max_elements = DEFAULT_MAX_ELEMENTS; - max_lights = DEFAULT_MAX_LIGHTS; - max_reflections = DEFAULT_MAX_REFLECTIONS; - } - - ~RenderList() { - memdelete_arr(elements); - memdelete_arr(base_elements); - } - }; - - LightInstance *directional_light; - LightInstance *directional_lights[RenderList::MAX_DIRECTIONAL_LIGHTS]; - - RenderList render_list; - - _FORCE_INLINE_ void _set_cull(bool p_front, bool p_disabled, bool p_reverse_cull); - - _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_alpha_pass); - _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e, const Transform &p_view_transform); - _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); - _FORCE_INLINE_ void _setup_light(RenderList::Element *e, const Transform &p_view_transform); - - void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RasterizerStorageGLES3::Sky *p_sky, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows); - - _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass); - - _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_shadow_pass); - - void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation); - - void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog = false); - void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows); - void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas); - void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env); - - void _copy_screen(bool p_invalidate_color = false, bool p_invalidate_depth = false); - void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug - - void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass); - - void _blur_effect_buffer(); - void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection); - void _post_process(Environment *env, const CameraMatrix &p_cam_projection); - - void _prepare_depth_texture(); - void _bind_depth_texture(); - - virtual void render_scene(const Transform &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(VS::ViewportDebugDraw p_debug_draw); - - void iteration(); - void initialize(); - void finalize(); - RasterizerSceneGLES3(); - ~RasterizerSceneGLES3(); -}; - -#endif // RASTERIZERSCENEGLES3_H diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp deleted file mode 100644 index 0aee19784e..0000000000 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ /dev/null @@ -1,8404 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_gles3.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_storage_gles3.h" -#include "core/engine.h" -#include "core/project_settings.h" -#include "rasterizer_canvas_gles3.h" -#include "rasterizer_scene_gles3.h" - -/* TEXTURE API */ - -#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_S3TC_DXT1_EXT 0x83F1 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - -#define _EXT_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 -#define _EXT_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 -#define _EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 -#define _EXT_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 - -#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_SLUMINANCE_NV 0x8C46 -#define _EXT_SLUMINANCE_ALPHA_NV 0x8C44 -#define _EXT_SRGB8_NV 0x8C41 -#define _EXT_SLUMINANCE8_NV 0x8C47 -#define _EXT_SLUMINANCE8_ALPHA8_NV 0x8C45 - -#define _EXT_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C -#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D -#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E -#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F - -#define _EXT_ATC_RGB_AMD 0x8C92 -#define _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 -#define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE - -#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F - -#define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF - -#define _EXT_COMPRESSED_R11_EAC 0x9270 -#define _EXT_COMPRESSED_SIGNED_R11_EAC 0x9271 -#define _EXT_COMPRESSED_RG11_EAC 0x9272 -#define _EXT_COMPRESSED_SIGNED_RG11_EAC 0x9273 -#define _EXT_COMPRESSED_RGB8_ETC2 0x9274 -#define _EXT_COMPRESSED_SRGB8_ETC2 0x9275 -#define _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 -#define _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 -#define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278 -#define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 - -#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 - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf -#endif - -#ifdef __EMSCRIPTEN__ -#include <emscripten/emscripten.h> - -void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) { - - /* clang-format off */ - EM_ASM({ - GLctx.getBufferSubData($0, $1, HEAPU8, $2, $3); - }, target, offset, data, size); - /* clang-format on */ -} -#endif - -void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) { - -#ifdef GLES_OVER_GL - - for (int i = 0; i < levels; i++) { - glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL); - width = MAX(1, (width / 2)); - height = MAX(1, (height / 2)); - } - -#else - glTexStorage2D(target, levels, internalformat, width, height); -#endif -} - -GLuint RasterizerStorageGLES3::system_fbo = 0; - -Ref<Image> RasterizerStorageGLES3::_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 &r_srgb, bool p_force_decompress) const { - - r_compressed = false; - r_gl_format = 0; - r_real_format = p_format; - Ref<Image> image = p_image; - r_srgb = false; - - bool need_decompress = false; - - switch (p_format) { - - case Image::FORMAT_L8: { -#ifdef GLES_OVER_GL - r_gl_internal_format = GL_R8; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; -#else - r_gl_internal_format = GL_LUMINANCE; - r_gl_format = GL_LUMINANCE; - r_gl_type = GL_UNSIGNED_BYTE; -#endif - } break; - case Image::FORMAT_LA8: { -#ifdef GLES_OVER_GL - r_gl_internal_format = GL_RG8; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; -#else - r_gl_internal_format = GL_LUMINANCE_ALPHA; - r_gl_format = GL_LUMINANCE_ALPHA; - r_gl_type = GL_UNSIGNED_BYTE; -#endif - } break; - case Image::FORMAT_R8: { - - r_gl_internal_format = GL_R8; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RG8: { - - r_gl_internal_format = GL_RG8; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RGB8: { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8 : GL_RGB8; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - r_srgb = true; - - } break; - case Image::FORMAT_RGBA8: { - - r_gl_format = GL_RGBA; - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8_ALPHA8 : GL_RGBA8; - r_gl_type = GL_UNSIGNED_BYTE; - r_srgb = true; - - } break; - case Image::FORMAT_RGBA4444: { - - r_gl_internal_format = GL_RGBA4; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4; - - } break; - case Image::FORMAT_RGB565: { - - 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: { - - r_gl_internal_format = GL_R32F; - r_gl_format = GL_RED; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGF: { - - r_gl_internal_format = GL_RG32F; - r_gl_format = GL_RG; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGBF: { - - r_gl_internal_format = GL_RGB32F; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGBAF: { - - r_gl_internal_format = GL_RGBA32F; - r_gl_format = GL_RGBA; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RH: { - r_gl_internal_format = GL_R32F; - r_gl_format = GL_RED; - r_gl_type = GL_HALF_FLOAT; - } break; - case Image::FORMAT_RGH: { - r_gl_internal_format = GL_RG32F; - r_gl_format = GL_RG; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBH: { - r_gl_internal_format = GL_RGB32F; - r_gl_format = GL_RGB; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBAH: { - r_gl_internal_format = GL_RGBA32F; - r_gl_format = GL_RGBA; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBE9995: { - r_gl_internal_format = GL_RGB9_E5; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV; - - } break; - case Image::FORMAT_DXT1: { - - if (config.s3tc_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - - } break; - case Image::FORMAT_DXT3: { - - if (config.s3tc_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - - } break; - case Image::FORMAT_DXT5: { - - if (config.s3tc_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = 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 = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : _EXT_COMPRESSED_RGBA_BPTC_UNORM; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = 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; - case Image::FORMAT_PVRTC2: { - - if (config.pvrtc_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - } break; - case Image::FORMAT_PVRTC2A: { - - if (config.pvrtc_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - - } break; - case Image::FORMAT_PVRTC4: { - - if (config.pvrtc_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - - } break; - case Image::FORMAT_PVRTC4A: { - - if (config.pvrtc_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - - } break; - case Image::FORMAT_ETC: { - - if (config.etc_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: { - - if (config.etc2_supported) { - - r_gl_internal_format = _EXT_COMPRESSED_R11_EAC; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_R11S: { - - if (config.etc2_supported) { - - r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RG11: { - - if (config.etc2_supported) { - - r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RG11S: { - if (config.etc2_supported) { - - r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RGB8: { - - if (config.etc2_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB8_ETC2 : _EXT_COMPRESSED_RGB8_ETC2; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RGBA8: { - - if (config.etc2_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : _EXT_COMPRESSED_RGBA8_ETC2_EAC; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RGB8A1: { - - if (config.etc2_supported) { - - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - r_srgb = true; - - } else { - - 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); - image->convert(Image::FORMAT_RGBA8); - } - - r_gl_format = GL_RGBA; - r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8_ALPHA8 : GL_RGBA8; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = false; - r_real_format = Image::FORMAT_RGBA8; - r_srgb = true; - - return image; - } - - return 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 RasterizerStorageGLES3::texture_create() { - - 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 RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VisualServer::TextureType p_type, uint32_t p_flags) { - - GLenum format; - GLenum internal_format; - GLenum type; - - bool compressed; - bool srgb; - - if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { - p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video - } - -#ifndef GLES_OVER_GL - switch (p_format) { - case Image::FORMAT_RF: - case Image::FORMAT_RGF: - case Image::FORMAT_RGBF: - case Image::FORMAT_RGBAF: - case Image::FORMAT_RH: - case Image::FORMAT_RGH: - case Image::FORMAT_RGBH: - case Image::FORMAT_RGBAH: { - if (!config.texture_float_linear_supported) { - // disable linear texture filtering when not supported for float format on some devices (issue #24295) - p_flags &= ~VS::TEXTURE_FLAG_FILTER; - } - } break; - default: { - } - } -#endif - - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - texture->width = p_width; - texture->height = p_height; - texture->depth = p_depth_3d; - texture->format = p_format; - texture->flags = p_flags; - texture->stored_cube_sides = 0; - - texture->type = p_type; - - switch (p_type) { - case VS::TEXTURE_TYPE_2D: { - texture->target = GL_TEXTURE_2D; - texture->images.resize(1); - } break; - case VS::TEXTURE_TYPE_CUBEMAP: { - texture->target = GL_TEXTURE_CUBE_MAP; - texture->images.resize(6); - } break; - case VS::TEXTURE_TYPE_2D_ARRAY: { - texture->target = GL_TEXTURE_2D_ARRAY; - texture->images.resize(p_depth_3d); - } break; - case VS::TEXTURE_TYPE_3D: { - texture->target = GL_TEXTURE_3D; - texture->images.resize(p_depth_3d); - } break; - } - - texture->is_npot_repeat_mipmap = false; -#ifdef JAVASCRIPT_ENABLED - // WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT) - // textures with repeat/mipmaps, even though NPOT textures should be supported as per the spec. - // Force decompressing them to work it around on WebGL 2.0 at a performance cost (GH-33058). - 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 & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) { - texture->is_npot_repeat_mipmap = true; - } -#endif // JAVASCRIPT_ENABLED - - Image::Format real_format; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap); - - texture->alloc_width = texture->width; - texture->alloc_height = texture->height; - texture->alloc_depth = texture->depth; - - texture->gl_format_cache = format; - texture->gl_type_cache = type; - texture->gl_internal_format_cache = internal_format; - texture->compressed = compressed; - texture->srgb = srgb; - texture->data_size = 0; - texture->mipmaps = 1; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - if (p_type == VS::TEXTURE_TYPE_3D || p_type == VS::TEXTURE_TYPE_2D_ARRAY) { - - int width = p_width; - int height = p_height; - int depth = p_depth_3d; - - int mipmaps = 0; - - while (width > 0 || height > 0 || (p_type == VS::TEXTURE_TYPE_3D && depth > 0)) { - width = MAX(1, width); - height = MAX(1, height); - depth = MAX(1, depth); - - glTexImage3D(texture->target, mipmaps, internal_format, width, height, depth, 0, format, type, NULL); - - width /= 2; - height /= 2; - - if (p_type == VS::TEXTURE_TYPE_3D) { - depth /= 2; - } - - mipmaps++; - - if (!(p_flags & VS::TEXTURE_FLAG_MIPMAPS)) - break; - } - - glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1); - - } else if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { - //prealloc if video - glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, type, NULL); - } - - texture->active = true; -} - -void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) { - - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(texture->format != p_image->get_format()); - ERR_FAIL_COND(p_image.is_null()); - - GLenum type; - GLenum format; - GLenum internal_format; - bool compressed; - bool srgb; - - if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->images.write[p_layer] = p_image; - } - - 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, srgb, texture->is_npot_repeat_mipmap); - - if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::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 = GL_TEXTURE_2D; - - switch (texture->type) { - case VS::TEXTURE_TYPE_2D: { - blit_target = GL_TEXTURE_2D; - } break; - case VS::TEXTURE_TYPE_CUBEMAP: { - ERR_FAIL_INDEX(p_layer, 6); - blit_target = _cube_side_enum[p_layer]; - } break; - case VS::TEXTURE_TYPE_2D_ARRAY: { - blit_target = GL_TEXTURE_2D_ARRAY; - } break; - case VS::TEXTURE_TYPE_3D: { - blit_target = GL_TEXTURE_3D; - } break; - } - - texture->data_size = img->get_data().size(); - PoolVector<uint8_t>::Read read = img->get_data().read(); - ERR_FAIL_COND(!read.ptr()); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - texture->ignore_mipmaps = compressed && !img->has_mipmaps(); - - if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); - else { - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - } - - if (config.srgb_decode_supported && srgb) { - - if (texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); - texture->using_srgb = true; - } else { - glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); - texture->using_srgb = false; - } - } - - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering - } - - if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { - - if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - } else { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - } else { - - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - -//set swizle for older format compatibility -#ifdef GLES_OVER_GL - switch (texture->format) { - - case Image::FORMAT_L8: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE); - - } break; - case Image::FORMAT_LA8: { - - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN); - } break; - default: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); - - } break; - } -#endif - if (config.use_anisotropic_filter) { - - if (texture->flags & VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { - - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config.anisotropic_level); - } else { - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); - } - } - - int mipmaps = ((texture->flags & VS::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 (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) { - - if (texture->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 & VS::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]); - } - } - } else { - if (texture->compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - - int bw = w; - int bh = h; - - glCompressedTexSubImage3D(blit_target, i, 0, 0, p_layer, bw, bh, 1, internal_format, size, &read[ofs]); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glTexSubImage3D(blit_target, i, 0, 0, p_layer, w, h, 1, format, type, &read[ofs]); - } - } - tsize += size; - - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); - } - - // Handle array and 3D textures, as those set their data per layer. - tsize *= MAX(texture->alloc_depth, 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,_rinfo.texture_mem); - - texture->stored_cube_sides |= (1 << p_layer); - - if ((texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) && (texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != VS::TEXTURE_TYPE_CUBEMAP || texture->stored_cube_sides == (1 << 6) - 1)) { - //generate mipmaps if they were requested and the image does not contain them - glGenerateMipmap(texture->target); - } else if (mipmaps > 1) { - glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1); - } else { - glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, 0); - } - - texture->mipmaps = mipmaps; - - //texture_set_flags(p_texture,texture->flags); -} - -// Uploads pixel data to a sub-region of a texture, for the specified mipmap. -// The texture pixels must have been allocated before, because most features seen in texture_set_data() make no sense in a partial update. -// TODO If we want this to be usable without pre-filling pixels with a full image, we have to call glTexImage2D() with null data. -void RasterizerStorageGLES3::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) { - - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(texture->format != p_image->get_format()); - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(src_w <= 0 || src_h <= 0); - ERR_FAIL_COND(src_x < 0 || src_y < 0 || src_x + src_w > p_image->get_width() || src_y + src_h > p_image->get_height()); - ERR_FAIL_COND(dst_x < 0 || dst_y < 0 || dst_x + src_w > texture->alloc_width || dst_y + src_h > texture->alloc_height); - ERR_FAIL_COND(p_dst_mip < 0 || p_dst_mip >= texture->mipmaps); - - GLenum type; - GLenum format; - GLenum internal_format; - bool compressed; - bool srgb; - - // Because OpenGL wants data as a dense array, we have to extract the sub-image if the source rect isn't the full image - Ref<Image> p_sub_img = p_image; - if (src_x > 0 || src_y > 0 || src_w != p_image->get_width() || src_h != p_image->get_height()) { - p_sub_img = p_image->get_rect(Rect2(src_x, src_y, src_w, src_h)); - } - - Image::Format real_format; - Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap); - - GLenum blit_target = GL_TEXTURE_2D; - - switch (texture->type) { - case VS::TEXTURE_TYPE_2D: { - blit_target = GL_TEXTURE_2D; - } break; - case VS::TEXTURE_TYPE_CUBEMAP: { - ERR_FAIL_INDEX(p_layer, 6); - blit_target = _cube_side_enum[p_layer]; - } break; - case VS::TEXTURE_TYPE_2D_ARRAY: { - blit_target = GL_TEXTURE_2D_ARRAY; - } break; - case VS::TEXTURE_TYPE_3D: { - blit_target = GL_TEXTURE_3D; - } break; - } - - PoolVector<uint8_t>::Read read = img->get_data().read(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - int src_data_size = img->get_data().size(); - int src_ofs = 0; - - if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) { - if (texture->compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glCompressedTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, internal_format, src_data_size, &read[src_ofs]); - - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // `format` has to match the internal_format used when the texture was created - glTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, format, type, &read[src_ofs]); - } - } else { - if (texture->compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glCompressedTexSubImage3D(blit_target, p_dst_mip, dst_x, dst_y, p_layer, src_w, src_h, 1, format, src_data_size, &read[src_ofs]); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // `format` has to match the internal_format used when the texture was created - glTexSubImage3D(blit_target, p_dst_mip, dst_x, dst_y, p_layer, src_w, src_h, 1, format, type, &read[src_ofs]); - } - } - - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering - } -} - -Ref<Image> RasterizerStorageGLES3::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 == VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && !texture->images[p_layer].is_null()) { - return texture->images[p_layer]; - } - - // 3D textures and 2D texture arrays need special treatment, as the glGetTexImage reads **the whole** - // texture to host-memory. 3D textures and 2D texture arrays are potentially very big, so reading - // everything just to throw everything but one layer away is A Bad Idea. - // - // Unfortunately, to solve this, the copy shader has to read the data out via a shader and store it - // in a temporary framebuffer. The data from the framebuffer can then be read using glReadPixels. - if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY || texture->type == VS::TEXTURE_TYPE_3D) { - // can't read a layer that doesn't exist - ERR_FAIL_INDEX_V(p_layer, texture->alloc_depth, Ref<Image>()); - - // get some information about the texture - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - - bool compressed; - bool srgb; - - _get_gl_image_and_format( - Ref<Image>(), - texture->format, - texture->flags, - real_format, - gl_format, - gl_internal_format, - gl_type, - compressed, - srgb, - texture->is_npot_repeat_mipmap); - - PoolVector<uint8_t> data; - - // TODO need to decide between RgbaUnorm and RgbaFloat32 for output - 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 more memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - // generate temporary resources - GLuint tmp_fbo; - glGenFramebuffers(1, &tmp_fbo); - - GLuint tmp_color_attachment; - glGenTextures(1, &tmp_color_attachment); - - // now bring the OpenGL context into the correct state - { - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo); - - // back color attachment with memory, then set properties - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tmp_color_attachment); - // TODO support HDR properly - 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); - - // use the color texture as color attachment for this render pass - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_color_attachment, 0); - - // more GL state, wheeeey - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - - // use volume tex for reading - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - glViewport(0, 0, texture->alloc_width, texture->alloc_height); - - // set up copy shader for proper use - shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); - shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, texture->type == VS::TEXTURE_TYPE_3D); - shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, texture->type == VS::TEXTURE_TYPE_2D_ARRAY); - shaders.copy.bind(); - - float layer; - if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY) - layer = (float)p_layer; - else - // calculate the normalized z coordinate for the layer - layer = (float)p_layer / (float)texture->alloc_depth; - - shaders.copy.set_uniform(CopyShaderGLES3::LAYER, layer); - - glBindVertexArray(resources.quadie_array); - } - - // clear color attachment, then perform copy - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - // read the image into the host buffer - glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); - - // remove temp resources and unset some GL state - { - shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, false); - shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, false); - shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glDeleteTextures(1, &tmp_color_attachment); - glDeleteFramebuffers(1, &tmp_fbo); - } - - 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); - } - -#ifdef GLES_OVER_GL - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - bool srgb; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, 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]); - } - } - - Image::Format img_format; - - //convert special case RGB10_A2 to RGBA8 because it's not a supported image format - if (texture->gl_internal_format_cache == GL_RGB10_A2) { - - img_format = Image::FORMAT_RGBA8; - - uint32_t *ptr = (uint32_t *)wb.ptr(); - uint32_t num_pixels = data_size / 4; - - for (uint32_t ofs = 0; ofs < num_pixels; ofs++) { - uint32_t px = ptr[ofs]; - uint32_t a = px >> 30 & 0xFF; - - ptr[ofs] = (px >> 2 & 0xFF) | - (px >> 12 & 0xFF) << 8 | - (px >> 22 & 0xFF) << 16 | - (a | a << 2 | a << 4 | a << 6) << 24; - } - } else { - img_format = real_format; - } - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, img_format, data)); - - return Ref<Image>(img); -#else - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - bool srgb; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, texture->is_npot_repeat_mipmap); - - 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.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); - shaders.copy.bind(); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - glBindVertexArray(resources.quadie_array); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindVertexArray(0); - - glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); - - shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); - - 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 RasterizerStorageGLES3::texture_set_flags(RID p_texture, uint32_t p_flags) { - - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!texture); - if (texture->render_target) { - - p_flags &= VS::TEXTURE_FLAG_FILTER; //can change only filter - } - - bool had_mipmaps = texture->flags & VS::TEXTURE_FLAG_MIPMAPS; - - texture->flags = p_flags; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { - - if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - } else { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - } else { - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - - if (config.use_anisotropic_filter) { - - if (texture->flags & VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { - - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config.anisotropic_level); - } else { - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); - } - } - - if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { - if (!had_mipmaps && texture->mipmaps == 1) { - glGenerateMipmap(texture->target); - } - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); - - } else { - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - } - - if (config.srgb_decode_supported && texture->srgb) { - - if (texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); - texture->using_srgb = true; - } else { - glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); - texture->using_srgb = false; - } - } - - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering - } -} -uint32_t RasterizerStorageGLES3::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 RasterizerStorageGLES3::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; -} - -VisualServer::TextureType RasterizerStorageGLES3::texture_get_type(RID p_texture) const { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, VS::TEXTURE_TYPE_2D); - - return texture->type; -} -uint32_t RasterizerStorageGLES3::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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::texture_get_depth(RID p_texture) const { - - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->depth; -} - -void RasterizerStorageGLES3::texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth) { - - 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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::texture_get_path(RID p_texture) const { - - Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND_V(!texture, String()); - return texture->path; -} -void RasterizerStorageGLES3::texture_debug_usage(List<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; - VS::TextureInfo tinfo; - tinfo.path = t->path; - tinfo.format = t->format; - tinfo.width = t->alloc_width; - tinfo.height = t->alloc_height; - tinfo.depth = t->alloc_depth; - tinfo.bytes = t->total_data_size; - r_info->push_back(tinfo); - } -} - -void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable) { - - config.shrink_textures_x2 = p_enable; -} - -void RasterizerStorageGLES3::textures_keep_original(bool p_enable) { - - config.keep_original_textures = p_enable; -} - -void RasterizerStorageGLES3::texture_set_detect_3d_callback(RID p_texture, VisualServer::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 RasterizerStorageGLES3::texture_set_detect_srgb_callback(RID p_texture, VisualServer::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 RasterizerStorageGLES3::texture_set_detect_normal_callback(RID p_texture, VisualServer::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 RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { - - Texture *texture = texture_owner.getornull(p_source); - ERR_FAIL_COND_V(!texture, RID()); - ERR_FAIL_COND_V(texture->type != VS::TEXTURE_TYPE_CUBEMAP, RID()); - - bool use_float = config.framebuffer_half_float_supported; - - if (p_resolution < 0) { - p_resolution = texture->width; - } - - glBindVertexArray(0); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) { - - glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); - texture->using_srgb = true; -#ifdef TOOLS_ENABLED - if (!(texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - texture->flags |= VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; - //notify that texture must be set to linear beforehand, so it works in other platforms when exported - } -#endif - } - - glActiveTexture(GL_TEXTURE1); - GLuint new_cubemap; - glGenTextures(1, &new_cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, new_cubemap); - - GLuint tmp_fb; - - glGenFramebuffers(1, &tmp_fb); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - - int size = p_resolution; - - int lod = 0; - - shaders.cubemap_filter.bind(); - - int mipmaps = 6; - - int mm_level = mipmaps; - - GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; - GLenum format = GL_RGBA; - GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - - while (mm_level) { - - for (int i = 0; i < 6; i++) { - glTexImage2D(_cube_side_enum[i], lod, internal_format, size, size, 0, format, type, NULL); - } - - lod++; - mm_level--; - - if (size > 1) - size >>= 1; - } - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod - 1); - - lod = 0; - mm_level = mipmaps; - - size = p_resolution; - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false); - - while (mm_level) { - - for (int i = 0; i < 6; i++) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, lod); - - glViewport(0, 0, size, size); - glBindVertexArray(resources.quadie_array); - - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::FACE_ID, i); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, lod / float(mipmaps - 1)); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindVertexArray(0); -#ifdef DEBUG_ENABLED - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); -#endif - } - - if (size > 1) - size >>= 1; - lod++; - mm_level--; - } - - //restore ranges - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod - 1); - - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - glDeleteFramebuffers(1, &tmp_fb); - - Texture *ctex = memnew(Texture); - - ctex->type = VS::TEXTURE_TYPE_CUBEMAP; - ctex->flags = VS::TEXTURE_FLAG_MIPMAPS | VS::TEXTURE_FLAG_FILTER; - ctex->width = p_resolution; - ctex->height = p_resolution; - ctex->alloc_width = p_resolution; - ctex->alloc_height = p_resolution; - ctex->format = use_float ? Image::FORMAT_RGBAH : Image::FORMAT_RGBA8; - ctex->target = GL_TEXTURE_CUBE_MAP; - ctex->gl_format_cache = format; - ctex->gl_internal_format_cache = internal_format; - ctex->gl_type_cache = type; - ctex->data_size = 0; - ctex->compressed = false; - ctex->srgb = false; - ctex->total_data_size = 0; - ctex->ignore_mipmaps = false; - ctex->mipmaps = mipmaps; - ctex->active = true; - ctex->tex_id = new_cubemap; - ctex->stored_cube_sides = (1 << 6) - 1; - ctex->render_target = NULL; - - return texture_owner.make_rid(ctex); -} - -Size2 RasterizerStorageGLES3::texture_size_with_proxy(RID p_texture) const { - - 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); - } -} - -void RasterizerStorageGLES3::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 RasterizerStorageGLES3::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; -} - -RID RasterizerStorageGLES3::sky_create() { - - Sky *sky = memnew(Sky); - sky->radiance = 0; - sky->irradiance = 0; - return sky_owner.make_rid(sky); -} - -void RasterizerStorageGLES3::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); - glDeleteTextures(1, &sky->irradiance); - sky->radiance = 0; - sky->irradiance = 0; - } - - sky->panorama = p_panorama; - if (!sky->panorama.is_valid()) { - return; //cleared - } - - Texture *texture = texture_owner.getornull(sky->panorama); - if (!texture) { - sky->panorama = RID(); - ERR_FAIL_COND(!texture); - } - - texture = texture->get_ptr(); //resolve for proxies - - glBindVertexArray(0); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0); -#ifdef GLES_OVER_GL - glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, int(Math::floor(Math::log(float(texture->width)) / Math::log(2.0f)))); - glGenerateMipmap(texture->target); -#else - glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, 0); -#endif - // Need Mipmaps regardless of whether they are set in import by user - glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_REPEAT); -#ifdef GLES_OVER_GL - glTexParameterf(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); -#else - glTexParameterf(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -#endif - glTexParameterf(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) { - - glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT); - texture->using_srgb = true; -#ifdef TOOLS_ENABLED - if (!(texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - texture->flags |= VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; - //notify that texture must be set to linear beforehand, so it works in other platforms when exported - } -#endif - } - - { - //Irradiance map - glActiveTexture(GL_TEXTURE1); - glGenTextures(1, &sky->irradiance); - glBindTexture(GL_TEXTURE_2D, sky->irradiance); - - GLuint tmp_fb; - - glGenFramebuffers(1, &tmp_fb); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - - int size = 32; - - bool use_float = config.framebuffer_half_float_supported; - - GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; - GLenum format = GL_RGBA; - GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->irradiance, 0); - - int irradiance_size = GLOBAL_GET("rendering/quality/reflections/irradiance_max_size"); - int upscale_size = MIN(int(previous_power_of_2(irradiance_size)), p_radiance_size); - - GLuint tmp_fb2; - GLuint tmp_tex; - { - //generate another one for rendering, as can't read and write from a single texarray it seems - glGenFramebuffers(1, &tmp_fb2); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2); - glGenTextures(1, &tmp_tex); - glBindTexture(GL_TEXTURE_2D, tmp_tex); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, upscale_size, 2.0 * upscale_size, 0, format, type, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#ifdef DEBUG_ENABLED - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); -#endif - } - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, true); - shaders.cubemap_filter.bind(); - - // Very large Panoramas require way too much effort to compute irradiance so use a mipmap - // level that corresponds to a panorama of 1024x512 - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, MAX(Math::floor(Math::log(float(texture->width)) / Math::log(2.0f)) - 10.0f, 0.0f)); - - // Compute Irradiance for a large texture, specified by radiance size and then pull out a low mipmap corresponding to 32x32 - for (int i = 0; i < 2; i++) { - glViewport(0, i * upscale_size, upscale_size, upscale_size); - glBindVertexArray(resources.quadie_array); - - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindVertexArray(0); - } - glGenerateMipmap(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tmp_tex); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, false); - - shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, true); - shaders.copy.bind(); - shaders.copy.set_uniform(CopyShaderGLES3::MIP_LEVEL, MAX(Math::floor(Math::log(float(upscale_size)) / Math::log(2.0f)) - 5.0f, 0.0f)); // Mip level that corresponds to a 32x32 texture - - glViewport(0, 0, size, size * 2.0); - glBindVertexArray(resources.quadie_array); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindVertexArray(0); - - shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, false); - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - glDeleteFramebuffers(1, &tmp_fb); - glDeleteFramebuffers(1, &tmp_fb2); - glDeleteTextures(1, &tmp_tex); - } - - // Now compute radiance - - glActiveTexture(GL_TEXTURE1); - glGenTextures(1, &sky->radiance); - - if (config.use_texture_array_environment) { - - //texture3D - glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance); - - GLuint tmp_fb; - - glGenFramebuffers(1, &tmp_fb); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - - int size = p_radiance_size; - - int array_level = 6; - - bool use_float = config.framebuffer_half_float_supported; - - GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; - GLenum format = GL_RGBA; - GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internal_format, size, size * 2, array_level, 0, format, type, NULL); - - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - GLuint tmp_fb2; - GLuint tmp_tex; - { - //generate another one for rendering, as can't read and write from a single texarray it seems - glGenFramebuffers(1, &tmp_fb2); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2); - glGenTextures(1, &tmp_tex); - glBindTexture(GL_TEXTURE_2D, tmp_tex); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); -#ifdef DEBUG_ENABLED - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); -#endif - } - - for (int j = 0; j < array_level; j++) { - - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2); - -#ifdef GLES_OVER_GL - if (j < 3) { -#else - if (j == 0) { -#endif - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false); - shaders.cubemap_filter.bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4)); - } else { - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, true); - shaders.cubemap_filter.bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_ARRAY_INDEX, j - 1); //read from previous to ensure better blur - } - - for (int i = 0; i < 2; i++) { - glViewport(0, i * size, size, size); - glBindVertexArray(resources.quadie_array); - - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, j / float(array_level - 1)); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindVertexArray(0); - } - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tmp_fb); - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, sky->radiance, 0, j); - glBindFramebuffer(GL_READ_FRAMEBUFFER, tmp_fb2); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, size, size * 2, 0, 0, size, size * 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - } - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false); - - //restore ranges - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance); - - glGenerateMipmap(GL_TEXTURE_2D_ARRAY); - - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - glDeleteFramebuffers(1, &tmp_fb); - glDeleteFramebuffers(1, &tmp_fb2); - glDeleteTextures(1, &tmp_tex); - - } else { - //regular single texture with mipmaps - glBindTexture(GL_TEXTURE_2D, sky->radiance); - - GLuint tmp_fb; - - glGenFramebuffers(1, &tmp_fb); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - - int size = p_radiance_size; - - int lod = 0; - - int mipmaps = 6; - - int mm_level = mipmaps; - - bool use_float = config.framebuffer_half_float_supported; - - GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; - GLenum format = GL_RGBA; - GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - - glTexStorage2DCustom(GL_TEXTURE_2D, mipmaps, internal_format, size, size * 2.0, format, type); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmaps - 1); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - GLuint tmp_fb2; - GLuint tmp_tex; - { - // Need a temporary framebuffer for rendering so we can read from previous iterations - glGenFramebuffers(1, &tmp_fb2); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2); - glGenTextures(1, &tmp_tex); - glBindTexture(GL_TEXTURE_2D, tmp_tex); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#ifdef DEBUG_ENABLED - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); -#endif - } - - lod = 0; - mm_level = mipmaps; - - size = p_radiance_size; - - while (mm_level) { - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->radiance, lod); - -#ifdef DEBUG_ENABLED - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); -#endif - glBindTexture(GL_TEXTURE_2D, tmp_tex); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL); - glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0); -#ifdef GLES_OVER_GL - if (lod < 3) { -#else - if (lod == 0) { -#endif - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, false); - shaders.cubemap_filter.bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4)); - } else { - - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, true); - shaders.cubemap_filter.bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, sky->radiance); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, float(lod - 1)); //read from previous to ensure better blur - } - - for (int i = 0; i < 2; i++) { - glViewport(0, i * size, size, size); - glBindVertexArray(resources.quadie_array); - - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, lod / float(mipmaps - 1)); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindVertexArray(0); - } - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tmp_fb); - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, sky->radiance, 0, lod); - glBindFramebuffer(GL_READ_FRAMEBUFFER, tmp_fb2); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, size, size * 2, 0, 0, size, size * 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - - if (size > 1) - size >>= 1; - lod++; - mm_level--; - } - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false); - - //restore ranges - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod - 1); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - glDeleteFramebuffers(1, &tmp_fb); - glDeleteFramebuffers(1, &tmp_fb2); - glDeleteTextures(1, &tmp_tex); - } -} - -/* SHADER API */ - -RID RasterizerStorageGLES3::shader_create() { - - Shader *shader = memnew(Shader); - shader->mode = 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 RasterizerStorageGLES3::_shader_make_dirty(Shader *p_shader) { - - if (p_shader->dirty_list.in_list()) - return; - - _shader_dirty_list.add(&p_shader->dirty_list); -} - -void RasterizerStorageGLES3::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); - VS::ShaderMode mode; - - if (mode_string == "canvas_item") - mode = VS::SHADER_CANVAS_ITEM; - else if (mode_string == "particles") - mode = VS::SHADER_PARTICLES; - else - mode = 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; - - ShaderGLES3 *shaders[VS::SHADER_MAX] = { - &scene->state.scene_shader, - &canvas->state.canvas_shader, - &this->shaders.particles, - - }; - - shader->shader = shaders[mode]; - - if (shader->custom_code_id == 0) { - shader->custom_code_id = shader->shader->create_custom_shader(); - } - - _shader_make_dirty(shader); -} -String RasterizerStorageGLES3::shader_get_code(RID p_shader) const { - - const Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND_V(!shader, String()); - - return shader->code; -} - -void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { - - _shader_dirty_list.remove(&p_shader->dirty_list); - - p_shader->valid = false; - p_shader->ubo_size = 0; - - p_shader->uniforms.clear(); - - if (p_shader->code == String()) { - return; //just invalid, but no error - } - - ShaderCompilerGLES3::GeneratedCode gen_code; - ShaderCompilerGLES3::IdentifierActions *actions = NULL; - - switch (p_shader->mode) { - case VS::SHADER_CANVAS_ITEM: { - - p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL; - p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX; - p_shader->canvas_item.uses_screen_texture = false; - p_shader->canvas_item.uses_screen_uv = false; - p_shader->canvas_item.uses_time = 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["blend_disabled"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_DISABLED); - - 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; - - actions = &shaders.actions_canvas; - actions->uniforms = &p_shader->uniforms; - - } break; - - case 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.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.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; - - 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; - - } break; - case VS::SHADER_PARTICLES: { - - actions = &shaders.actions_particles; - actions->uniforms = &p_shader->uniforms; - } break; - case VS::SHADER_MAX: - break; // Can't happen, but silences warning - } - - Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code); - 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.defines); - - p_shader->ubo_size = gen_code.uniform_total_size; - p_shader->ubo_offsets = gen_code.uniform_offsets; - p_shader->texture_count = gen_code.texture_uniforms.size(); - p_shader->texture_hints = gen_code.texture_hints; - p_shader->texture_types = gen_code.texture_types; - - p_shader->uses_vertex_time = gen_code.uses_vertex_time; - p_shader->uses_fragment_time = gen_code.uses_fragment_time; - - //all materials using this shader will have to be invalidated, unfortunately - - 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 RasterizerStorageGLES3::update_dirty_shaders() { - - while (_shader_dirty_list.first()) { - _update_shader(_shader_dirty_list.first()->self()); - } -} - -void RasterizerStorageGLES3::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); // ok should be not anymore dirty - - 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; - 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; - 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_IVEC3: - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC2: - case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_UVEC4: { - - pi.type = Variant::POOL_INT_ARRAY; - } break; - case ShaderLanguage::TYPE_FLOAT: { - pi.type = Variant::REAL; - 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::TRANSFORM; break; - case ShaderLanguage::TYPE_SAMPLER2D: - case ShaderLanguage::TYPE_ISAMPLER2D: - case ShaderLanguage::TYPE_USAMPLER2D: { - - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture2D"; - } break; - case ShaderLanguage::TYPE_SAMPLER2DARRAY: - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: { - - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "TextureArray"; - } break; - case ShaderLanguage::TYPE_SAMPLER3D: - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: { - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture3D"; - } break; - case ShaderLanguage::TYPE_SAMPLERCUBE: { - - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "CubeMap"; - } break; - }; - - p_param_list->push_back(pi); - } -} - -void RasterizerStorageGLES3::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 RasterizerStorageGLES3::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(); -} - -/* COMMON MATERIAL API */ - -void RasterizerStorageGLES3::_material_make_dirty(Material *p_material) const { - - if (p_material->dirty_list.in_list()) - return; - - _material_dirty_list.add(&p_material->dirty_list); -} - -RID RasterizerStorageGLES3::material_create() { - - Material *material = memnew(Material); - - return material_owner.make_rid(material); -} - -void RasterizerStorageGLES3::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 shader, remove from previous shader material list - material->shader->materials.remove(&material->list); - } - material->shader = shader; - - if (shader) { - shader->materials.add(&material->list); - } - - _material_make_dirty(material); -} - -RID RasterizerStorageGLES3::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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::material_get_param(RID p_material, const StringName &p_param) const { - - const Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, Variant()); - - if (material->params.has(p_param)) - return material->params[p_param]; - - return material_get_param_default(p_material, p_param); -} - -Variant RasterizerStorageGLES3::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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::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 RasterizerStorageGLES3::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; -} - -void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) { - - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - Map<RasterizerScene::InstanceBase *, int>::Element *E = material->instance_owners.find(p_instance); - if (E) { - E->get()++; - } else { - material->instance_owners[p_instance] = 1; - } -} - -void RasterizerStorageGLES3::material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) { - - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - Map<RasterizerScene::InstanceBase *, 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 RasterizerStorageGLES3::material_set_render_priority(RID p_material, int priority) { - - ERR_FAIL_COND(priority < VS::MATERIAL_RENDER_PRIORITY_MIN); - ERR_FAIL_COND(priority > VS::MATERIAL_RENDER_PRIORITY_MAX); - - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - material->render_priority = priority; -} - -_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant &value, uint8_t *data, bool p_linear_color) { - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - - bool v = value; - - GLuint *gui = (GLuint *)data; - *gui = v ? GL_TRUE : GL_FALSE; - } break; - case ShaderLanguage::TYPE_BVEC2: { - - int v = value; - GLuint *gui = (GLuint *)data; - gui[0] = (v & 1) ? GL_TRUE : GL_FALSE; - gui[1] = (v & 2) ? GL_TRUE : GL_FALSE; - - } break; - case ShaderLanguage::TYPE_BVEC3: { - - int v = value; - GLuint *gui = (GLuint *)data; - gui[0] = (v & 1) ? GL_TRUE : GL_FALSE; - gui[1] = (v & 2) ? GL_TRUE : GL_FALSE; - gui[2] = (v & 4) ? GL_TRUE : GL_FALSE; - - } break; - case ShaderLanguage::TYPE_BVEC4: { - - int v = value; - GLuint *gui = (GLuint *)data; - gui[0] = (v & 1) ? GL_TRUE : GL_FALSE; - gui[1] = (v & 2) ? GL_TRUE : GL_FALSE; - gui[2] = (v & 4) ? GL_TRUE : GL_FALSE; - gui[3] = (v & 8) ? GL_TRUE : GL_FALSE; - - } break; - case ShaderLanguage::TYPE_INT: { - - int v = value; - GLint *gui = (GLint *)data; - gui[0] = v; - - } break; - case ShaderLanguage::TYPE_IVEC2: { - - PoolVector<int> iv = value; - int s = iv.size(); - GLint *gui = (GLint *)data; - - PoolVector<int>::Read r = iv.read(); - - for (int i = 0; i < 2; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - - } break; - case ShaderLanguage::TYPE_IVEC3: { - - PoolVector<int> iv = value; - int s = iv.size(); - GLint *gui = (GLint *)data; - - PoolVector<int>::Read r = iv.read(); - - for (int i = 0; i < 3; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_IVEC4: { - - PoolVector<int> iv = value; - int s = iv.size(); - GLint *gui = (GLint *)data; - - PoolVector<int>::Read r = iv.read(); - - for (int i = 0; i < 4; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_UINT: { - - int v = value; - GLuint *gui = (GLuint *)data; - gui[0] = v; - - } break; - case ShaderLanguage::TYPE_UVEC2: { - - PoolVector<int> iv = value; - int s = iv.size(); - GLuint *gui = (GLuint *)data; - - PoolVector<int>::Read r = iv.read(); - - for (int i = 0; i < 2; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - PoolVector<int> iv = value; - int s = iv.size(); - GLuint *gui = (GLuint *)data; - - PoolVector<int>::Read r = iv.read(); - - for (int i = 0; i < 3; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - - } break; - case ShaderLanguage::TYPE_UVEC4: { - PoolVector<int> iv = value; - int s = iv.size(); - GLuint *gui = (GLuint *)data; - - PoolVector<int>::Read r = iv.read(); - - for (int i = 0; i < 4; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - float v = value; - GLfloat *gui = (GLfloat *)data; - gui[0] = v; - - } break; - case ShaderLanguage::TYPE_VEC2: { - Vector2 v = value; - GLfloat *gui = (GLfloat *)data; - gui[0] = v.x; - gui[1] = v.y; - - } break; - case ShaderLanguage::TYPE_VEC3: { - Vector3 v = value; - GLfloat *gui = (GLfloat *)data; - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - - } break; - case ShaderLanguage::TYPE_VEC4: { - - GLfloat *gui = (GLfloat *)data; - - if (value.get_type() == Variant::COLOR) { - Color v = value; - - if (p_linear_color) { - v = v.to_linear(); - } - - gui[0] = v.r; - gui[1] = v.g; - gui[2] = v.b; - gui[3] = v.a; - } else if (value.get_type() == Variant::RECT2) { - Rect2 v = value; - - gui[0] = v.position.x; - gui[1] = v.position.y; - gui[2] = v.size.x; - gui[3] = v.size.y; - } else if (value.get_type() == Variant::QUAT) { - Quat v = value; - - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - gui[3] = v.w; - } else { - Plane v = value; - - gui[0] = v.normal.x; - gui[1] = v.normal.y; - gui[2] = v.normal.z; - gui[3] = v.d; - } - } break; - case ShaderLanguage::TYPE_MAT2: { - Transform2D v = value; - GLfloat *gui = (GLfloat *)data; - - //in std140 members of mat2 are treated as vec4s - gui[0] = v.elements[0][0]; - gui[1] = v.elements[0][1]; - gui[2] = 0; - gui[3] = 0; - gui[4] = v.elements[1][0]; - gui[5] = v.elements[1][1]; - gui[6] = 0; - gui[7] = 0; - } break; - case ShaderLanguage::TYPE_MAT3: { - - Basis v = value; - GLfloat *gui = (GLfloat *)data; - - gui[0] = v.elements[0][0]; - gui[1] = v.elements[1][0]; - gui[2] = v.elements[2][0]; - gui[3] = 0; - gui[4] = v.elements[0][1]; - gui[5] = v.elements[1][1]; - gui[6] = v.elements[2][1]; - gui[7] = 0; - gui[8] = v.elements[0][2]; - gui[9] = v.elements[1][2]; - gui[10] = v.elements[2][2]; - gui[11] = 0; - } break; - case ShaderLanguage::TYPE_MAT4: { - - Transform v = value; - GLfloat *gui = (GLfloat *)data; - - gui[0] = v.basis.elements[0][0]; - gui[1] = v.basis.elements[1][0]; - gui[2] = v.basis.elements[2][0]; - gui[3] = 0; - gui[4] = v.basis.elements[0][1]; - gui[5] = v.basis.elements[1][1]; - gui[6] = v.basis.elements[2][1]; - gui[7] = 0; - gui[8] = v.basis.elements[0][2]; - gui[9] = v.basis.elements[1][2]; - gui[10] = v.basis.elements[2][2]; - gui[11] = 0; - gui[12] = v.origin.x; - gui[13] = v.origin.y; - gui[14] = v.origin.z; - gui[15] = 1; - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) { - - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - - GLuint *gui = (GLuint *)data; - *gui = value[0].boolean ? GL_TRUE : GL_FALSE; - } break; - case ShaderLanguage::TYPE_BVEC2: { - - GLuint *gui = (GLuint *)data; - gui[0] = value[0].boolean ? GL_TRUE : GL_FALSE; - gui[1] = value[1].boolean ? GL_TRUE : GL_FALSE; - - } break; - case ShaderLanguage::TYPE_BVEC3: { - - GLuint *gui = (GLuint *)data; - gui[0] = value[0].boolean ? GL_TRUE : GL_FALSE; - gui[1] = value[1].boolean ? GL_TRUE : GL_FALSE; - gui[2] = value[2].boolean ? GL_TRUE : GL_FALSE; - - } break; - case ShaderLanguage::TYPE_BVEC4: { - - GLuint *gui = (GLuint *)data; - gui[0] = value[0].boolean ? GL_TRUE : GL_FALSE; - gui[1] = value[1].boolean ? GL_TRUE : GL_FALSE; - gui[2] = value[2].boolean ? GL_TRUE : GL_FALSE; - gui[3] = value[3].boolean ? GL_TRUE : GL_FALSE; - - } break; - case ShaderLanguage::TYPE_INT: { - - GLint *gui = (GLint *)data; - gui[0] = value[0].sint; - - } break; - case ShaderLanguage::TYPE_IVEC2: { - - GLint *gui = (GLint *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC3: { - - GLint *gui = (GLint *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC4: { - - GLint *gui = (GLint *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_UINT: { - - GLuint *gui = (GLuint *)data; - gui[0] = value[0].uint; - - } break; - case ShaderLanguage::TYPE_UVEC2: { - - GLint *gui = (GLint *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - GLint *gui = (GLint *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].uint; - } - - } break; - case ShaderLanguage::TYPE_UVEC4: { - GLint *gui = (GLint *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - - GLfloat *gui = (GLfloat *)data; - gui[0] = value[0].real; - - } break; - case ShaderLanguage::TYPE_VEC2: { - - GLfloat *gui = (GLfloat *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC3: { - - GLfloat *gui = (GLfloat *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC4: { - - GLfloat *gui = (GLfloat *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].real; - } - } break; - case ShaderLanguage::TYPE_MAT2: { - GLfloat *gui = (GLfloat *)data; - - //in std140 members of mat2 are treated as vec4s - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = 0; - gui[3] = 0; - gui[4] = value[2].real; - gui[5] = value[3].real; - gui[6] = 0; - gui[7] = 0; - } break; - case ShaderLanguage::TYPE_MAT3: { - - GLfloat *gui = (GLfloat *)data; - - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = value[2].real; - gui[3] = 0; - gui[4] = value[3].real; - gui[5] = value[4].real; - gui[6] = value[5].real; - gui[7] = 0; - gui[8] = value[6].real; - gui[9] = value[7].real; - gui[10] = value[8].real; - gui[11] = 0; - } break; - case ShaderLanguage::TYPE_MAT4: { - - GLfloat *gui = (GLfloat *)data; - - for (int i = 0; i < 16; i++) { - gui[i] = value[i].real; - } - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) { - - switch (type) { - - case ShaderLanguage::TYPE_BOOL: - case ShaderLanguage::TYPE_INT: - case ShaderLanguage::TYPE_UINT: - case ShaderLanguage::TYPE_FLOAT: { - zeromem(data, 4); - } break; - case ShaderLanguage::TYPE_BVEC2: - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_UVEC2: - case ShaderLanguage::TYPE_VEC2: { - zeromem(data, 8); - } break; - case ShaderLanguage::TYPE_BVEC3: - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_VEC3: { - zeromem(data, 12); - } break; - case ShaderLanguage::TYPE_BVEC4: - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC4: - case ShaderLanguage::TYPE_VEC4: { - - zeromem(data, 16); - } break; - case ShaderLanguage::TYPE_MAT2: { - - zeromem(data, 32); - } break; - case ShaderLanguage::TYPE_MAT3: { - - zeromem(data, 48); - } break; - case ShaderLanguage::TYPE_MAT4: { - zeromem(data, 64); - } break; - - default: { - } - } -} - -void RasterizerStorageGLES3::_update_material(Material *material) { - - if (material->dirty_list.in_list()) - _material_dirty_list.remove(&material->dirty_list); - - if (material->shader && material->shader->dirty_list.in_list()) { - _update_shader(material->shader); - } - - if (material->shader && !material->shader->valid) - return; - - //update caches - - { - bool can_cast_shadow = false; - bool is_animated = false; - - if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) { - - if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX && - (!material->shader->spatial.uses_alpha || material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) { - can_cast_shadow = true; - } - - if (material->shader->spatial.uses_discard && material->shader->uses_fragment_time) { - is_animated = true; - } - - if (material->shader->spatial.uses_vertex && material->shader->uses_vertex_time) { - is_animated = true; - } - - if (can_cast_shadow != material->can_cast_shadow_cache || is_animated != material->is_animated_cache) { - material->can_cast_shadow_cache = can_cast_shadow; - material->is_animated_cache = is_animated; - - for (Map<Geometry *, int>::Element *E = material->geometry_owners.front(); E; E = E->next()) { - E->key()->material_changed_notify(); - } - - for (Map<RasterizerScene::InstanceBase *, int>::Element *E = material->instance_owners.front(); E; E = E->next()) { - E->key()->base_changed(false, true); - } - } - } - } - - //clear ubo if it needs to be cleared - if (material->ubo_size) { - - if (!material->shader || material->shader->ubo_size != material->ubo_size) { - //by by ubo - glDeleteBuffers(1, &material->ubo_id); - material->ubo_id = 0; - material->ubo_size = 0; - } - } - - //create ubo if it needs to be created - if (material->ubo_size == 0 && material->shader && material->shader->ubo_size) { - - glGenBuffers(1, &material->ubo_id); - glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id); - glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_STATIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - material->ubo_size = material->shader->ubo_size; - } - - //fill up the UBO if it needs to be filled - if (material->shader && material->ubo_size) { - uint8_t *local_ubo = (uint8_t *)alloca(material->ubo_size); - - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = material->shader->uniforms.front(); E; E = E->next()) { - - if (E->get().order < 0) - continue; // texture, does not go here - - //regular uniform - uint8_t *data = &local_ubo[material->shader->ubo_offsets[E->get().order]]; - - Map<StringName, Variant>::Element *V = material->params.find(E->key()); - - if (V) { - //user provided - _fill_std140_variant_ubo_value(E->get().type, V->get(), data, material->shader->mode == VS::SHADER_SPATIAL); - - } else if (E->get().default_value.size()) { - //default value - _fill_std140_ubo_value(E->get().type, E->get().default_value, data); - //value=E->get().default_value; - } else { - //zero because it was not provided - if (E->get().type == ShaderLanguage::TYPE_VEC4 && E->get().hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { - //colors must be set as black, with alpha as 1.0 - _fill_std140_variant_ubo_value(E->get().type, Color(0, 0, 0, 1), data, material->shader->mode == VS::SHADER_SPATIAL); - } else { - //else just zero it out - _fill_std140_ubo_empty(E->get().type, data); - } - } - } - - glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id); - glBufferData(GL_UNIFORM_BUFFER, material->ubo_size, local_ubo, GL_STATIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } - - //set up the texture array, for easy access when it needs to be drawn - if (material->shader && material->shader->texture_count) { - - material->texture_is_3d.resize(material->shader->texture_count); - material->textures.resize(material->shader->texture_count); - - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = material->shader->uniforms.front(); E; E = E->next()) { - - if (E->get().texture_order < 0) - continue; // not a texture, does not go here - - RID texture; - - switch (E->get().type) { - case ShaderLanguage::TYPE_SAMPLER3D: - case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - material->texture_is_3d.write[E->get().texture_order] = true; - } break; - default: { - material->texture_is_3d.write[E->get().texture_order] = false; - } break; - } - - Map<StringName, Variant>::Element *V = material->params.find(E->key()); - if (V) { - texture = V->get(); - } - - if (!texture.is_valid()) { - Map<StringName, RID>::Element *W = material->shader->default_textures.find(E->key()); - if (W) { - texture = W->get(); - } - } - - material->textures.write[E->get().texture_order] = texture; - } - - } else { - material->textures.clear(); - material->texture_is_3d.clear(); - } -} - -void RasterizerStorageGLES3::_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 RasterizerStorageGLES3::_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 RasterizerStorageGLES3::update_dirty_materials() { - - while (_material_dirty_list.first()) { - - Material *material = _material_dirty_list.first()->self(); - - _update_material(material); - } -} - -/* MESH API */ - -RID RasterizerStorageGLES3::mesh_create() { - - Mesh *mesh = memnew(Mesh); - - return mesh_owner.make_rid(mesh); -} - -void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) { - - PoolVector<uint8_t> array = p_array; - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_COND(!(p_format & VS::ARRAY_FORMAT_VERTEX)); - - //must have index and bones, both. - { - uint32_t bones_weight = VS::ARRAY_FORMAT_BONES | VS::ARRAY_FORMAT_WEIGHTS; - ERR_FAIL_COND_MSG((p_format & bones_weight) && (p_format & bones_weight) != bones_weight, "Array must have both bones and weights in format or none."); - } - - //bool has_morph = p_blend_shapes.size(); - - Surface::Attrib attribs[VS::ARRAY_MAX]; - - int stride = 0; - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - - attribs[i].index = i; - - if (!(p_format & (1 << i))) { - attribs[i].enabled = false; - attribs[i].integer = false; - continue; - } - - attribs[i].enabled = true; - attribs[i].offset = stride; - attribs[i].integer = false; - - switch (i) { - - case VS::ARRAY_VERTEX: { - - if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - attribs[i].size = 2; - } else { - attribs[i].size = (p_format & VS::ARRAY_COMPRESS_VERTEX) ? 4 : 3; - } - - if (p_format & VS::ARRAY_COMPRESS_VERTEX) { - attribs[i].type = GL_HALF_FLOAT; - stride += attribs[i].size * 2; - } else { - attribs[i].type = GL_FLOAT; - stride += attribs[i].size * 4; - } - - attribs[i].normalized = GL_FALSE; - - } break; - case VS::ARRAY_NORMAL: { - - attribs[i].size = 3; - - if (p_format & VS::ARRAY_COMPRESS_NORMAL) { - attribs[i].type = GL_BYTE; - stride += 4; //pad extra byte - attribs[i].normalized = GL_TRUE; - } else { - attribs[i].type = GL_FLOAT; - stride += 12; - attribs[i].normalized = GL_FALSE; - } - - } break; - case VS::ARRAY_TANGENT: { - - attribs[i].size = 4; - - if (p_format & VS::ARRAY_COMPRESS_TANGENT) { - attribs[i].type = GL_BYTE; - stride += 4; - attribs[i].normalized = GL_TRUE; - } else { - attribs[i].type = GL_FLOAT; - stride += 16; - attribs[i].normalized = GL_FALSE; - } - - } break; - case VS::ARRAY_COLOR: { - - attribs[i].size = 4; - - if (p_format & VS::ARRAY_COMPRESS_COLOR) { - attribs[i].type = GL_UNSIGNED_BYTE; - stride += 4; - attribs[i].normalized = GL_TRUE; - } else { - attribs[i].type = GL_FLOAT; - stride += 16; - attribs[i].normalized = GL_FALSE; - } - - } break; - case VS::ARRAY_TEX_UV: { - - attribs[i].size = 2; - - if (p_format & VS::ARRAY_COMPRESS_TEX_UV) { - attribs[i].type = GL_HALF_FLOAT; - stride += 4; - } else { - attribs[i].type = GL_FLOAT; - stride += 8; - } - - attribs[i].normalized = GL_FALSE; - - } break; - case VS::ARRAY_TEX_UV2: { - - attribs[i].size = 2; - - if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) { - attribs[i].type = GL_HALF_FLOAT; - stride += 4; - } else { - attribs[i].type = GL_FLOAT; - stride += 8; - } - attribs[i].normalized = GL_FALSE; - - } break; - case VS::ARRAY_BONES: { - - attribs[i].size = 4; - - if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) { - attribs[i].type = GL_UNSIGNED_SHORT; - stride += 8; - } else { - attribs[i].type = GL_UNSIGNED_BYTE; - stride += 4; - } - - attribs[i].normalized = GL_FALSE; - attribs[i].integer = true; - - } break; - case VS::ARRAY_WEIGHTS: { - - attribs[i].size = 4; - - if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) { - - attribs[i].type = GL_UNSIGNED_SHORT; - stride += 8; - attribs[i].normalized = GL_TRUE; - } else { - attribs[i].type = GL_FLOAT; - stride += 16; - attribs[i].normalized = GL_FALSE; - } - - } break; - case VS::ARRAY_INDEX: { - - attribs[i].size = 1; - - if (p_vertex_count >= (1 << 16)) { - attribs[i].type = GL_UNSIGNED_INT; - attribs[i].stride = 4; - } else { - attribs[i].type = GL_UNSIGNED_SHORT; - attribs[i].stride = 2; - } - - attribs[i].normalized = GL_FALSE; - - } break; - } - } - - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - attribs[i].stride = stride; - } - - //validate sizes - - int array_size = stride * p_vertex_count; - int index_array_size = 0; - if (array.size() != array_size && array.size() + p_vertex_count * 2 == array_size) { - //old format, convert - array = PoolVector<uint8_t>(); - - array.resize(p_array.size() + p_vertex_count * 2); - - PoolVector<uint8_t>::Write w = array.write(); - PoolVector<uint8_t>::Read r = p_array.read(); - - uint16_t *w16 = (uint16_t *)w.ptr(); - const uint16_t *r16 = (uint16_t *)r.ptr(); - - uint16_t one = Math::make_half_float(1); - - for (int i = 0; i < p_vertex_count; i++) { - - *w16++ = *r16++; - *w16++ = *r16++; - *w16++ = *r16++; - *w16++ = one; - for (int j = 0; j < (stride / 2) - 4; j++) { - *w16++ = *r16++; - } - } - } - - ERR_FAIL_COND(array.size() != array_size); - - if (p_format & VS::ARRAY_FORMAT_INDEX) { - - index_array_size = attribs[VS::ARRAY_INDEX].stride * p_index_count; - } - - ERR_FAIL_COND(p_index_array.size() != index_array_size); - - ERR_FAIL_COND(p_blend_shapes.size() != mesh->blend_shape_count); - - for (int i = 0; i < p_blend_shapes.size(); i++) { - ERR_FAIL_COND(p_blend_shapes[i].size() != array_size); - } - - //ok all valid, create stuff - - Surface *surface = memnew(Surface); - - surface->active = true; - surface->array_len = p_vertex_count; - surface->index_array_len = p_index_count; - surface->array_byte_size = array.size(); - surface->index_array_byte_size = p_index_array.size(); - surface->primitive = p_primitive; - surface->mesh = mesh; - surface->format = p_format; - surface->skeleton_bone_aabb = p_bone_aabbs; - surface->skeleton_bone_used.resize(surface->skeleton_bone_aabb.size()); - surface->aabb = p_aabb; - surface->max_bone = p_bone_aabbs.size(); - surface->total_data_size += surface->array_byte_size + surface->index_array_byte_size; - - for (int i = 0; i < surface->skeleton_bone_used.size(); i++) { - if (surface->skeleton_bone_aabb[i].size.x < 0 || surface->skeleton_bone_aabb[i].size.y < 0 || surface->skeleton_bone_aabb[i].size.z < 0) { - surface->skeleton_bone_used.write[i] = false; - } else { - surface->skeleton_bone_used.write[i] = true; - } - } - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - surface->attribs[i] = attribs[i]; - } - - { - - PoolVector<uint8_t>::Read vr = array.read(); - - glGenBuffers(1, &surface->vertex_id); - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), (p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - if (p_format & VS::ARRAY_FORMAT_INDEX) { - - PoolVector<uint8_t>::Read ir = p_index_array.read(); - - glGenBuffers(1, &surface->index_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_array_size, ir.ptr(), GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind - } - - //generate arrays for faster state switching - - for (int ai = 0; ai < 2; ai++) { - - if (ai == 0) { - //for normal draw - glGenVertexArrays(1, &surface->array_id); - glBindVertexArray(surface->array_id); - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - } else if (ai == 1) { - //for instancing draw (can be changed and no one cares) - glGenVertexArrays(1, &surface->instancing_array_id); - glBindVertexArray(surface->instancing_array_id); - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - } - - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - - if (!attribs[i].enabled) - continue; - - if (attribs[i].integer) { - glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); - } else { - glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); - } - glEnableVertexAttribArray(attribs[i].index); - } - - if (surface->index_id) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); - } - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - -#ifdef DEBUG_ENABLED - - if (config.generate_wireframes && p_primitive == VS::PRIMITIVE_TRIANGLES) { - //generate wireframes, this is used mostly by editor - PoolVector<uint32_t> wf_indices; - int index_count; - - if (p_format & VS::ARRAY_FORMAT_INDEX) { - - index_count = p_index_count * 2; - wf_indices.resize(index_count); - - PoolVector<uint8_t>::Read ir = p_index_array.read(); - PoolVector<uint32_t>::Write wr = wf_indices.write(); - - if (p_vertex_count < (1 << 16)) { - //read 16 bit indices - const uint16_t *src_idx = (const uint16_t *)ir.ptr(); - for (int i = 0; i + 5 < index_count; i += 6) { - - wr[i + 0] = src_idx[i / 2]; - wr[i + 1] = src_idx[i / 2 + 1]; - wr[i + 2] = src_idx[i / 2 + 1]; - wr[i + 3] = src_idx[i / 2 + 2]; - wr[i + 4] = src_idx[i / 2 + 2]; - wr[i + 5] = src_idx[i / 2]; - } - - } else { - - //read 16 bit indices - const uint32_t *src_idx = (const uint32_t *)ir.ptr(); - for (int i = 0; i + 5 < index_count; i += 6) { - - wr[i + 0] = src_idx[i / 2]; - wr[i + 1] = src_idx[i / 2 + 1]; - wr[i + 2] = src_idx[i / 2 + 1]; - wr[i + 3] = src_idx[i / 2 + 2]; - wr[i + 4] = src_idx[i / 2 + 2]; - wr[i + 5] = src_idx[i / 2]; - } - } - - } else { - - index_count = p_vertex_count * 2; - wf_indices.resize(index_count); - PoolVector<uint32_t>::Write wr = wf_indices.write(); - for (int i = 0; i + 5 < index_count; i += 6) { - - wr[i + 0] = i / 2; - wr[i + 1] = i / 2 + 1; - wr[i + 2] = i / 2 + 1; - wr[i + 3] = i / 2 + 2; - wr[i + 4] = i / 2 + 2; - wr[i + 5] = i / 2; - } - } - { - PoolVector<uint32_t>::Read ir = wf_indices.read(); - - glGenBuffers(1, &surface->index_wireframe_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_wireframe_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_count * sizeof(uint32_t), ir.ptr(), GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind - - surface->index_wireframe_len = index_count; - } - - for (int ai = 0; ai < 2; ai++) { - - if (ai == 0) { - //for normal draw - glGenVertexArrays(1, &surface->array_wireframe_id); - glBindVertexArray(surface->array_wireframe_id); - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - } else if (ai == 1) { - //for instancing draw (can be changed and no one cares) - glGenVertexArrays(1, &surface->instancing_array_wireframe_id); - glBindVertexArray(surface->instancing_array_wireframe_id); - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - } - - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - - if (!attribs[i].enabled) - continue; - - if (attribs[i].integer) { - glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); - } else { - glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); - } - glEnableVertexAttribArray(attribs[i].index); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_wireframe_id); - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - } - -#endif - } - - { - - //blend shapes - - for (int i = 0; i < p_blend_shapes.size(); i++) { - - Surface::BlendShape mt; - - PoolVector<uint8_t>::Read vr = p_blend_shapes[i].read(); - - surface->total_data_size += array_size; - - glGenBuffers(1, &mt.vertex_id); - glBindBuffer(GL_ARRAY_BUFFER, mt.vertex_id); - glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - glGenVertexArrays(1, &mt.array_id); - glBindVertexArray(mt.array_id); - glBindBuffer(GL_ARRAY_BUFFER, mt.vertex_id); - - for (int j = 0; j < VS::ARRAY_MAX - 1; j++) { - - if (!attribs[j].enabled) - continue; - - if (attribs[j].integer) { - glVertexAttribIPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].stride, CAST_INT_TO_UCHAR_PTR(attribs[j].offset)); - } else { - glVertexAttribPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].normalized, attribs[j].stride, CAST_INT_TO_UCHAR_PTR(attribs[j].offset)); - } - glEnableVertexAttribArray(attribs[j].index); - } - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - surface->blend_shapes.push_back(mt); - } - } - - mesh->surfaces.push_back(surface); - mesh->instance_change_notify(true, true); - - info.vertex_mem += surface->total_data_size; -} - -void RasterizerStorageGLES3::mesh_set_blend_shape_count(RID p_mesh, int p_amount) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_COND(mesh->surfaces.size() != 0); - ERR_FAIL_COND(p_amount < 0); - - mesh->blend_shape_count = p_amount; - mesh->instance_change_notify(true, false); -} -int RasterizerStorageGLES3::mesh_get_blend_shape_count(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - - return mesh->blend_shape_count; -} - -void RasterizerStorageGLES3::mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - - mesh->blend_shape_mode = p_mode; -} -VS::BlendShapeMode RasterizerStorageGLES3::mesh_get_blend_shape_mode(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::BLEND_SHAPE_MODE_NORMALIZED); - - return mesh->blend_shape_mode; -} - -void RasterizerStorageGLES3::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size()); - - int total_size = p_data.size(); - ERR_FAIL_COND(p_offset + total_size > mesh->surfaces[p_surface]->array_byte_size); - - PoolVector<uint8_t>::Read r = p_data.read(); - - glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->vertex_id); - glBufferSubData(GL_ARRAY_BUFFER, p_offset, total_size, r.ptr()); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind -} - -void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size()); - - if (mesh->surfaces[p_surface]->material == p_material) - return; - - if (mesh->surfaces[p_surface]->material.is_valid()) { - _material_remove_geometry(mesh->surfaces[p_surface]->material, mesh->surfaces[p_surface]); - } - - mesh->surfaces[p_surface]->material = p_material; - - if (mesh->surfaces[p_surface]->material.is_valid()) { - _material_add_geometry(mesh->surfaces[p_surface]->material, mesh->surfaces[p_surface]); - } - - mesh->instance_change_notify(false, true); -} -RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID()); - - return mesh->surfaces[p_surface]->material; -} - -int RasterizerStorageGLES3::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0); - - return mesh->surfaces[p_surface]->array_len; -} -int RasterizerStorageGLES3::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0); - - return mesh->surfaces[p_surface]->index_array_len; -} - -PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, PoolVector<uint8_t>()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), PoolVector<uint8_t>()); - - Surface *surface = mesh->surfaces[p_surface]; - - PoolVector<uint8_t> ret; - ret.resize(surface->array_byte_size); - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - -#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) - { - PoolVector<uint8_t>::Write w = ret.write(); - glGetBufferSubData(GL_ARRAY_BUFFER, 0, surface->array_byte_size, w.ptr()); - } -#else - void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT); - ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); - { - PoolVector<uint8_t>::Write w = ret.write(); - copymem(w.ptr(), data, surface->array_byte_size); - } - glUnmapBuffer(GL_ARRAY_BUFFER); -#endif - - glBindBuffer(GL_ARRAY_BUFFER, 0); - return ret; -} - -PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh, int p_surface) const { - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, PoolVector<uint8_t>()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), PoolVector<uint8_t>()); - - Surface *surface = mesh->surfaces[p_surface]; - - PoolVector<uint8_t> ret; - ret.resize(surface->index_array_byte_size); - - if (surface->index_array_byte_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); - -#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) - { - PoolVector<uint8_t>::Write w = ret.write(); - glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr()); - } -#else - void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT); - ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); - { - PoolVector<uint8_t>::Write w = ret.write(); - copymem(w.ptr(), data, surface->index_array_byte_size); - } - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); -#endif - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - return ret; -} - -uint32_t RasterizerStorageGLES3::mesh_surface_get_format(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - - ERR_FAIL_COND_V(!mesh, 0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0); - - return mesh->surfaces[p_surface]->format; -} - -VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::PRIMITIVE_MAX); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_MAX); - - return mesh->surfaces[p_surface]->primitive; -} - -AABB RasterizerStorageGLES3::mesh_surface_get_aabb(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), AABB()); - - return mesh->surfaces[p_surface]->aabb; -} -Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, Vector<PoolVector<uint8_t> >()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Vector<PoolVector<uint8_t> >()); - - Vector<PoolVector<uint8_t> > bsarr; - - for (int i = 0; i < mesh->surfaces[p_surface]->blend_shapes.size(); i++) { - - PoolVector<uint8_t> ret; - ret.resize(mesh->surfaces[p_surface]->array_byte_size); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id); - -#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) - { - PoolVector<uint8_t>::Write w = ret.write(); - glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, w.ptr()); - } -#else - void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT); - ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >()); - { - PoolVector<uint8_t>::Write w = ret.write(); - copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size); - } - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); -#endif - - bsarr.push_back(ret); - } - - return bsarr; -} - -Vector<AABB> RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, Vector<AABB>()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Vector<AABB>()); - - return mesh->surfaces[p_surface]->skeleton_bone_aabb; -} - -void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size()); - - Surface *surface = mesh->surfaces[p_surface]; - - if (surface->material.is_valid()) { - _material_remove_geometry(surface->material, mesh->surfaces[p_surface]); - } - - glDeleteBuffers(1, &surface->vertex_id); - if (surface->index_id) { - glDeleteBuffers(1, &surface->index_id); - } - - glDeleteVertexArrays(1, &surface->array_id); - glDeleteVertexArrays(1, &surface->instancing_array_id); - - for (int i = 0; i < surface->blend_shapes.size(); i++) { - - glDeleteBuffers(1, &surface->blend_shapes[i].vertex_id); - glDeleteVertexArrays(1, &surface->blend_shapes[i].array_id); - } - - if (surface->index_wireframe_id) { - glDeleteBuffers(1, &surface->index_wireframe_id); - glDeleteVertexArrays(1, &surface->array_wireframe_id); - glDeleteVertexArrays(1, &surface->instancing_array_wireframe_id); - } - - info.vertex_mem -= surface->total_data_size; - - memdelete(surface); - - mesh->surfaces.remove(p_surface); - - mesh->instance_change_notify(true, true); -} - -int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - return mesh->surfaces.size(); -} - -void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - - mesh->custom_aabb = p_aabb; - mesh->instance_change_notify(true, false); -} - -AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - - return mesh->custom_aabb; -} - -AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - - if (mesh->custom_aabb != AABB()) { - return mesh->custom_aabb; - } - - Skeleton *sk = NULL; - if (p_skeleton.is_valid()) { - sk = skeleton_owner.getornull(p_skeleton); - } - - AABB aabb; - - if (sk && sk->size != 0) { - - for (int i = 0; i < mesh->surfaces.size(); i++) { - - AABB laabb; - if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->skeleton_bone_aabb.size()) { - - int bs = mesh->surfaces[i]->skeleton_bone_aabb.size(); - const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr(); - const bool *skused = mesh->surfaces[i]->skeleton_bone_used.ptr(); - - int sbs = sk->size; - ERR_CONTINUE(bs > sbs); - const float *texture = sk->skel_texture.ptr(); - - bool first = true; - if (sk->use_2d) { - for (int j = 0; j < bs; j++) { - - if (!skused[j]) - continue; - - int base_ofs = ((j / 256) * 256) * 2 * 4 + (j % 256) * 4; - - Transform mtx; - - mtx.basis[0].x = texture[base_ofs + 0]; - mtx.basis[0].y = texture[base_ofs + 1]; - mtx.origin.x = texture[base_ofs + 3]; - base_ofs += 256 * 4; - mtx.basis[1].x = texture[base_ofs + 0]; - mtx.basis[1].y = texture[base_ofs + 1]; - mtx.origin.y = texture[base_ofs + 3]; - - AABB baabb = mtx.xform(skbones[j]); - - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } else { - for (int j = 0; j < bs; j++) { - - if (!skused[j]) - continue; - - int base_ofs = ((j / 256) * 256) * 3 * 4 + (j % 256) * 4; - - Transform mtx; - - mtx.basis[0].x = texture[base_ofs + 0]; - mtx.basis[0].y = texture[base_ofs + 1]; - mtx.basis[0].z = texture[base_ofs + 2]; - mtx.origin.x = texture[base_ofs + 3]; - base_ofs += 256 * 4; - mtx.basis[1].x = texture[base_ofs + 0]; - mtx.basis[1].y = texture[base_ofs + 1]; - mtx.basis[1].z = texture[base_ofs + 2]; - mtx.origin.y = texture[base_ofs + 3]; - base_ofs += 256 * 4; - mtx.basis[2].x = texture[base_ofs + 0]; - mtx.basis[2].y = texture[base_ofs + 1]; - mtx.basis[2].z = texture[base_ofs + 2]; - mtx.origin.z = texture[base_ofs + 3]; - - AABB baabb = mtx.xform(skbones[j]); - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } - - } else { - - laabb = mesh->surfaces[i]->aabb; - } - - if (i == 0) - aabb = laabb; - else - aabb.merge_with(laabb); - } - } else { - - for (int i = 0; i < mesh->surfaces.size(); i++) { - - if (i == 0) - aabb = mesh->surfaces[i]->aabb; - else - aabb.merge_with(mesh->surfaces[i]->aabb); - } - } - - return aabb; -} -void RasterizerStorageGLES3::mesh_clear(RID p_mesh) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - - while (mesh->surfaces.size()) { - mesh_remove_surface(p_mesh, 0); - } -} - -void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, const float *p_weights) { - - glBindVertexArray(s->array_id); - - BlendShapeShaderGLES3::Conditionals cond[VS::ARRAY_MAX - 1] = { - BlendShapeShaderGLES3::ENABLE_NORMAL, //will be ignored - BlendShapeShaderGLES3::ENABLE_NORMAL, - BlendShapeShaderGLES3::ENABLE_TANGENT, - BlendShapeShaderGLES3::ENABLE_COLOR, - BlendShapeShaderGLES3::ENABLE_UV, - BlendShapeShaderGLES3::ENABLE_UV2, - BlendShapeShaderGLES3::ENABLE_SKELETON, - BlendShapeShaderGLES3::ENABLE_SKELETON, - }; - - int stride = 0; - - if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - stride = 2 * 4; - } else { - stride = 3 * 4; - } - - static const int sizes[VS::ARRAY_MAX - 1] = { - 3 * 4, - 3 * 4, - 4 * 4, - 4 * 4, - 2 * 4, - 2 * 4, - 4 * 4, - 4 * 4 - }; - - for (int i = 1; i < VS::ARRAY_MAX - 1; i++) { - shaders.blend_shapes.set_conditional(cond[i], s->format & (1 << i)); //enable conditional for format - if (s->format & (1 << i)) { - stride += sizes[i]; - } - } - - //copy all first - float base_weight = 1.0; - - int mtc = s->blend_shapes.size(); - - if (s->mesh->blend_shape_mode == VS::BLEND_SHAPE_MODE_NORMALIZED) { - - for (int i = 0; i < mtc; i++) { - base_weight -= p_weights[i]; - } - } - - shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND, false); //first pass does not blend - shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::USE_2D_VERTEX, s->format & VS::ARRAY_FLAG_USE_2D_VERTICES); //use 2D vertices if needed - - shaders.blend_shapes.bind(); - - shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT, base_weight); - glEnable(GL_RASTERIZER_DISCARD); - - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[0]); - glBeginTransformFeedback(GL_POINTS); - glDrawArrays(GL_POINTS, 0, s->array_len); - glEndTransformFeedback(); - - shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND, true); //first pass does not blend - shaders.blend_shapes.bind(); - - for (int ti = 0; ti < mtc; ti++) { - float weight = p_weights[ti]; - - if (weight < 0.00001) //not bother with this one - continue; - - glBindVertexArray(s->blend_shapes[ti].array_id); - glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[1]); - - shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT, weight); - - int ofs = 0; - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - - if (s->format & (1 << i)) { - glEnableVertexAttribArray(i + 8); - switch (i) { - - case VS::ARRAY_VERTEX: { - if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 2 * 4; - } else { - glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 3 * 4; - } - } break; - case VS::ARRAY_NORMAL: { - glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 3 * 4; - } break; - case VS::ARRAY_TANGENT: { - glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - case VS::ARRAY_COLOR: { - glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - case VS::ARRAY_TEX_UV: { - glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 2 * 4; - - } break; - case VS::ARRAY_TEX_UV2: { - glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 2 * 4; - - } break; - case VS::ARRAY_BONES: { - glVertexAttribIPointer(i + 8, 4, GL_UNSIGNED_INT, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - case VS::ARRAY_WEIGHTS: { - glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - } - - } else { - glDisableVertexAttribArray(i + 8); - } - } - - glBeginTransformFeedback(GL_POINTS); - glDrawArrays(GL_POINTS, 0, s->array_len); - glEndTransformFeedback(); - - SWAP(resources.transform_feedback_buffers[0], resources.transform_feedback_buffers[1]); - } - - glDisable(GL_RASTERIZER_DISCARD); - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); - - glBindVertexArray(resources.transform_feedback_array); - glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); - - int ofs = 0; - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - - if (s->format & (1 << i)) { - glEnableVertexAttribArray(i); - switch (i) { - - case VS::ARRAY_VERTEX: { - if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 2 * 4; - } else { - glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 3 * 4; - } - } break; - case VS::ARRAY_NORMAL: { - glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 3 * 4; - } break; - case VS::ARRAY_TANGENT: { - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - case VS::ARRAY_COLOR: { - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - case VS::ARRAY_TEX_UV: { - glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 2 * 4; - - } break; - case VS::ARRAY_TEX_UV2: { - glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 2 * 4; - - } break; - case VS::ARRAY_BONES: { - glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - case VS::ARRAY_WEIGHTS: { - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); - ofs += 4 * 4; - - } break; - } - - } else { - glDisableVertexAttribArray(i); - } - } - - if (s->index_array_len) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); - } -} - -/* MULTIMESH API */ - -RID RasterizerStorageGLES3::multimesh_create() { - - MultiMesh *multimesh = memnew(MultiMesh); - return multimesh_owner.make_rid(multimesh); -} - -void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data_format) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (multimesh->size == p_instances && multimesh->transform_format == p_transform_format && multimesh->color_format == p_color_format && multimesh->custom_data_format == p_data_format) - return; - - if (multimesh->buffer) { - glDeleteBuffers(1, &multimesh->buffer); - multimesh->data.resize(0); - multimesh->buffer = 0; - } - - multimesh->size = p_instances; - multimesh->transform_format = p_transform_format; - multimesh->color_format = p_color_format; - multimesh->custom_data_format = p_data_format; - - if (multimesh->size) { - - if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { - multimesh->xform_floats = 8; - } else { - multimesh->xform_floats = 12; - } - - if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { - multimesh->color_floats = 1; - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { - multimesh->color_floats = 4; - } else { - multimesh->color_floats = 0; - } - - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { - multimesh->custom_data_floats = 1; - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { - multimesh->custom_data_floats = 4; - } else { - multimesh->custom_data_floats = 0; - } - - int format_floats = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - - multimesh->data.resize(format_floats * p_instances); - - float *dataptr = multimesh->data.ptrw(); - - for (int i = 0; i < p_instances * format_floats; i += format_floats) { - - int color_from = 0; - int custom_data_from = 0; - - if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { - dataptr[i + 0] = 1.0; - dataptr[i + 1] = 0.0; - dataptr[i + 2] = 0.0; - dataptr[i + 3] = 0.0; - dataptr[i + 4] = 0.0; - dataptr[i + 5] = 1.0; - dataptr[i + 6] = 0.0; - dataptr[i + 7] = 0.0; - color_from = 8; - custom_data_from = 8; - } else { - dataptr[i + 0] = 1.0; - dataptr[i + 1] = 0.0; - dataptr[i + 2] = 0.0; - dataptr[i + 3] = 0.0; - dataptr[i + 4] = 0.0; - dataptr[i + 5] = 1.0; - dataptr[i + 6] = 0.0; - dataptr[i + 7] = 0.0; - dataptr[i + 8] = 0.0; - dataptr[i + 9] = 0.0; - dataptr[i + 10] = 1.0; - dataptr[i + 11] = 0.0; - color_from = 12; - custom_data_from = 12; - } - - if (multimesh->color_format == VS::MULTIMESH_COLOR_NONE) { - //none - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { - - union { - uint32_t colu; - float colf; - } cu; - - cu.colu = 0xFFFFFFFF; - dataptr[i + color_from + 0] = cu.colf; - custom_data_from = color_from + 1; - - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { - dataptr[i + color_from + 0] = 1.0; - dataptr[i + color_from + 1] = 1.0; - dataptr[i + color_from + 2] = 1.0; - dataptr[i + color_from + 3] = 1.0; - custom_data_from = color_from + 4; - } - - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) { - //none - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { - - union { - uint32_t colu; - float colf; - } cu; - - cu.colu = 0; - dataptr[i + custom_data_from + 0] = cu.colf; - - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { - dataptr[i + custom_data_from + 0] = 0.0; - dataptr[i + custom_data_from + 1] = 0.0; - dataptr[i + custom_data_from + 2] = 0.0; - dataptr[i + custom_data_from + 3] = 0.0; - } - } - - glGenBuffers(1, &multimesh->buffer); - glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer); - glBufferData(GL_ARRAY_BUFFER, multimesh->data.size() * sizeof(float), NULL, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - multimesh->dirty_data = true; - multimesh->dirty_aabb = true; - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } -} - -int RasterizerStorageGLES3::multimesh_get_instance_count(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); - - return multimesh->size; -} - -void RasterizerStorageGLES3::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (multimesh->mesh.is_valid()) { - Mesh *mesh = mesh_owner.getornull(multimesh->mesh); - if (mesh) { - mesh->multimeshes.remove(&multimesh->mesh_list); - } - } - - multimesh->mesh = p_mesh; - - if (multimesh->mesh.is_valid()) { - Mesh *mesh = mesh_owner.getornull(multimesh->mesh); - if (mesh) { - mesh->multimeshes.add(&multimesh->mesh_list); - } - } - - multimesh->dirty_aabb = true; - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } -} - -void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index]; - - dataptr[0] = p_transform.basis.elements[0][0]; - dataptr[1] = p_transform.basis.elements[0][1]; - dataptr[2] = p_transform.basis.elements[0][2]; - dataptr[3] = p_transform.origin.x; - dataptr[4] = p_transform.basis.elements[1][0]; - dataptr[5] = p_transform.basis.elements[1][1]; - dataptr[6] = p_transform.basis.elements[1][2]; - dataptr[7] = p_transform.origin.y; - dataptr[8] = p_transform.basis.elements[2][0]; - dataptr[9] = p_transform.basis.elements[2][1]; - dataptr[10] = p_transform.basis.elements[2][2]; - dataptr[11] = p_transform.origin.z; - - multimesh->dirty_data = true; - multimesh->dirty_aabb = true; - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } -} - -void RasterizerStorageGLES3::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index]; - - dataptr[0] = p_transform.elements[0][0]; - dataptr[1] = p_transform.elements[1][0]; - dataptr[2] = 0; - dataptr[3] = p_transform.elements[2][0]; - dataptr[4] = p_transform.elements[0][1]; - dataptr[5] = p_transform.elements[1][1]; - dataptr[6] = 0; - dataptr[7] = p_transform.elements[2][1]; - - multimesh->dirty_data = true; - multimesh->dirty_aabb = true; - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } -} -void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE); - ERR_FAIL_INDEX(multimesh->color_format, VS::MULTIMESH_COLOR_MAX); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats]; - - if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { - - uint8_t *data8 = (uint8_t *)dataptr; - data8[0] = CLAMP(p_color.r * 255.0, 0, 255); - data8[1] = CLAMP(p_color.g * 255.0, 0, 255); - data8[2] = CLAMP(p_color.b * 255.0, 0, 255); - data8[3] = CLAMP(p_color.a * 255.0, 0, 255); - - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { - dataptr[0] = p_color.r; - dataptr[1] = p_color.g; - dataptr[2] = p_color.b; - dataptr[3] = p_color.a; - } - - multimesh->dirty_data = true; - multimesh->dirty_aabb = true; - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } -} - -void RasterizerStorageGLES3::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_custom_data) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE); - ERR_FAIL_INDEX(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats]; - - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { - - uint8_t *data8 = (uint8_t *)dataptr; - data8[0] = CLAMP(p_custom_data.r * 255.0, 0, 255); - data8[1] = CLAMP(p_custom_data.g * 255.0, 0, 255); - data8[2] = CLAMP(p_custom_data.b * 255.0, 0, 255); - data8[3] = CLAMP(p_custom_data.a * 255.0, 0, 255); - - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { - dataptr[0] = p_custom_data.r; - dataptr[1] = p_custom_data.g; - dataptr[2] = p_custom_data.b; - dataptr[3] = p_custom_data.a; - } - - multimesh->dirty_data = true; - multimesh->dirty_aabb = true; - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } -} -RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, RID()); - - return multimesh->mesh; -} - -Transform RasterizerStorageGLES3::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform()); - ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform()); - ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D, Transform()); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index]; - - Transform xform; - - xform.basis.elements[0][0] = dataptr[0]; - xform.basis.elements[0][1] = dataptr[1]; - xform.basis.elements[0][2] = dataptr[2]; - xform.origin.x = dataptr[3]; - xform.basis.elements[1][0] = dataptr[4]; - xform.basis.elements[1][1] = dataptr[5]; - xform.basis.elements[1][2] = dataptr[6]; - xform.origin.y = dataptr[7]; - xform.basis.elements[2][0] = dataptr[8]; - xform.basis.elements[2][1] = dataptr[9]; - xform.basis.elements[2][2] = dataptr[10]; - xform.origin.z = dataptr[11]; - - return xform; -} -Transform2D RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform2D()); - ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform2D()); - ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D, Transform2D()); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index]; - - Transform2D xform; - - xform.elements[0][0] = dataptr[0]; - xform.elements[1][0] = dataptr[1]; - xform.elements[2][0] = dataptr[3]; - xform.elements[0][1] = dataptr[4]; - xform.elements[1][1] = dataptr[5]; - xform.elements[2][1] = dataptr[7]; - - return xform; -} - -Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->size, Color()); - ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color()); - ERR_FAIL_INDEX_V(multimesh->color_format, VS::MULTIMESH_COLOR_MAX, Color()); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats]; - - if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { - union { - uint32_t colu; - float colf; - } cu; - - cu.colf = dataptr[0]; - - return Color::hex(BSWAP32(cu.colu)); - - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { - Color c; - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - - return c; - } - - return Color(); -} - -Color RasterizerStorageGLES3::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->size, Color()); - ERR_FAIL_COND_V(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE, Color()); - ERR_FAIL_INDEX_V(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX, Color()); - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats]; - - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { - union { - uint32_t colu; - float colf; - } cu; - - cu.colf = dataptr[0]; - - return Color::hex(BSWAP32(cu.colu)); - - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { - Color c; - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - - return c; - } - - return Color(); -} - -void RasterizerStorageGLES3::multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_COND(!multimesh->data.ptr()); - - int dsize = multimesh->data.size(); - - ERR_FAIL_COND(dsize != p_array.size()); - - PoolVector<float>::Read r = p_array.read(); - copymem(multimesh->data.ptrw(), r.ptr(), dsize * sizeof(float)); - - multimesh->dirty_data = true; - multimesh->dirty_aabb = true; - - if (!multimesh->update_list.in_list()) { - multimesh_update_list.add(&multimesh->update_list); - } -} - -void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->visible_instances = p_visible; -} -int RasterizerStorageGLES3::multimesh_get_visible_instances(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, -1); - - return multimesh->visible_instances; -} - -AABB RasterizerStorageGLES3::multimesh_get_aabb(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, AABB()); - - const_cast<RasterizerStorageGLES3 *>(this)->update_dirty_multimeshes(); //update pending AABBs - - return multimesh->aabb; -} - -void RasterizerStorageGLES3::update_dirty_multimeshes() { - - while (multimesh_update_list.first()) { - - MultiMesh *multimesh = multimesh_update_list.first()->self(); - - if (multimesh->size && multimesh->dirty_data) { - - glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer); - glBufferSubData(GL_ARRAY_BUFFER, 0, multimesh->data.size() * sizeof(float), multimesh->data.ptr()); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - if (multimesh->size && multimesh->dirty_aabb) { - - AABB mesh_aabb; - - if (multimesh->mesh.is_valid()) { - mesh_aabb = mesh_get_aabb(multimesh->mesh, RID()); - } else { - mesh_aabb.size += Vector3(0.001, 0.001, 0.001); - } - - int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; - int count = multimesh->data.size(); - float *data = multimesh->data.ptrw(); - - AABB aabb; - - if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { - - for (int i = 0; i < count; i += stride) { - - float *dataptr = &data[i]; - Transform xform; - xform.basis[0][0] = dataptr[0]; - xform.basis[0][1] = dataptr[1]; - xform.origin[0] = dataptr[3]; - xform.basis[1][0] = dataptr[4]; - xform.basis[1][1] = dataptr[5]; - xform.origin[1] = dataptr[7]; - - AABB laabb = xform.xform(mesh_aabb); - if (i == 0) - aabb = laabb; - else - aabb.merge_with(laabb); - } - } else { - - for (int i = 0; i < count; i += stride) { - - float *dataptr = &data[i]; - Transform xform; - - xform.basis.elements[0][0] = dataptr[0]; - xform.basis.elements[0][1] = dataptr[1]; - xform.basis.elements[0][2] = dataptr[2]; - xform.origin.x = dataptr[3]; - xform.basis.elements[1][0] = dataptr[4]; - xform.basis.elements[1][1] = dataptr[5]; - xform.basis.elements[1][2] = dataptr[6]; - xform.origin.y = dataptr[7]; - xform.basis.elements[2][0] = dataptr[8]; - xform.basis.elements[2][1] = dataptr[9]; - xform.basis.elements[2][2] = dataptr[10]; - xform.origin.z = dataptr[11]; - - AABB laabb = xform.xform(mesh_aabb); - if (i == 0) - aabb = laabb; - else - aabb.merge_with(laabb); - } - } - - multimesh->aabb = aabb; - } - multimesh->dirty_aabb = false; - multimesh->dirty_data = false; - - multimesh->instance_change_notify(true, false); - - multimesh_update_list.remove(multimesh_update_list.first()); - } -} - -/* IMMEDIATE API */ - -RID RasterizerStorageGLES3::immediate_create() { - - Immediate *im = memnew(Immediate); - return immediate_owner.make_rid(im); -} - -void RasterizerStorageGLES3::immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture) { - - ERR_FAIL_INDEX(p_primitive, (int)VS::PRIMITIVE_MAX); - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(im->building); - - Immediate::Chunk ic; - ic.texture = p_texture; - ic.primitive = p_primitive; - im->chunks.push_back(ic); - im->mask = 0; - im->building = true; -} -void RasterizerStorageGLES3::immediate_vertex(RID p_immediate, const Vector3 &p_vertex) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - Immediate::Chunk *c = &im->chunks.back()->get(); - - if (c->vertices.empty() && im->chunks.size() == 1) { - - im->aabb.position = p_vertex; - im->aabb.size = Vector3(); - } else { - im->aabb.expand_to(p_vertex); - } - - if (im->mask & VS::ARRAY_FORMAT_NORMAL) - c->normals.push_back(chunk_normal); - if (im->mask & VS::ARRAY_FORMAT_TANGENT) - c->tangents.push_back(chunk_tangent); - if (im->mask & VS::ARRAY_FORMAT_COLOR) - c->colors.push_back(chunk_color); - if (im->mask & VS::ARRAY_FORMAT_TEX_UV) - c->uvs.push_back(chunk_uv); - if (im->mask & VS::ARRAY_FORMAT_TEX_UV2) - c->uvs2.push_back(chunk_uv2); - im->mask |= VS::ARRAY_FORMAT_VERTEX; - c->vertices.push_back(p_vertex); -} - -void RasterizerStorageGLES3::immediate_normal(RID p_immediate, const Vector3 &p_normal) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_NORMAL; - chunk_normal = p_normal; -} -void RasterizerStorageGLES3::immediate_tangent(RID p_immediate, const Plane &p_tangent) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_TANGENT; - chunk_tangent = p_tangent; -} -void RasterizerStorageGLES3::immediate_color(RID p_immediate, const Color &p_color) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_COLOR; - chunk_color = p_color; -} -void RasterizerStorageGLES3::immediate_uv(RID p_immediate, const Vector2 &tex_uv) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_TEX_UV; - chunk_uv = tex_uv; -} -void RasterizerStorageGLES3::immediate_uv2(RID p_immediate, const Vector2 &tex_uv) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_TEX_UV2; - chunk_uv2 = tex_uv; -} - -void RasterizerStorageGLES3::immediate_end(RID p_immediate) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->building = false; - - im->instance_change_notify(true, false); -} -void RasterizerStorageGLES3::immediate_clear(RID p_immediate) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(im->building); - - im->chunks.clear(); - im->instance_change_notify(true, false); -} - -AABB RasterizerStorageGLES3::immediate_get_aabb(RID p_immediate) const { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND_V(!im, AABB()); - return im->aabb; -} - -void RasterizerStorageGLES3::immediate_set_material(RID p_immediate, RID p_material) { - - Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND(!im); - im->material = p_material; - im->instance_change_notify(false, true); -} - -RID RasterizerStorageGLES3::immediate_get_material(RID p_immediate) const { - - const Immediate *im = immediate_owner.getornull(p_immediate); - ERR_FAIL_COND_V(!im, RID()); - return im->material; -} - -/* SKELETON API */ - -RID RasterizerStorageGLES3::skeleton_create() { - - Skeleton *skeleton = memnew(Skeleton); - - glGenTextures(1, &skeleton->texture); - - return skeleton_owner.make_rid(skeleton); -} - -void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_COND(p_bones < 0); - - if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) - return; - - skeleton->size = p_bones; - skeleton->use_2d = p_2d_skeleton; - - int height = p_bones / 256; - if (p_bones % 256) - height++; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, skeleton->texture); - - if (skeleton->use_2d) { - skeleton->skel_texture.resize(256 * height * 2 * 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, height * 2, 0, GL_RGBA, GL_FLOAT, NULL); - } else { - skeleton->skel_texture.resize(256 * height * 3 * 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, height * 3, 0, GL_RGBA, GL_FLOAT, NULL); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - if (!skeleton->update_list.in_list()) { - skeleton_update_list.add(&skeleton->update_list); - } -} -int RasterizerStorageGLES3::skeleton_get_bone_count(RID p_skeleton) const { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND_V(!skeleton, 0); - - return skeleton->size; -} - -void RasterizerStorageGLES3::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(skeleton->use_2d); - - float *texture = skeleton->skel_texture.ptrw(); - - int base_ofs = ((p_bone / 256) * 256) * 3 * 4 + (p_bone % 256) * 4; - - texture[base_ofs + 0] = p_transform.basis[0].x; - texture[base_ofs + 1] = p_transform.basis[0].y; - texture[base_ofs + 2] = p_transform.basis[0].z; - texture[base_ofs + 3] = p_transform.origin.x; - base_ofs += 256 * 4; - texture[base_ofs + 0] = p_transform.basis[1].x; - texture[base_ofs + 1] = p_transform.basis[1].y; - texture[base_ofs + 2] = p_transform.basis[1].z; - texture[base_ofs + 3] = p_transform.origin.y; - base_ofs += 256 * 4; - texture[base_ofs + 0] = p_transform.basis[2].x; - texture[base_ofs + 1] = p_transform.basis[2].y; - texture[base_ofs + 2] = p_transform.basis[2].z; - texture[base_ofs + 3] = p_transform.origin.z; - - if (!skeleton->update_list.in_list()) { - skeleton_update_list.add(&skeleton->update_list); - } -} - -Transform RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform()); - ERR_FAIL_COND_V(skeleton->use_2d, Transform()); - - const float *texture = skeleton->skel_texture.ptr(); - - Transform ret; - - int base_ofs = ((p_bone / 256) * 256) * 3 * 4 + (p_bone % 256) * 4; - - ret.basis[0].x = texture[base_ofs + 0]; - ret.basis[0].y = texture[base_ofs + 1]; - ret.basis[0].z = texture[base_ofs + 2]; - ret.origin.x = texture[base_ofs + 3]; - base_ofs += 256 * 4; - ret.basis[1].x = texture[base_ofs + 0]; - ret.basis[1].y = texture[base_ofs + 1]; - ret.basis[1].z = texture[base_ofs + 2]; - ret.origin.y = texture[base_ofs + 3]; - base_ofs += 256 * 4; - ret.basis[2].x = texture[base_ofs + 0]; - ret.basis[2].y = texture[base_ofs + 1]; - ret.basis[2].z = texture[base_ofs + 2]; - ret.origin.z = texture[base_ofs + 3]; - - return ret; -} -void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(!skeleton->use_2d); - - float *texture = skeleton->skel_texture.ptrw(); - - int base_ofs = ((p_bone / 256) * 256) * 2 * 4 + (p_bone % 256) * 4; - - texture[base_ofs + 0] = p_transform[0][0]; - texture[base_ofs + 1] = p_transform[1][0]; - texture[base_ofs + 2] = 0; - texture[base_ofs + 3] = p_transform[2][0]; - base_ofs += 256 * 4; - texture[base_ofs + 0] = p_transform[0][1]; - texture[base_ofs + 1] = p_transform[1][1]; - texture[base_ofs + 2] = 0; - texture[base_ofs + 3] = p_transform[2][1]; - - if (!skeleton->update_list.in_list()) { - skeleton_update_list.add(&skeleton->update_list); - } -} -Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform2D()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); - ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); - - const float *texture = skeleton->skel_texture.ptr(); - - Transform2D ret; - - int base_ofs = ((p_bone / 256) * 256) * 2 * 4 + (p_bone % 256) * 4; - - ret[0][0] = texture[base_ofs + 0]; - ret[1][0] = texture[base_ofs + 1]; - ret[2][0] = texture[base_ofs + 3]; - base_ofs += 256 * 4; - ret[0][1] = texture[base_ofs + 0]; - ret[1][1] = texture[base_ofs + 1]; - ret[2][1] = texture[base_ofs + 3]; - - return ret; -} - -void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(!skeleton->use_2d); - - skeleton->base_transform_2d = p_base_transform; -} - -void RasterizerStorageGLES3::update_dirty_skeletons() { - - glActiveTexture(GL_TEXTURE0); - - while (skeleton_update_list.first()) { - - Skeleton *skeleton = skeleton_update_list.first()->self(); - if (skeleton->size) { - - int height = skeleton->size / 256; - if (skeleton->size % 256) - height++; - - glBindTexture(GL_TEXTURE_2D, skeleton->texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, height * (skeleton->use_2d ? 2 : 3), GL_RGBA, GL_FLOAT, skeleton->skel_texture.ptr()); - } - - for (Set<RasterizerScene::InstanceBase *>::Element *E = skeleton->instances.front(); E; E = E->next()) { - E->get()->base_changed(true, false); - } - - skeleton_update_list.remove(skeleton_update_list.first()); - } -} - -/* Light API */ - -RID RasterizerStorageGLES3::light_create(VS::LightType p_type) { - - Light *light = memnew(Light); - light->type = p_type; - - light->param[VS::LIGHT_PARAM_ENERGY] = 1.0; - light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0; - light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5; - light->param[VS::LIGHT_PARAM_RANGE] = 1.0; - light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45; - light->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45; - light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0; - light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1; - light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3; - light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; - light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1; - light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1; - - light->color = Color(1, 1, 1, 1); - light->shadow = false; - light->negative = false; - light->cull_mask = 0xFFFFFFFF; - light->directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; - light->omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; - light->omni_shadow_detail = VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL; - light->directional_blend_splits = false; - light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; - light->reverse_cull = false; - light->use_gi = true; - light->version = 0; - - return light_owner.make_rid(light); -} - -void RasterizerStorageGLES3::light_set_color(RID p_light, const Color &p_color) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->color = p_color; -} -void RasterizerStorageGLES3::light_set_param(RID p_light, VS::LightParam p_param, float p_value) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX(p_param, VS::LIGHT_PARAM_MAX); - - switch (p_param) { - case VS::LIGHT_PARAM_RANGE: - case VS::LIGHT_PARAM_SPOT_ANGLE: - case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: - case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: - case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: - case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: - case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS: - case VS::LIGHT_PARAM_SHADOW_BIAS: { - - light->version++; - light->instance_change_notify(true, false); - } break; - default: { - } - } - - light->param[p_param] = p_value; -} -void RasterizerStorageGLES3::light_set_shadow(RID p_light, bool p_enabled) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - light->shadow = p_enabled; - - light->version++; - light->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::light_set_shadow_color(RID p_light, const Color &p_color) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - light->shadow_color = p_color; -} - -void RasterizerStorageGLES3::light_set_projector(RID p_light, RID p_texture) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->projector = p_texture; -} - -void RasterizerStorageGLES3::light_set_negative(RID p_light, bool p_enable) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->negative = p_enable; -} -void RasterizerStorageGLES3::light_set_cull_mask(RID p_light, uint32_t p_mask) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->cull_mask = p_mask; - - light->version++; - light->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->reverse_cull = p_enabled; - - light->version++; - light->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::light_set_use_gi(RID p_light, bool p_enabled) { - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->use_gi = p_enabled; - - light->version++; - light->instance_change_notify(true, false); -} -void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->omni_shadow_mode = p_mode; - - light->version++; - light->instance_change_notify(true, false); -} - -VS::LightOmniShadowMode RasterizerStorageGLES3::light_omni_get_shadow_mode(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_CUBE); - - return light->omni_shadow_mode; -} - -void RasterizerStorageGLES3::light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->omni_shadow_detail = p_detail; - light->version++; - light->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->directional_shadow_mode = p_mode; - light->version++; - light->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::light_directional_set_blend_splits(RID p_light, bool p_enable) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->directional_blend_splits = p_enable; - light->version++; - light->instance_change_notify(true, false); -} - -bool RasterizerStorageGLES3::light_directional_get_blend_splits(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, false); - - return light->directional_blend_splits; -} - -VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); - - return light->directional_shadow_mode; -} - -void RasterizerStorageGLES3::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->directional_range_mode = p_range_mode; -} - -VS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES3::light_directional_get_shadow_depth_range_mode(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); - - return light->directional_range_mode; -} - -VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL); - - return light->type; -} - -float RasterizerStorageGLES3::light_get_param(RID p_light, VS::LightParam p_param) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL); - - return light->param[p_param]; -} - -Color RasterizerStorageGLES3::light_get_color(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, Color()); - - return light->color; -} - -bool RasterizerStorageGLES3::light_get_use_gi(RID p_light) { - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, false); - - return light->use_gi; -} - -bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL); - - return light->shadow; -} - -uint64_t RasterizerStorageGLES3::light_get_version(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, 0); - - return light->version; -} - -AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, AABB()); - - switch (light->type) { - - case VS::LIGHT_SPOT: { - - float len = light->param[VS::LIGHT_PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len; - return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); - }; - case VS::LIGHT_OMNI: { - - float r = light->param[VS::LIGHT_PARAM_RANGE]; - return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2); - }; - case VS::LIGHT_DIRECTIONAL: { - - return AABB(); - }; - } - - ERR_FAIL_V(AABB()); -} - -/* PROBE API */ - -RID RasterizerStorageGLES3::reflection_probe_create() { - - ReflectionProbe *reflection_probe = memnew(ReflectionProbe); - - reflection_probe->intensity = 1.0; - reflection_probe->interior_ambient = Color(); - reflection_probe->interior_ambient_energy = 1.0; - reflection_probe->interior_ambient_probe_contrib = 0.0; - - reflection_probe->max_distance = 0; - reflection_probe->extents = Vector3(1, 1, 1); - reflection_probe->origin_offset = Vector3(0, 0, 0); - reflection_probe->interior = false; - reflection_probe->box_projection = false; - reflection_probe->enable_shadows = false; - reflection_probe->cull_mask = (1 << 20) - 1; - reflection_probe->update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE; - - return reflection_probe_owner.make_rid(reflection_probe); -} - -void RasterizerStorageGLES3::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->update_mode = p_mode; - reflection_probe->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::reflection_probe_set_intensity(RID p_probe, float p_intensity) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->intensity = p_intensity; -} - -void RasterizerStorageGLES3::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior_ambient = p_ambient; -} - -void RasterizerStorageGLES3::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior_ambient_energy = p_energy; -} - -void RasterizerStorageGLES3::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior_ambient_probe_contrib = p_contrib; -} - -void RasterizerStorageGLES3::reflection_probe_set_max_distance(RID p_probe, float p_distance) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->max_distance = p_distance; - reflection_probe->instance_change_notify(true, false); -} -void RasterizerStorageGLES3::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->extents = p_extents; - reflection_probe->instance_change_notify(true, false); -} -void RasterizerStorageGLES3::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->origin_offset = p_offset; - reflection_probe->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior = p_enable; - reflection_probe->instance_change_notify(true, false); -} -void RasterizerStorageGLES3::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->box_projection = p_enable; -} - -void RasterizerStorageGLES3::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->enable_shadows = p_enable; - reflection_probe->instance_change_notify(true, false); -} -void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->cull_mask = p_layers; - reflection_probe->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution) { -} - -AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const { - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, AABB()); - - AABB aabb; - aabb.position = -reflection_probe->extents; - aabb.size = reflection_probe->extents * 2.0; - - return aabb; -} -VS::ReflectionProbeUpdateMode RasterizerStorageGLES3::reflection_probe_get_update_mode(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS); - - return reflection_probe->update_mode; -} - -uint32_t RasterizerStorageGLES3::reflection_probe_get_cull_mask(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->cull_mask; -} - -Vector3 RasterizerStorageGLES3::reflection_probe_get_extents(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Vector3()); - - return reflection_probe->extents; -} -Vector3 RasterizerStorageGLES3::reflection_probe_get_origin_offset(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Vector3()); - - return reflection_probe->origin_offset; -} - -bool RasterizerStorageGLES3::reflection_probe_renders_shadows(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, false); - - return reflection_probe->enable_shadows; -} - -float RasterizerStorageGLES3::reflection_probe_get_origin_max_distance(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->max_distance; -} - -RID RasterizerStorageGLES3::gi_probe_create() { - - GIProbe *gip = memnew(GIProbe); - - gip->bounds = AABB(Vector3(), Vector3(1, 1, 1)); - gip->dynamic_range = 1.0; - gip->energy = 1.0; - gip->propagation = 1.0; - gip->bias = 0.4; - gip->normal_bias = 0.4; - gip->interior = false; - gip->compress = false; - gip->version = 1; - gip->cell_size = 1.0; - - return gi_probe_owner.make_rid(gip); -} - -void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->bounds = p_bounds; - gip->version++; - gip->instance_change_notify(true, false); -} -AABB RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, AABB()); - - return gip->bounds; -} - -void RasterizerStorageGLES3::gi_probe_set_cell_size(RID p_probe, float p_size) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->cell_size = p_size; - gip->version++; - gip->instance_change_notify(true, false); -} - -float RasterizerStorageGLES3::gi_probe_get_cell_size(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, 0); - - return gip->cell_size; -} - -void RasterizerStorageGLES3::gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->to_cell = p_xform; -} - -Transform RasterizerStorageGLES3::gi_probe_get_to_cell_xform(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, Transform()); - - return gip->to_cell; -} - -void RasterizerStorageGLES3::gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) { - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->dynamic_data = p_data; - gip->version++; - gip->instance_change_notify(true, false); -} -PoolVector<int> RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, PoolVector<int>()); - - return gip->dynamic_data; -} - -void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe, int p_range) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->dynamic_range = p_range; -} -int RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, 0); - - return gip->dynamic_range; -} - -void RasterizerStorageGLES3::gi_probe_set_energy(RID p_probe, float p_range) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->energy = p_range; -} - -void RasterizerStorageGLES3::gi_probe_set_bias(RID p_probe, float p_range) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->bias = p_range; -} - -void RasterizerStorageGLES3::gi_probe_set_normal_bias(RID p_probe, float p_range) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->normal_bias = p_range; -} - -void RasterizerStorageGLES3::gi_probe_set_propagation(RID p_probe, float p_range) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->propagation = p_range; -} - -void RasterizerStorageGLES3::gi_probe_set_interior(RID p_probe, bool p_enable) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->interior = p_enable; -} - -bool RasterizerStorageGLES3::gi_probe_is_interior(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, false); - - return gip->interior; -} - -void RasterizerStorageGLES3::gi_probe_set_compress(RID p_probe, bool p_enable) { - - GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!gip); - - gip->compress = p_enable; -} - -bool RasterizerStorageGLES3::gi_probe_is_compressed(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, false); - - return gip->compress; -} -float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, 0); - - return gip->energy; -} - -float RasterizerStorageGLES3::gi_probe_get_bias(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, 0); - - return gip->bias; -} - -float RasterizerStorageGLES3::gi_probe_get_normal_bias(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, 0); - - return gip->normal_bias; -} - -float RasterizerStorageGLES3::gi_probe_get_propagation(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, 0); - - return gip->propagation; -} - -uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip, 0); - - return gip->version; -} - -RasterizerStorage::GIProbeCompression RasterizerStorageGLES3::gi_probe_get_dynamic_data_get_preferred_compression() const { - if (config.s3tc_supported) { - return GI_PROBE_S3TC; - } else { - return GI_PROBE_UNCOMPRESSED; - } -} - -RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) { - - GIProbeData *gipd = memnew(GIProbeData); - - gipd->width = p_width; - gipd->height = p_height; - gipd->depth = p_depth; - gipd->compression = p_compression; - - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &gipd->tex_id); - glBindTexture(GL_TEXTURE_3D, gipd->tex_id); - - int level = 0; - int min_size = 1; - - if (gipd->compression == GI_PROBE_S3TC) { - min_size = 4; - } - - while (true) { - - if (gipd->compression == GI_PROBE_S3TC) { - int size = p_width * p_height * p_depth; - glCompressedTexImage3D(GL_TEXTURE_3D, level, _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT, p_width, p_height, p_depth, 0, size, NULL); - } else { - glTexImage3D(GL_TEXTURE_3D, level, GL_RGBA8, p_width, p_height, p_depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } - - if (p_width <= min_size || p_height <= min_size || p_depth <= min_size) - break; - p_width >>= 1; - p_height >>= 1; - p_depth >>= 1; - level++; - } - - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, level); - - gipd->levels = level + 1; - - return gi_probe_data_owner.make_rid(gipd); -} - -void RasterizerStorageGLES3::gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) { - - GIProbeData *gipd = gi_probe_data_owner.getornull(p_gi_probe_data); - ERR_FAIL_COND(!gipd); - /* - Vector<uint8_t> data; - data.resize((gipd->width>>p_mipmap)*(gipd->height>>p_mipmap)*(gipd->depth>>p_mipmap)*4); - - for(int i=0;i<(gipd->width>>p_mipmap);i++) { - for(int j=0;j<(gipd->height>>p_mipmap);j++) { - for(int k=0;k<(gipd->depth>>p_mipmap);k++) { - - int ofs = (k*(gipd->height>>p_mipmap)*(gipd->width>>p_mipmap)) + j *(gipd->width>>p_mipmap) + i; - ofs*=4; - data[ofs+0]=i*0xFF/(gipd->width>>p_mipmap); - data[ofs+1]=j*0xFF/(gipd->height>>p_mipmap); - data[ofs+2]=k*0xFF/(gipd->depth>>p_mipmap); - data[ofs+3]=0xFF; - } - } - } -*/ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, gipd->tex_id); - if (gipd->compression == GI_PROBE_S3TC) { - int size = (gipd->width >> p_mipmap) * (gipd->height >> p_mipmap) * p_slice_count; - glCompressedTexSubImage3D(GL_TEXTURE_3D, p_mipmap, 0, 0, p_depth_slice, gipd->width >> p_mipmap, gipd->height >> p_mipmap, p_slice_count, _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT, size, p_data); - } else { - glTexSubImage3D(GL_TEXTURE_3D, p_mipmap, 0, 0, p_depth_slice, gipd->width >> p_mipmap, gipd->height >> p_mipmap, p_slice_count, GL_RGBA, GL_UNSIGNED_BYTE, p_data); - } - //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data); - //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr()); -} -///////////////////////////// - -RID RasterizerStorageGLES3::lightmap_capture_create() { - - LightmapCapture *capture = memnew(LightmapCapture); - return lightmap_capture_data_owner.make_rid(capture); -} - -void RasterizerStorageGLES3::lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) { - - LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND(!capture); - capture->bounds = p_bounds; - capture->instance_change_notify(true, false); -} -AABB RasterizerStorageGLES3::lightmap_capture_get_bounds(RID p_capture) const { - - const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND_V(!capture, AABB()); - return capture->bounds; -} -void RasterizerStorageGLES3::lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) { - - LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND(!capture); - - ERR_FAIL_COND(p_octree.size() == 0 || (p_octree.size() % sizeof(LightmapCaptureOctree)) != 0); - - capture->octree.resize(p_octree.size() / sizeof(LightmapCaptureOctree)); - if (p_octree.size()) { - PoolVector<LightmapCaptureOctree>::Write w = capture->octree.write(); - PoolVector<uint8_t>::Read r = p_octree.read(); - copymem(w.ptr(), r.ptr(), p_octree.size()); - } - capture->instance_change_notify(true, false); -} -PoolVector<uint8_t> RasterizerStorageGLES3::lightmap_capture_get_octree(RID p_capture) const { - - const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND_V(!capture, PoolVector<uint8_t>()); - - if (capture->octree.size() == 0) - return PoolVector<uint8_t>(); - - PoolVector<uint8_t> ret; - ret.resize(capture->octree.size() * sizeof(LightmapCaptureOctree)); - { - PoolVector<LightmapCaptureOctree>::Read r = capture->octree.read(); - PoolVector<uint8_t>::Write w = ret.write(); - copymem(w.ptr(), r.ptr(), ret.size()); - } - - return ret; -} - -void RasterizerStorageGLES3::lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) { - LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND(!capture); - capture->cell_xform = p_xform; -} - -Transform RasterizerStorageGLES3::lightmap_capture_get_octree_cell_transform(RID p_capture) const { - const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND_V(!capture, Transform()); - return capture->cell_xform; -} - -void RasterizerStorageGLES3::lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) { - LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND(!capture); - capture->cell_subdiv = p_subdiv; -} - -int RasterizerStorageGLES3::lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { - const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND_V(!capture, 0); - return capture->cell_subdiv; -} - -void RasterizerStorageGLES3::lightmap_capture_set_energy(RID p_capture, float p_energy) { - - LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND(!capture); - capture->energy = p_energy; -} - -float RasterizerStorageGLES3::lightmap_capture_get_energy(RID p_capture) const { - - const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND_V(!capture, 0); - return capture->energy; -} - -const PoolVector<RasterizerStorage::LightmapCaptureOctree> *RasterizerStorageGLES3::lightmap_capture_get_octree_ptr(RID p_capture) const { - const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); - ERR_FAIL_COND_V(!capture, NULL); - return &capture->octree; -} - -/////// - -RID RasterizerStorageGLES3::particles_create() { - - Particles *particles = memnew(Particles); - - return particles_owner.make_rid(particles); -} - -void RasterizerStorageGLES3::particles_set_emitting(RID p_particles, bool p_emitting) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->emitting = p_emitting; -} - -bool RasterizerStorageGLES3::particles_get_emitting(RID p_particles) { - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND_V(!particles, false); - - return particles->emitting; -} - -void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->amount = p_amount; - - int floats = p_amount * 24; - float *data = memnew_arr(float, floats); - - for (int i = 0; i < floats; i++) { - data[i] = 0; - } - - for (int i = 0; i < 2; i++) { - - glBindVertexArray(particles->particle_vaos[i]); - - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[i]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_STATIC_DRAW); - - for (int j = 0; j < 6; j++) { - glEnableVertexAttribArray(j); - glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16)); - } - } - - if (particles->histories_enabled) { - - for (int i = 0; i < 2; i++) { - glBindVertexArray(particles->particle_vao_histories[i]); - - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[i]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_COPY); - - for (int j = 0; j < 6; j++) { - glEnableVertexAttribArray(j); - glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16)); - } - particles->particle_valid_histories[i] = false; - } - } - - glBindVertexArray(0); - - particles->prev_ticks = 0; - particles->phase = 0; - particles->prev_phase = 0; - particles->clear = true; - - memdelete_arr(data); -} - -void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles, float p_lifetime) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->lifetime = p_lifetime; -} - -void RasterizerStorageGLES3::particles_set_one_shot(RID p_particles, bool p_one_shot) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->one_shot = p_one_shot; -} - -void RasterizerStorageGLES3::particles_set_pre_process_time(RID p_particles, float p_time) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->pre_process_time = p_time; -} -void RasterizerStorageGLES3::particles_set_explosiveness_ratio(RID p_particles, float p_ratio) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->explosiveness = p_ratio; -} -void RasterizerStorageGLES3::particles_set_randomness_ratio(RID p_particles, float p_ratio) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->randomness = p_ratio; -} - -void RasterizerStorageGLES3::_particles_update_histories(Particles *particles) { - - bool needs_histories = particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH; - - if (needs_histories == particles->histories_enabled) - return; - - particles->histories_enabled = needs_histories; - - int floats = particles->amount * 24; - - if (!needs_histories) { - - glDeleteBuffers(2, particles->particle_buffer_histories); - glDeleteVertexArrays(2, particles->particle_vao_histories); - - } else { - - glGenBuffers(2, particles->particle_buffer_histories); - glGenVertexArrays(2, particles->particle_vao_histories); - - for (int i = 0; i < 2; i++) { - glBindVertexArray(particles->particle_vao_histories[i]); - - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[i]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), NULL, GL_DYNAMIC_COPY); - - for (int j = 0; j < 6; j++) { - glEnableVertexAttribArray(j); - glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16)); - } - - particles->particle_valid_histories[i] = false; - } - } - - particles->clear = true; -} - -void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->custom_aabb = p_aabb; - _particles_update_histories(particles); - particles->instance_change_notify(true, false); -} - -void RasterizerStorageGLES3::particles_set_speed_scale(RID p_particles, float p_scale) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->speed_scale = p_scale; -} -void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->use_local_coords = p_enable; -} - -void RasterizerStorageGLES3::particles_set_fixed_fps(RID p_particles, int p_fps) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->fixed_fps = p_fps; -} - -void RasterizerStorageGLES3::particles_set_fractional_delta(RID p_particles, bool p_enable) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->fractional_delta = p_enable; -} - -void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->process_material = p_material; -} - -void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->draw_order = p_order; - _particles_update_histories(particles); -} - -void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_passes) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->draw_passes.resize(p_passes); -} - -void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); - particles->draw_passes.write[p_pass] = p_mesh; -} - -void RasterizerStorageGLES3::particles_restart(RID p_particles) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->restart_request = true; -} - -void RasterizerStorageGLES3::particles_request_process(RID p_particles) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - if (!particles->particle_element.in_list()) { - particle_update_list.add(&particles->particle_element); - } -} - -AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { - - const Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND_V(!particles, AABB()); - - const float *data; - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); - -#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) - PoolVector<uint8_t> vector; - vector.resize(particles->amount * 16 * 6); - { - PoolVector<uint8_t>::Write w = vector.write(); - glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, w.ptr()); - } - PoolVector<uint8_t>::Read r = vector.read(); - data = reinterpret_cast<const float *>(r.ptr()); -#else - data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); -#endif - AABB aabb; - - Transform inv = particles->emission_transform.affine_inverse(); - - for (int i = 0; i < particles->amount; i++) { - int ofs = i * 24; - Vector3 pos = Vector3(data[ofs + 15], data[ofs + 19], data[ofs + 23]); - if (!particles->use_local_coords) { - pos = inv.xform(pos); - } - if (i == 0) - aabb.position = pos; - else - aabb.expand_to(pos); - } - -#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) - r.release(); - vector = PoolVector<uint8_t>(); -#else - glUnmapBuffer(GL_ARRAY_BUFFER); -#endif - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - float longest_axis = 0; - for (int i = 0; i < particles->draw_passes.size(); i++) { - if (particles->draw_passes[i].is_valid()) { - AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID()); - longest_axis = MAX(maabb.get_longest_axis_size(), longest_axis); - } - } - - aabb.grow_by(longest_axis); - - return aabb; -} - -AABB RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const { - - const Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND_V(!particles, AABB()); - - return particles->custom_aabb; -} - -void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, const Transform &p_transform) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->emission_transform = p_transform; -} - -int RasterizerStorageGLES3::particles_get_draw_passes(RID p_particles) const { - - const Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND_V(!particles, 0); - - return particles->draw_passes.size(); -} - -RID RasterizerStorageGLES3::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { - - const Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND_V(!particles, RID()); - ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID()); - - return particles->draw_passes[p_pass]; -} - -void RasterizerStorageGLES3::_particles_process(Particles *p_particles, float p_delta) { - - float new_phase = Math::fmod((float)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, (float)1.0); - - if (p_particles->clear) { - p_particles->cycle_number = 0; - p_particles->random_seed = Math::rand(); - } else if (new_phase < p_particles->phase) { - if (p_particles->one_shot) { - p_particles->emitting = false; - shaders.particles.set_uniform(ParticlesShaderGLES3::EMITTING, false); - } - p_particles->cycle_number++; - } - - shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE, new_phase); - shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, p_particles->phase); - p_particles->phase = new_phase; - - shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta * p_particles->speed_scale); - shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, p_particles->clear); - glUniform1ui(shaders.particles.get_uniform_location(ParticlesShaderGLES3::RANDOM_SEED), p_particles->random_seed); - - if (p_particles->use_local_coords) - shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform()); - else - shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, p_particles->emission_transform); - - glUniform1ui(shaders.particles.get_uniform(ParticlesShaderGLES3::CYCLE), p_particles->cycle_number); - - p_particles->clear = false; - - glBindVertexArray(p_particles->particle_vaos[0]); - - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, p_particles->particle_buffers[1]); - - // GLint size = 0; - // glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); - - glBeginTransformFeedback(GL_POINTS); - glDrawArrays(GL_POINTS, 0, p_particles->amount); - glEndTransformFeedback(); - - SWAP(p_particles->particle_buffers[0], p_particles->particle_buffers[1]); - SWAP(p_particles->particle_vaos[0], p_particles->particle_vaos[1]); - - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); - glBindVertexArray(0); - /* //debug particles :D - glBindBuffer(GL_ARRAY_BUFFER, p_particles->particle_buffers[0]); - - float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, p_particles->amount * 16 * 6, GL_MAP_READ_BIT); - for (int i = 0; i < p_particles->amount; i++) { - int ofs = i * 24; - print_line(itos(i) + ":"); - print_line("\tColor: " + Color(data[ofs + 0], data[ofs + 1], data[ofs + 2], data[ofs + 3])); - print_line("\tVelocity: " + Vector3(data[ofs + 4], data[ofs + 5], data[ofs + 6])); - print_line("\tActive: " + itos(data[ofs + 7])); - print_line("\tCustom: " + Color(data[ofs + 8], data[ofs + 9], data[ofs + 10], data[ofs + 11])); - print_line("\tXF X: " + Color(data[ofs + 12], data[ofs + 13], data[ofs + 14], data[ofs + 15])); - print_line("\tXF Y: " + Color(data[ofs + 16], data[ofs + 17], data[ofs + 18], data[ofs + 19])); - print_line("\tXF Z: " + Color(data[ofs + 20], data[ofs + 21], data[ofs + 22], data[ofs + 23])); - } - - glUnmapBuffer(GL_ARRAY_BUFFER); - glBindBuffer(GL_ARRAY_BUFFER, 0); - //*/ -} - -void RasterizerStorageGLES3::update_particles() { - - glEnable(GL_RASTERIZER_DISCARD); - - while (particle_update_list.first()) { - - //use transform feedback to process particles - - Particles *particles = particle_update_list.first()->self(); - - if (particles->restart_request) { - particles->prev_ticks = 0; - particles->phase = 0; - particles->prev_phase = 0; - particles->clear = true; - particles->particle_valid_histories[0] = false; - particles->particle_valid_histories[1] = false; - particles->restart_request = false; - } - - if (particles->inactive && !particles->emitting) { - - particle_update_list.remove(particle_update_list.first()); - continue; - } - - if (particles->emitting) { - if (particles->inactive) { - //restart system from scratch - particles->prev_ticks = 0; - particles->phase = 0; - particles->prev_phase = 0; - particles->clear = true; - particles->particle_valid_histories[0] = false; - particles->particle_valid_histories[1] = false; - } - particles->inactive = false; - particles->inactive_time = 0; - } else { - particles->inactive_time += particles->speed_scale * frame.delta; - if (particles->inactive_time > particles->lifetime * 1.2) { - particles->inactive = true; - particle_update_list.remove(particle_update_list.first()); - continue; - } - } - - Material *material = material_owner.getornull(particles->process_material); - if (!material || !material->shader || material->shader->mode != VS::SHADER_PARTICLES) { - - shaders.particles.set_custom_shader(0); - } else { - shaders.particles.set_custom_shader(material->shader->custom_code_id); - - if (material->ubo_id) { - - glBindBufferBase(GL_UNIFORM_BUFFER, 0, material->ubo_id); - } - - int tc = material->textures.size(); - RID *textures = material->textures.ptrw(); - ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = material->shader->texture_hints.ptrw(); - - for (int i = 0; i < tc; i++) { - - glActiveTexture(GL_TEXTURE0 + i); - - GLenum target; - GLuint tex; - - RasterizerStorageGLES3::Texture *t = texture_owner.getornull(textures[i]); - - if (!t) { - //check hints - target = GL_TEXTURE_2D; - - switch (texture_hints[i]) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { - tex = resources.black_tex; - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - tex = resources.aniso_tex; - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - tex = resources.normal_tex; - } break; - default: { - tex = resources.white_tex; - } break; - } - } else { - - t = t->get_ptr(); //resolve for proxies - target = t->target; - tex = t->tex_id; - } - - glBindTexture(target, tex); - } - } - - shaders.particles.set_conditional(ParticlesShaderGLES3::USE_FRACTIONAL_DELTA, particles->fractional_delta); - - shaders.particles.bind(); - - shaders.particles.set_uniform(ParticlesShaderGLES3::TOTAL_PARTICLES, particles->amount); - shaders.particles.set_uniform(ParticlesShaderGLES3::TIME, frame.time[0]); - shaders.particles.set_uniform(ParticlesShaderGLES3::EXPLOSIVENESS, particles->explosiveness); - shaders.particles.set_uniform(ParticlesShaderGLES3::LIFETIME, particles->lifetime); - shaders.particles.set_uniform(ParticlesShaderGLES3::ATTRACTOR_COUNT, 0); - shaders.particles.set_uniform(ParticlesShaderGLES3::EMITTING, particles->emitting); - shaders.particles.set_uniform(ParticlesShaderGLES3::RANDOMNESS, particles->randomness); - - bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0; - - if (particles->clear && particles->pre_process_time > 0.0) { - - float frame_time; - if (particles->fixed_fps > 0) - frame_time = 1.0 / particles->fixed_fps; - else - frame_time = 1.0 / 30.0; - - float todo = particles->pre_process_time; - - while (todo >= 0) { - _particles_process(particles, frame_time); - todo -= frame_time; - } - } - - if (particles->fixed_fps > 0) { - float frame_time; - float decr; - if (zero_time_scale) { - frame_time = 0.0; - decr = 1.0 / particles->fixed_fps; - } else { - frame_time = 1.0 / particles->fixed_fps; - decr = frame_time; - } - float delta = frame.delta; - if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 - delta = 0.1; - } else if (delta <= 0.0) { //unlikely but.. - delta = 0.001; - } - float todo = particles->frame_remainder + delta; - - while (todo >= frame_time) { - _particles_process(particles, frame_time); - todo -= decr; - } - - particles->frame_remainder = todo; - - } else { - if (zero_time_scale) - _particles_process(particles, 0.0); - else - _particles_process(particles, frame.delta); - } - - particle_update_list.remove(particle_update_list.first()); - - if (particles->histories_enabled) { - - SWAP(particles->particle_buffer_histories[0], particles->particle_buffer_histories[1]); - SWAP(particles->particle_vao_histories[0], particles->particle_vao_histories[1]); - SWAP(particles->particle_valid_histories[0], particles->particle_valid_histories[1]); - - //copy - glBindBuffer(GL_COPY_READ_BUFFER, particles->particle_buffers[0]); - glBindBuffer(GL_COPY_WRITE_BUFFER, particles->particle_buffer_histories[0]); - glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, particles->amount * 24 * sizeof(float)); - - particles->particle_valid_histories[0] = true; - } - - particles->instance_change_notify(true, false); //make sure shadows are updated - } - - glDisable(GL_RASTERIZER_DISCARD); -} - -bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const { - - const Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND_V(!particles, false); - return !particles->emitting && particles->inactive; -} - -//////// - -void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND(!skeleton); - - skeleton->instances.insert(p_instance); -} - -void RasterizerStorageGLES3::instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND(!skeleton); - - skeleton->instances.erase(p_instance); -} - -void RasterizerStorageGLES3::instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { - - Instantiable *inst = NULL; - switch (p_instance->base_type) { - case VS::INSTANCE_MESH: { - inst = mesh_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_MULTIMESH: { - inst = multimesh_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_IMMEDIATE: { - inst = immediate_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_PARTICLES: { - inst = particles_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_REFLECTION_PROBE: { - inst = reflection_probe_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_LIGHT: { - inst = light_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_GI_PROBE: { - inst = gi_probe_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_LIGHTMAP_CAPTURE: { - inst = lightmap_capture_data_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - default: { - ERR_FAIL(); - } - } - - inst->instance_list.add(&p_instance->dependency_item); -} - -void RasterizerStorageGLES3::instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { - - Instantiable *inst = NULL; - - switch (p_instance->base_type) { - case VS::INSTANCE_MESH: { - inst = mesh_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_MULTIMESH: { - inst = multimesh_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_IMMEDIATE: { - inst = immediate_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_PARTICLES: { - inst = particles_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_REFLECTION_PROBE: { - inst = reflection_probe_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_LIGHT: { - inst = light_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_GI_PROBE: { - inst = gi_probe_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - case VS::INSTANCE_LIGHTMAP_CAPTURE: { - inst = lightmap_capture_data_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; - default: { - ERR_FAIL(); - } - } - - inst->instance_list.remove(&p_instance->dependency_item); -} - -/* RENDER TARGET */ - -void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { - - if (rt->fbo) { - glDeleteFramebuffers(1, &rt->fbo); - glDeleteTextures(1, &rt->color); - rt->fbo = 0; - } - - if (rt->buffers.active) { - glDeleteFramebuffers(1, &rt->buffers.fbo); - glDeleteRenderbuffers(1, &rt->buffers.depth); - glDeleteRenderbuffers(1, &rt->buffers.diffuse); - if (rt->buffers.effects_active) { - glDeleteRenderbuffers(1, &rt->buffers.specular); - glDeleteRenderbuffers(1, &rt->buffers.normal_rough); - glDeleteRenderbuffers(1, &rt->buffers.sss); - glDeleteFramebuffers(1, &rt->buffers.effect_fbo); - glDeleteTextures(1, &rt->buffers.effect); - } - - rt->buffers.effects_active = false; - rt->buffers.active = false; - } - - if (rt->depth) { - glDeleteTextures(1, &rt->depth); - rt->depth = 0; - } - - if (rt->effects.ssao.blur_fbo[0]) { - glDeleteFramebuffers(1, &rt->effects.ssao.blur_fbo[0]); - glDeleteTextures(1, &rt->effects.ssao.blur_red[0]); - glDeleteFramebuffers(1, &rt->effects.ssao.blur_fbo[1]); - glDeleteTextures(1, &rt->effects.ssao.blur_red[1]); - for (int i = 0; i < rt->effects.ssao.depth_mipmap_fbos.size(); i++) { - glDeleteFramebuffers(1, &rt->effects.ssao.depth_mipmap_fbos[i]); - } - - rt->effects.ssao.depth_mipmap_fbos.clear(); - - glDeleteTextures(1, &rt->effects.ssao.linear_depth); - - rt->effects.ssao.blur_fbo[0] = 0; - rt->effects.ssao.blur_fbo[1] = 0; - } - - if (rt->exposure.fbo) { - glDeleteFramebuffers(1, &rt->exposure.fbo); - glDeleteTextures(1, &rt->exposure.color); - rt->exposure.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; - } - - Texture *tex = texture_owner.getornull(rt->texture); - tex->alloc_height = 0; - tex->alloc_width = 0; - tex->width = 0; - tex->height = 0; - tex->active = false; - - for (int i = 0; i < 2; i++) { - if (rt->effects.mip_maps[i].color) { - for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) { - glDeleteFramebuffers(1, &rt->effects.mip_maps[i].sizes[j].fbo); - } - - glDeleteTextures(1, &rt->effects.mip_maps[i].color); - rt->effects.mip_maps[i].sizes.clear(); - rt->effects.mip_maps[i].levels = 0; - rt->effects.mip_maps[i].color = 0; - } - } - - /* - if (rt->effects.screen_space_depth) { - glDeleteTextures(1,&rt->effects.screen_space_depth); - rt->effects.screen_space_depth=0; - - } -*/ -} - -void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { - - if (rt->width <= 0 || rt->height <= 0) - return; - - GLuint color_internal_format; - GLuint color_format; - GLuint color_type; - Image::Format image_format; - - bool hdr = rt->flags[RENDER_TARGET_HDR] && config.framebuffer_half_float_supported; - //hdr = false; - - if (!hdr || rt->flags[RENDER_TARGET_NO_3D]) { - - if (rt->flags[RENDER_TARGET_NO_3D_EFFECTS] && !rt->flags[RENDER_TARGET_TRANSPARENT]) { - //if this is not used, linear colorspace looks pretty bad - //this is the default mode used for mobile - color_internal_format = GL_RGB10_A2; - color_format = GL_RGBA; - color_type = GL_UNSIGNED_INT_2_10_10_10_REV; - image_format = Image::FORMAT_RGBA8; - } else { - - color_internal_format = GL_RGBA8; - color_format = GL_RGBA; - color_type = GL_UNSIGNED_BYTE; - image_format = Image::FORMAT_RGBA8; - } - } else { - color_internal_format = GL_RGBA16F; - color_format = GL_RGBA; - color_type = GL_HALF_FLOAT; - image_format = Image::FORMAT_RGBAH; - } - - { - /* FRONT FBO */ - - glActiveTexture(GL_TEXTURE0); - - glGenFramebuffers(1, &rt->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); - - glGenTextures(1, &rt->depth); - glBindTexture(GL_TEXTURE_2D, rt->depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->width, rt->height, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, rt->depth, 0); - - 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); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - printf("framebuffer fail, status: %x\n", status); - } - - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - - Texture *tex = texture_owner.getornull(rt->texture); - tex->format = image_format; - tex->gl_format_cache = color_format; - tex->gl_type_cache = color_type; - tex->gl_internal_format_cache = color_internal_format; - tex->tex_id = rt->color; - tex->width = rt->width; - tex->alloc_width = rt->width; - tex->height = rt->height; - tex->alloc_height = rt->height; - tex->active = true; - - texture_set_flags(rt->texture, tex->flags); - } - - /* BACK FBO */ - - if (!rt->flags[RENDER_TARGET_NO_3D] && (!rt->flags[RENDER_TARGET_NO_3D_EFFECTS] || rt->msaa != VS::VIEWPORT_MSAA_DISABLED)) { - - rt->buffers.active = true; - - static const int msaa_value[] = { 0, 2, 4, 8, 16, 4, 16 }; // MSAA_EXT_nX is a GLES2 temporary hack ignored in GLES3 for now... - 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->buffers.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo); - - glGenRenderbuffers(1, &rt->buffers.depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.depth); - if (msaa == 0) - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rt->width, rt->height); - else - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT24, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->buffers.depth); - - glGenRenderbuffers(1, &rt->buffers.diffuse); - glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.diffuse); - - if (msaa == 0) - glRenderbufferStorage(GL_RENDERBUFFER, color_internal_format, rt->width, rt->height); - else - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->buffers.diffuse); - - if (!rt->flags[RENDER_TARGET_NO_3D_EFFECTS]) { - - rt->buffers.effects_active = true; - glGenRenderbuffers(1, &rt->buffers.specular); - glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.specular); - - if (msaa == 0) - glRenderbufferStorage(GL_RENDERBUFFER, color_internal_format, rt->width, rt->height); - else - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rt->buffers.specular); - - glGenRenderbuffers(1, &rt->buffers.normal_rough); - glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.normal_rough); - - if (msaa == 0) - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, rt->width, rt->height); - else - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGBA8, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rt->buffers.normal_rough); - - glGenRenderbuffers(1, &rt->buffers.sss); - glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.sss); - - if (msaa == 0) - glRenderbufferStorage(GL_RENDERBUFFER, GL_R8, rt->width, rt->height); - else - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_R8, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_RENDERBUFFER, rt->buffers.sss); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - printf("err status: %x\n", status); - _render_target_clear(rt); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } - - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - // effect resolver - - glGenFramebuffers(1, &rt->buffers.effect_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.effect_fbo); - - glGenTextures(1, &rt->buffers.effect); - glBindTexture(GL_TEXTURE_2D, rt->buffers.effect); - glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, - color_format, color_type, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, rt->buffers.effect, 0); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - printf("err status: %x\n", status); - _render_target_clear(rt); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } - - ///////////////// ssao - - //AO strength textures - for (int i = 0; i < 2; i++) { - - glGenFramebuffers(1, &rt->effects.ssao.blur_fbo[i]); - glBindFramebuffer(GL_FRAMEBUFFER, rt->effects.ssao.blur_fbo[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, rt->depth, 0); - - glGenTextures(1, &rt->effects.ssao.blur_red[i]); - glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.blur_red[i]); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt->width, rt->height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.blur_red[i], 0); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - _render_target_clear(rt); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } - } - //5 mip levels for depth texture, but base is read separately - - glGenTextures(1, &rt->effects.ssao.linear_depth); - glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.linear_depth); - - int ssao_w = rt->width / 2; - int ssao_h = rt->height / 2; - - for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw - - glTexImage2D(GL_TEXTURE_2D, i, GL_R16UI, ssao_w, ssao_h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL); - ssao_w >>= 1; - ssao_h >>= 1; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); - - for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw - - GLuint fbo; - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.linear_depth, i); - rt->effects.ssao.depth_mipmap_fbos.push_back(fbo); - } - - //////Exposure - - glGenFramebuffers(1, &rt->exposure.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->exposure.fbo); - - glGenTextures(1, &rt->exposure.color); - glBindTexture(GL_TEXTURE_2D, rt->exposure.color); - if (config.framebuffer_float_supported) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); - } else if (config.framebuffer_half_float_supported) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, 1, 1, 0, GL_RED, GL_HALF_FLOAT, NULL); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, NULL); - } - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - _render_target_clear(rt); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } - } else { - rt->buffers.effects_active = false; - } - } else { - rt->buffers.active = false; - rt->buffers.effects_active = true; - } - - if (!rt->flags[RENDER_TARGET_NO_SAMPLING] && rt->width >= 2 && rt->height >= 2) { - - for (int i = 0; i < 2; i++) { - - ERR_FAIL_COND(rt->effects.mip_maps[i].sizes.size()); - int w = rt->width; - int h = rt->height; - - if (i > 0) { - w >>= 1; - h >>= 1; - } - - glGenTextures(1, &rt->effects.mip_maps[i].color); - glBindTexture(GL_TEXTURE_2D, rt->effects.mip_maps[i].color); - - int level = 0; - int fb_w = w; - int fb_h = h; - - while (true) { - - RenderTarget::Effects::MipMaps::Size mm; - mm.width = w; - mm.height = h; - rt->effects.mip_maps[i].sizes.push_back(mm); - - w >>= 1; - h >>= 1; - - if (w < 2 || h < 2) - break; - - level++; - } - - glTexStorage2DCustom(GL_TEXTURE_2D, level + 1, color_internal_format, fb_w, fb_h, color_format, color_type); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); - glDisable(GL_SCISSOR_TEST); - glColorMask(1, 1, 1, 1); - if (!rt->buffers.active) { - glDepthMask(GL_TRUE); - } - - for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) { - - RenderTarget::Effects::MipMaps::Size &mm = rt->effects.mip_maps[i].sizes.write[j]; - - glGenFramebuffers(1, &mm.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.mip_maps[i].color, j); - bool used_depth = false; - if (j == 0 && i == 0) { //use always - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); - used_depth = true; - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - _render_target_clear(rt); - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } - - float zero[4] = { 1, 0, 1, 0 }; - glViewport(0, 0, rt->effects.mip_maps[i].sizes[j].width, rt->effects.mip_maps[i].sizes[j].height); - glClearBufferfv(GL_COLOR, 0, zero); - if (used_depth) { - glClearDepth(1.0); - glClear(GL_DEPTH_BUFFER_BIT); - } - } - - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - rt->effects.mip_maps[i].levels = level; - - 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_MAG_FILTER, GL_NEAREST); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - } -} - -RID RasterizerStorageGLES3::render_target_create() { - - RenderTarget *rt = memnew(RenderTarget); - - Texture *t = memnew(Texture); - - t->type = VS::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->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->texture = texture_owner.make_rid(t); - - return render_target_owner.make_rid(rt); -} - -void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) { - //only used in GLES2 -} - -void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - if (rt->width == p_width && rt->height == p_height) - return; - - _render_target_clear(rt); - rt->width = p_width; - rt->height = p_height; - _render_target_allocate(rt); -} - -RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) const { - - 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 RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { - 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); - - // 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; - } - } else { - Texture *t; - - if (rt->external.fbo == 0) { - // create our fbo - glGenFramebuffers(1, &rt->external.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo); - - // allocate a texture - t = memnew(Texture); - - t->type = VS::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 - glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo); - - // find our texture - t = texture_owner.getornull(rt->external.texture); - } - - // set our texture - t->tex_id = 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; - - // is there a point to setting the internal formats? we don't know them.. - - // set our texture as the destination for our framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0); - - // check status and unbind - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - printf("framebuffer fail, status: %x\n", status); - } - - ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); - } -} - -void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - rt->flags[p_flag] = p_value; - - switch (p_flag) { - 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 RasterizerStorageGLES3::render_target_was_used(RID p_render_target) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, false); - - return rt->used_in_frame; -} - -void RasterizerStorageGLES3::render_target_set_as_unused(RID p_render_target) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - rt->used_in_frame = false; -} - -void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - - if (rt->msaa == p_msaa) - return; - - _render_target_clear(rt); - rt->msaa = p_msaa; - _render_target_allocate(rt); -} - -/* CANVAS SHADOW */ - -RID RasterizerStorageGLES3::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); - glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); - - glGenRenderbuffers(1, &cls->depth); - glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cls->size, cls->height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - glGenTextures(1, &cls->distance); - glBindTexture(GL_TEXTURE_2D, cls->distance); - if (config.use_rgba_2d_shadows) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, NULL); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - //printf("errnum: %x\n",status); - glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - memdelete(cls); - ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID()); - } - - return canvas_light_shadow_owner.make_rid(cls); -} - -/* LIGHT SHADOW MAPPING */ - -RID RasterizerStorageGLES3::canvas_light_occluder_create() { - - CanvasOccluder *co = memnew(CanvasOccluder); - co->index_id = 0; - co->vertex_id = 0; - co->len = 0; - glGenVertexArrays(1, &co->array_id); - - return canvas_occluder_owner.make_rid(co); -} - -void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) { - - CanvasOccluder *co = canvas_occluder_owner.getornull(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; - glBindVertexArray(co->array_id); - glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); - glBindVertexArray(0); - } -} - -VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { - - if (mesh_owner.owns(p_rid)) { - return VS::INSTANCE_MESH; - } - - if (multimesh_owner.owns(p_rid)) { - return VS::INSTANCE_MULTIMESH; - } - - if (immediate_owner.owns(p_rid)) { - return VS::INSTANCE_IMMEDIATE; - } - - if (particles_owner.owns(p_rid)) { - return VS::INSTANCE_PARTICLES; - } - - if (light_owner.owns(p_rid)) { - return VS::INSTANCE_LIGHT; - } - - if (reflection_probe_owner.owns(p_rid)) { - return VS::INSTANCE_REFLECTION_PROBE; - } - - if (gi_probe_owner.owns(p_rid)) { - return VS::INSTANCE_GI_PROBE; - } - - if (lightmap_capture_data_owner.owns(p_rid)) { - return VS::INSTANCE_LIGHTMAP_CAPTURE; - } - - return VS::INSTANCE_NONE; -} - -bool RasterizerStorageGLES3::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); - texture_owner.free(rt->texture); - memdelete(t); - render_target_owner.free(p_rid); - memdelete(rt); - - } else if (texture_owner.owns(p_rid)) { - // delete the texture - Texture *texture = texture_owner.getornull(p_rid); - ERR_FAIL_COND_V(texture->render_target, true); //can't free the render target texture, dude - info.texture_mem -= texture->total_data_size; - texture_owner.free(p_rid); - memdelete(texture); - - } else if (sky_owner.owns(p_rid)) { - // delete the sky - Sky *sky = sky_owner.getornull(p_rid); - sky_set_texture(p_rid, RID(), 256); - sky_owner.free(p_rid); - memdelete(sky); - - } else if (shader_owner.owns(p_rid)) { - - // delete the texture - 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 *mat = shader->materials.first()->self(); - - mat->shader = NULL; - _material_make_dirty(mat); - - shader->materials.remove(shader->materials.first()); - } - - //material_shader.free_custom_shader(shader->custom_code_id); - shader_owner.free(p_rid); - memdelete(shader); - - } else if (material_owner.owns(p_rid)) { - - // delete the texture - Material *material = material_owner.getornull(p_rid); - - if (material->shader) { - material->shader->materials.remove(&material->list); - } - - if (material->ubo_id) { - glDeleteBuffers(1, &material->ubo_id); - } - - //remove from owners - for (Map<Geometry *, int>::Element *E = material->geometry_owners.front(); E; E = E->next()) { - - Geometry *g = E->key(); - g->material = RID(); - } - for (Map<RasterizerScene::InstanceBase *, int>::Element *E = material->instance_owners.front(); E; E = E->next()) { - RasterizerScene::InstanceBase *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(material); - - } else if (skeleton_owner.owns(p_rid)) { - - // delete the texture - Skeleton *skeleton = skeleton_owner.getornull(p_rid); - if (skeleton->update_list.in_list()) { - skeleton_update_list.remove(&skeleton->update_list); - } - - for (Set<RasterizerScene::InstanceBase *>::Element *E = skeleton->instances.front(); E; E = E->next()) { - E->get()->skeleton = RID(); - } - - skeleton_allocate(p_rid, 0, false); - - glDeleteTextures(1, &skeleton->texture); - skeleton_owner.free(p_rid); - memdelete(skeleton); - - } else if (mesh_owner.owns(p_rid)) { - - // delete the texture - 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); - - } else if (multimesh_owner.owns(p_rid)) { - - // delete the texture - 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, VS::MULTIMESH_TRANSFORM_2D, VS::MULTIMESH_COLOR_NONE); //frees multimesh - update_dirty_multimeshes(); - - multimesh_owner.free(p_rid); - memdelete(multimesh); - } else if (immediate_owner.owns(p_rid)) { - - Immediate *immediate = immediate_owner.getornull(p_rid); - immediate->instance_remove_deps(); - - immediate_owner.free(p_rid); - memdelete(immediate); - } else if (light_owner.owns(p_rid)) { - - // delete the texture - Light *light = light_owner.getornull(p_rid); - light->instance_remove_deps(); - - light_owner.free(p_rid); - memdelete(light); - - } 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); - - } else if (gi_probe_owner.owns(p_rid)) { - - // delete the texture - GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); - gi_probe->instance_remove_deps(); - - gi_probe_owner.free(p_rid); - memdelete(gi_probe); - } else if (gi_probe_data_owner.owns(p_rid)) { - - // delete the texture - GIProbeData *gi_probe_data = gi_probe_data_owner.getornull(p_rid); - - glDeleteTextures(1, &gi_probe_data->tex_id); - gi_probe_data_owner.free(p_rid); - memdelete(gi_probe_data); - } 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); - - } 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); - - glDeleteVertexArrays(1, &co->array_id); - - canvas_occluder_owner.free(p_rid); - memdelete(co); - - } 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); - } else if (particles_owner.owns(p_rid)) { - Particles *particles = particles_owner.getornull(p_rid); - particles->instance_remove_deps(); - particles_owner.free(p_rid); - memdelete(particles); - } else { - return false; - } - - return true; -} - -bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const { - - if (p_feature == "bptc") - return config.bptc_supported; - - if (p_feature == "s3tc") - return config.s3tc_supported; - - if (p_feature == "etc") - return config.etc_supported; - - if (p_feature == "etc2") - return config.etc2_supported; - - if (p_feature == "pvrtc") - return config.pvrtc_supported; - - return false; -} - -//////////////////////////////////////////// - -void RasterizerStorageGLES3::set_debug_generate_wireframes(bool p_generate) { - - config.generate_wireframes = p_generate; -} - -void RasterizerStorageGLES3::render_info_begin_capture() { - - info.snap = info.render; -} - -void RasterizerStorageGLES3::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; -} - -int RasterizerStorageGLES3::get_captured_render_info(VS::RenderInfo p_info) { - - switch (p_info) { - case VS::INFO_OBJECTS_IN_FRAME: { - - return info.snap.object_count; - } break; - case VS::INFO_VERTICES_IN_FRAME: { - - return info.snap.vertices_count; - } break; - case VS::INFO_MATERIAL_CHANGES_IN_FRAME: { - return info.snap.material_switch_count; - } break; - case VS::INFO_SHADER_CHANGES_IN_FRAME: { - return info.snap.shader_rebind_count; - } break; - case VS::INFO_SURFACE_CHANGES_IN_FRAME: { - return info.snap.surface_switch_count; - } break; - case VS::INFO_DRAW_CALLS_IN_FRAME: { - return info.snap.draw_call_count; - } break; - default: { - return get_render_info(p_info); - } - } -} - -int RasterizerStorageGLES3::get_render_info(VS::RenderInfo p_info) { - - switch (p_info) { - case VS::INFO_OBJECTS_IN_FRAME: - return info.render_final.object_count; - case VS::INFO_VERTICES_IN_FRAME: - return info.render_final.vertices_count; - case VS::INFO_MATERIAL_CHANGES_IN_FRAME: - return info.render_final.material_switch_count; - case VS::INFO_SHADER_CHANGES_IN_FRAME: - return info.render_final.shader_rebind_count; - case VS::INFO_SURFACE_CHANGES_IN_FRAME: - return info.render_final.surface_switch_count; - case VS::INFO_DRAW_CALLS_IN_FRAME: - return info.render_final.draw_call_count; - case VS::INFO_USAGE_VIDEO_MEM_TOTAL: - return 0; //no idea - case VS::INFO_VIDEO_MEM_USED: - return info.vertex_mem + info.texture_mem; - case VS::INFO_TEXTURE_MEM_USED: - return info.texture_mem; - case VS::INFO_VERTEX_MEM_USED: - return info.vertex_mem; - default: - return 0; //no idea either - } -} - -String RasterizerStorageGLES3::get_video_adapter_name() const { - - return (const char *)glGetString(GL_RENDERER); -} - -String RasterizerStorageGLES3::get_video_adapter_vendor() const { - - return (const char *)glGetString(GL_VENDOR); -} - -void RasterizerStorageGLES3::initialize() { - - RasterizerStorageGLES3::system_fbo = 0; - - //// extensions config - /// - - { - - int max_extensions = 0; - glGetIntegerv(GL_NUM_EXTENSIONS, &max_extensions); - for (int i = 0; i < max_extensions; i++) { - const GLubyte *s = glGetStringi(GL_EXTENSIONS, i); - if (!s) - break; - config.extensions.insert((const char *)s); - } - } - - config.shrink_textures_x2 = false; - config.use_fast_texture_filter = int(ProjectSettings::get_singleton()->get("rendering/quality/filters/use_nearest_mipmap_filter")); - config.use_anisotropic_filter = config.extensions.has("rendering/quality/filters/anisotropic_filter_level"); - - config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); - config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc"); - config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc"); -#ifdef GLES_OVER_GL - config.etc2_supported = false; - config.s3tc_supported = true; - config.rgtc_supported = true; //RGTC - core since OpenGL version 3.0 - config.texture_float_linear_supported = true; - config.framebuffer_float_supported = true; - config.framebuffer_half_float_supported = true; - -#else - config.etc2_supported = true; - config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc"); - 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.texture_float_linear_supported = config.extensions.has("GL_OES_texture_float_linear"); - config.framebuffer_float_supported = config.extensions.has("GL_EXT_color_buffer_float"); - config.framebuffer_half_float_supported = config.extensions.has("GL_EXT_color_buffer_half_float") || config.framebuffer_float_supported; - -#endif - - config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc"); - config.srgb_decode_supported = config.extensions.has("GL_EXT_texture_sRGB_decode"); - - config.anisotropic_level = 1.0; - config.use_anisotropic_filter = config.extensions.has("GL_EXT_texture_filter_anisotropic"); - if (config.use_anisotropic_filter) { - glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &config.anisotropic_level); - config.anisotropic_level = MIN(int(ProjectSettings::get_singleton()->get("rendering/quality/filters/anisotropic_filter_level")), config.anisotropic_level); - } - - frame.clear_request = false; - - shaders.copy.init(); - - { - //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); - - glGenTextures(1, &resources.white_tex_3d); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, resources.white_tex_3d); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 2, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); - - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0); - - glGenTextures(1, &resources.white_tex_array); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, resources.white_tex_array); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 8, 8, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); - glGenerateMipmap(GL_TEXTURE_2D_ARRAY); - glBindTexture(GL_TEXTURE_2D, 0); - } - - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); - - config.use_rgba_2d_shadows = !config.framebuffer_float_supported; - - //generic quadie for copying - - { - //quad buffers - - 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); //unbind - - glGenVertexArrays(1, &resources.quadie_array); - glBindVertexArray(resources.quadie_array); - glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8)); - glEnableVertexAttribArray(4); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - } - - //generic quadie for copying without touching sky - - { - //transform feedback buffers - uint32_t xf_feedback_size = GLOBAL_DEF_RST("rendering/limits/buffers/blend_shape_max_buffer_size_kb", 4096); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/blend_shape_max_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/blend_shape_max_buffer_size_kb", PROPERTY_HINT_RANGE, "0,8192,1,or_greater")); - - for (int i = 0; i < 2; i++) { - - glGenBuffers(1, &resources.transform_feedback_buffers[i]); - glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[i]); - glBufferData(GL_ARRAY_BUFFER, xf_feedback_size * 1024, NULL, GL_STREAM_DRAW); - } - - shaders.blend_shapes.init(); - - glGenVertexArrays(1, &resources.transform_feedback_array); - } - - shaders.cubemap_filter.init(); - bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx"); - shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq); - shaders.particles.init(); - -#ifdef GLES_OVER_GL - glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); -#endif - - frame.count = 0; - frame.delta = 0; - frame.current_rt = NULL; - config.keep_original_textures = false; - config.generate_wireframes = false; - config.use_texture_array_environment = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections"); - - config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); - - String renderer = (const char *)glGetString(GL_RENDERER); - - config.use_depth_prepass = bool(GLOBAL_GET("rendering/quality/depth_prepass/enable")); - if (config.use_depth_prepass) { - - String vendors = GLOBAL_GET("rendering/quality/depth_prepass/disable_for_vendors"); - Vector<String> vendor_match = vendors.split(","); - for (int i = 0; i < vendor_match.size(); i++) { - String v = vendor_match[i].strip_edges(); - if (v == String()) - continue; - - if (renderer.findn(v) != -1) { - config.use_depth_prepass = false; - } - } - } -} - -void RasterizerStorageGLES3::finalize() { - - glDeleteTextures(1, &resources.white_tex); - glDeleteTextures(1, &resources.black_tex); - glDeleteTextures(1, &resources.normal_tex); -} - -void RasterizerStorageGLES3::update_dirty_resources() { - - update_dirty_multimeshes(); - update_dirty_skeletons(); - update_dirty_shaders(); - update_dirty_materials(); - update_particles(); -} - -RasterizerStorageGLES3::RasterizerStorageGLES3() { -} diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h deleted file mode 100644 index 54c2e2b884..0000000000 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ /dev/null @@ -1,1478 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_gles3.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. */ -/*************************************************************************/ - -#ifndef RASTERIZERSTORAGEGLES3_H -#define RASTERIZERSTORAGEGLES3_H - -#include "core/self_list.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual/shader_language.h" -#include "shader_compiler_gles3.h" -#include "shader_gles3.h" - -#include "shaders/blend_shape.glsl.gen.h" -#include "shaders/canvas.glsl.gen.h" -#include "shaders/copy.glsl.gen.h" -#include "shaders/cubemap_filter.glsl.gen.h" -#include "shaders/particles.glsl.gen.h" - -#include "core/rid_owner.h" - -// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead. -#ifdef __EMSCRIPTEN__ -void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); -#endif - -class RasterizerCanvasGLES3; -class RasterizerSceneGLES3; - -#define _TEXTURE_SRGB_DECODE_EXT 0x8A48 -#define _DECODE_EXT 0x8A49 -#define _SKIP_DECODE_EXT 0x8A4A - -void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type); - -class RasterizerStorageGLES3 : public RasterizerStorage { -public: - RasterizerCanvasGLES3 *canvas; - RasterizerSceneGLES3 *scene; - static GLuint system_fbo; //on some devices, such as apple, screen is rendered to yet another fbo. - - enum RenderArchitecture { - RENDER_ARCH_MOBILE, - RENDER_ARCH_DESKTOP, - }; - - struct Config { - - bool shrink_textures_x2; - bool use_fast_texture_filter; - bool use_anisotropic_filter; - - bool s3tc_supported; - bool latc_supported; - bool rgtc_supported; - bool bptc_supported; - bool etc_supported; - bool etc2_supported; - bool pvrtc_supported; - - bool srgb_decode_supported; - - bool texture_float_linear_supported; - bool framebuffer_float_supported; - bool framebuffer_half_float_supported; - - bool use_rgba_2d_shadows; - - float anisotropic_level; - - int max_texture_image_units; - int max_texture_size; - - bool generate_wireframes; - - bool use_texture_array_environment; - - Set<String> extensions; - - bool keep_original_textures; - - bool use_depth_prepass; - bool force_vertex_shading; - } config; - - mutable struct Shaders { - - CopyShaderGLES3 copy; - - ShaderCompilerGLES3 compiler; - - CubemapFilterShaderGLES3 cubemap_filter; - - BlendShapeShaderGLES3 blend_shapes; - - ParticlesShaderGLES3 particles; - - ShaderCompilerGLES3::IdentifierActions actions_canvas; - ShaderCompilerGLES3::IdentifierActions actions_scene; - ShaderCompilerGLES3::IdentifierActions actions_particles; - } shaders; - - struct Resources { - - GLuint white_tex; - GLuint black_tex; - GLuint normal_tex; - GLuint aniso_tex; - - GLuint white_tex_3d; - GLuint white_tex_array; - - GLuint quadie; - GLuint quadie_array; - - GLuint transform_feedback_buffers[2]; - GLuint transform_feedback_array; - - } resources; - - 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; - - void reset() { - object_count = 0; - draw_call_count = 0; - material_switch_count = 0; - surface_switch_count = 0; - shader_rebind_count = 0; - vertices_count = 0; - } - } render, render_final, snap; - - Info() { - - texture_mem = 0; - vertex_mem = 0; - render.reset(); - render_final.reset(); - } - - } info; - - ///////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////DATA/////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////// - - struct Instantiable { - - SelfList<RasterizerScene::InstanceBase>::List instance_list; - - _FORCE_INLINE_ void instance_change_notify(bool p_aabb, bool p_materials) { - - SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first(); - while (instances) { - - instances->self()->base_changed(p_aabb, p_materials); - instances = instances->next(); - } - } - - _FORCE_INLINE_ void instance_remove_deps() { - SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first(); - while (instances) { - - SelfList<RasterizerScene::InstanceBase> *next = instances->next(); - instances->self()->base_removed(); - instances = next; - } - } - - Instantiable() {} - virtual ~Instantiable() { - } - }; - - struct GeometryOwner : public Instantiable { - - virtual ~GeometryOwner() {} - }; - struct Geometry : 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 */ - - struct RenderTarget; - - struct Texture { - - Texture *proxy; - Set<Texture *> proxy_owners; - - String path; - uint32_t flags; - int width, height, depth; - int alloc_width, alloc_height, alloc_depth; - Image::Format format; - VS::TextureType type; - - GLenum target; - GLenum gl_format_cache; - GLenum gl_internal_format_cache; - GLenum gl_type_cache; - int data_size; //original data size, useful for retrieving back - bool compressed; - bool srgb; - int total_data_size; - bool ignore_mipmaps; - - int mipmaps; - - bool is_npot_repeat_mipmap; - - bool active; - GLuint tex_id; - - bool using_srgb; - bool redraw_if_visible; - - uint16_t stored_cube_sides; - - RenderTarget *render_target; - - Vector<Ref<Image> > images; - - VisualServer::TextureDetectCallback detect_3d; - void *detect_3d_ud; - - VisualServer::TextureDetectCallback detect_srgb; - void *detect_srgb_ud; - - VisualServer::TextureDetectCallback detect_normal; - void *detect_normal_ud; - - Texture() : - proxy(NULL), - flags(0), - width(0), - height(0), - format(Image::FORMAT_L8), - type(VS::TEXTURE_TYPE_2D), - target(GL_TEXTURE_2D), - data_size(0), - compressed(false), - srgb(false), - total_data_size(0), - ignore_mipmaps(false), - mipmaps(0), - active(false), - tex_id(0), - using_srgb(false), - redraw_if_visible(false), - stored_cube_sides(0), - render_target(NULL), - detect_3d(NULL), - detect_3d_ud(NULL), - detect_srgb(NULL), - detect_srgb_ud(NULL), - detect_normal(NULL), - detect_normal_ud(NULL) { - } - - _ALWAYS_INLINE_ Texture *get_ptr() { - if (proxy) { - return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. - } else { - return this; - } - } - - ~Texture() { - - if (tex_id != 0) { - - glDeleteTextures(1, &tex_id); - } - - for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { - E->get()->proxy = NULL; - } - - if (proxy) { - proxy->proxy_owners.erase(this); - } - } - }; - - mutable RID_PtrOwner<Texture2D> 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 &r_srgb, bool p_force_decompress) const; - - 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, VS::TextureType p_type, uint32_t p_flags = VS::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 VS::TextureType texture_get_type(RID p_texture) const; - virtual uint32_t texture_get_texid(RID p_texture) const; - virtual uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual uint32_t texture_get_depth(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth); - virtual void texture_bind(RID p_texture, uint32_t p_texture_no); - - virtual void texture_set_path(RID p_texture, const String &p_path); - virtual String texture_get_path(RID p_texture) const; - - virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); - - virtual void texture_debug_usage(List<VS::TextureInfo> *r_info); - - 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_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); - - virtual void texture_set_proxy(RID p_texture, RID p_proxy); - virtual Size2 texture_size_with_proxy(RID p_texture) const; - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); - - /* SKY API */ - - struct Sky { - - RID panorama; - GLuint radiance; - GLuint irradiance; - 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; - - VS::ShaderMode mode; - ShaderGLES3 *shader; - String code; - SelfList<Material>::List materials; - - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; - Vector<uint32_t> ubo_offsets; - uint32_t ubo_size; - - uint32_t texture_count; - - uint32_t custom_code_id; - uint32_t version; - - SelfList<Shader> dirty_list; - - Map<StringName, RID> default_textures; - - Vector<ShaderLanguage::DataType> texture_types; - Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; - - bool valid; - - String path; - - struct CanvasItem { - - enum BlendMode { - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - BLEND_MODE_PMALPHA, - BLEND_MODE_DISABLED, - }; - - int blend_mode; - - enum LightMode { - LIGHT_MODE_NORMAL, - LIGHT_MODE_UNSHADED, - LIGHT_MODE_LIGHT_ONLY - }; - - int light_mode; - - bool uses_screen_texture; - bool uses_screen_uv; - bool uses_time; - - } 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 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; - ubo_size = 0; - valid = false; - custom_code_id = 0; - version = 1; - } - }; - - mutable SelfList<Shader>::List _shader_dirty_list; - void _shader_make_dirty(Shader *p_shader); - - mutable RID_PtrOwner<Shader> shader_owner; - - virtual RID shader_create(); - - virtual void shader_set_code(RID p_shader, const String &p_code); - virtual String shader_get_code(RID p_shader) const; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture); - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const; - - void _update_shader(Shader *p_shader) const; - - void update_dirty_shaders(); - - /* COMMON MATERIAL API */ - - struct Material { - - Shader *shader; - GLuint ubo_id; - uint32_t ubo_size; - Map<StringName, Variant> params; - SelfList<Material> list; - SelfList<Material> dirty_list; - Vector<bool> texture_is_3d; - Vector<RID> textures; - float line_width; - int render_priority; - - RID next_pass; - - uint32_t index; - uint64_t last_pass; - - Map<Geometry *, int> geometry_owners; - Map<RasterizerScene::InstanceBase *, int> instance_owners; - - bool can_cast_shadow_cache; - bool is_animated_cache; - - Material() : - shader(NULL), - ubo_id(0), - ubo_size(0), - list(this), - dirty_list(this), - line_width(1.0), - render_priority(0), - last_pass(0), - can_cast_shadow_cache(false), - is_animated_cache(false) { - } - }; - - 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); - - mutable RID_PtrOwner<Material> material_owner; - - virtual RID material_create(); - - virtual void material_set_shader(RID p_material, RID p_shader); - 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); - virtual Variant material_get_param(RID p_material, const StringName &p_param) const; - 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); - - virtual bool material_is_animated(RID p_material); - virtual bool material_casts_shadows(RID p_material); - - virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance); - virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance); - - virtual void material_set_render_priority(RID p_material, int priority); - - void _update_material(Material *material); - - void update_dirty_materials(); - - /* MESH API */ - - struct Mesh; - struct Surface : public Geometry { - - struct Attrib { - - bool enabled; - bool integer; - GLuint index; - GLint size; - GLenum type; - GLboolean normalized; - GLsizei stride; - uint32_t offset; - }; - - Attrib attribs[VS::ARRAY_MAX]; - - Mesh *mesh; - uint32_t format; - - GLuint array_id; - GLuint instancing_array_id; - GLuint vertex_id; - GLuint index_id; - - GLuint index_wireframe_id; - GLuint array_wireframe_id; - GLuint instancing_array_wireframe_id; - int index_wireframe_len; - - Vector<AABB> skeleton_bone_aabb; - Vector<bool> skeleton_bone_used; - - //bool packed; - - struct BlendShape { - GLuint vertex_id; - GLuint array_id; - }; - - Vector<BlendShape> blend_shapes; - - AABB aabb; - - int array_len; - int index_array_len; - int max_bone; - - int array_byte_size; - int index_array_byte_size; - - VS::PrimitiveType primitive; - - bool active; - - virtual void material_changed_notify() { - mesh->instance_change_notify(false, true); - mesh->update_multimeshes(); - } - - int total_data_size; - - Surface() : - mesh(NULL), - format(0), - array_id(0), - vertex_id(0), - index_id(0), - index_wireframe_id(0), - array_wireframe_id(0), - instancing_array_wireframe_id(0), - index_wireframe_len(0), - array_len(0), - index_array_len(0), - array_byte_size(0), - index_array_byte_size(0), - primitive(VS::PRIMITIVE_POINTS), - active(false), - total_data_size(0) { - type = GEOMETRY_SURFACE; - } - - ~Surface() { - } - }; - - struct MultiMesh; - - struct Mesh : public GeometryOwner { - - bool active; - Vector<Surface *> surfaces; - int blend_shape_count; - VS::BlendShapeMode blend_shape_mode; - AABB custom_aabb; - mutable uint64_t last_pass; - SelfList<MultiMesh>::List multimeshes; - _FORCE_INLINE_ void update_multimeshes() { - - SelfList<MultiMesh> *mm = multimeshes.first(); - while (mm) { - mm->self()->instance_change_notify(false, true); - mm = mm->next(); - } - } - - Mesh() : - active(false), - blend_shape_count(0), - blend_shape_mode(VS::BLEND_SHAPE_MODE_NORMALIZED), - last_pass(0) { - } - }; - - mutable RID_PtrOwner<Mesh> mesh_owner; - - virtual RID mesh_create(); - - virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()); - - virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount); - virtual int mesh_get_blend_shape_count(RID p_mesh) const; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode); - virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; - - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data); - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; - - virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; - virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; - - virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const; - virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const; - - virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; - virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; - - virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const; - virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const; - virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const; - - virtual void mesh_remove_surface(RID p_mesh, int p_surface); - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const; - virtual void mesh_clear(RID p_mesh); - - void mesh_render_blend_shapes(Surface *s, const float *p_weights); - - /* MULTIMESH API */ - - struct MultiMesh : public GeometryOwner { - RID mesh; - int size; - VS::MultimeshTransformFormat transform_format; - VS::MultimeshColorFormat color_format; - VS::MultimeshCustomDataFormat custom_data_format; - Vector<float> data; - AABB aabb; - SelfList<MultiMesh> update_list; - SelfList<MultiMesh> mesh_list; - GLuint buffer; - int visible_instances; - - int xform_floats; - int color_floats; - int custom_data_floats; - - bool dirty_aabb; - bool dirty_data; - - MultiMesh() : - size(0), - transform_format(VS::MULTIMESH_TRANSFORM_2D), - color_format(VS::MULTIMESH_COLOR_NONE), - custom_data_format(VS::MULTIMESH_CUSTOM_DATA_NONE), - update_list(this), - mesh_list(this), - buffer(0), - visible_instances(-1), - xform_floats(0), - color_floats(0), - custom_data_floats(0), - dirty_aabb(true), - dirty_data(true) { - } - }; - - mutable RID_PtrOwner<MultiMesh> multimesh_owner; - - SelfList<MultiMesh>::List multimesh_update_list; - - void update_dirty_multimeshes(); - - virtual RID multimesh_create(); - - virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE); - virtual int multimesh_get_instance_count(RID p_multimesh) const; - - virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh); - virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform); - virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform); - virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); - virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_custom_data); - - virtual RID multimesh_get_mesh(RID p_multimesh) const; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const; - virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const; - virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; - virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const; - - virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array); - - virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible); - virtual int multimesh_get_visible_instances(RID p_multimesh) const; - - virtual AABB multimesh_get_aabb(RID p_multimesh) const; - - /* IMMEDIATE API */ - - struct Immediate : public Geometry { - - struct Chunk { - - RID texture; - VS::PrimitiveType primitive; - Vector<Vector3> vertices; - Vector<Vector3> normals; - Vector<Plane> tangents; - Vector<Color> colors; - Vector<Vector2> uvs; - Vector<Vector2> uvs2; - }; - - List<Chunk> chunks; - bool building; - int mask; - AABB aabb; - - Immediate() { - type = GEOMETRY_IMMEDIATE; - building = false; - } - }; - - Vector3 chunk_vertex; - Vector3 chunk_normal; - Plane chunk_tangent; - Color chunk_color; - Vector2 chunk_uv; - Vector2 chunk_uv2; - - mutable RID_PtrOwner<Immediate> immediate_owner; - - virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture = RID()); - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex); - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal); - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent); - virtual void immediate_color(RID p_immediate, const Color &p_color); - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv); - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv); - virtual void immediate_end(RID p_immediate); - virtual void immediate_clear(RID p_immediate); - virtual void immediate_set_material(RID p_immediate, RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; - virtual AABB immediate_get_aabb(RID p_immediate) const; - - /* SKELETON API */ - - struct Skeleton { - bool use_2d; - int size; - Vector<float> skel_texture; - GLuint texture; - SelfList<Skeleton> update_list; - Set<RasterizerScene::InstanceBase *> instances; //instances using skeleton - Transform2D base_transform_2d; - - Skeleton() : - use_2d(false), - size(0), - texture(0), - update_list(this) { - } - }; - - mutable RID_PtrOwner<Skeleton> skeleton_owner; - - SelfList<Skeleton>::List skeleton_update_list; - - void update_dirty_skeletons(); - - virtual RID skeleton_create(); - virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false); - virtual int skeleton_get_bone_count(RID p_skeleton) const; - virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform); - virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const; - virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); - virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; - virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); - - /* Light API */ - - struct Light : Instantiable { - - VS::LightType type; - float param[VS::LIGHT_PARAM_MAX]; - Color color; - Color shadow_color; - RID projector; - bool shadow; - bool negative; - bool reverse_cull; - bool use_gi; - uint32_t cull_mask; - VS::LightOmniShadowMode omni_shadow_mode; - VS::LightOmniShadowDetail omni_shadow_detail; - VS::LightDirectionalShadowMode directional_shadow_mode; - VS::LightDirectionalShadowDepthRangeMode directional_range_mode; - bool directional_blend_splits; - uint64_t version; - }; - - mutable RID_PtrOwner<Light> light_owner; - - virtual RID light_create(VS::LightType p_type); - - virtual void light_set_color(RID p_light, const Color &p_color); - virtual void light_set_param(RID p_light, VS::LightParam p_param, float p_value); - virtual void light_set_shadow(RID p_light, bool p_enabled); - virtual void light_set_shadow_color(RID p_light, const Color &p_color); - virtual void light_set_projector(RID p_light, RID p_texture); - virtual void light_set_negative(RID p_light, bool p_enable); - virtual void light_set_cull_mask(RID p_light, uint32_t p_mask); - virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); - virtual void light_set_use_gi(RID p_light, bool p_enabled); - - virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode); - virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail); - - virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode); - virtual void light_directional_set_blend_splits(RID p_light, bool p_enable); - virtual bool light_directional_get_blend_splits(RID p_light) const; - - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); - - virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode); - virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; - - virtual bool light_has_shadow(RID p_light) const; - - virtual VS::LightType light_get_type(RID p_light) const; - virtual float light_get_param(RID p_light, VS::LightParam p_param); - virtual Color light_get_color(RID p_light); - virtual bool light_get_use_gi(RID p_light); - - virtual AABB light_get_aabb(RID p_light) const; - virtual uint64_t light_get_version(RID p_light) const; - - /* PROBE API */ - - struct ReflectionProbe : Instantiable { - - VS::ReflectionProbeUpdateMode update_mode; - float intensity; - Color interior_ambient; - float interior_ambient_energy; - float interior_ambient_probe_contrib; - float max_distance; - Vector3 extents; - Vector3 origin_offset; - bool interior; - bool box_projection; - bool enable_shadows; - uint32_t cull_mask; - }; - - mutable RID_PtrOwner<ReflectionProbe> reflection_probe_owner; - - virtual RID reflection_probe_create(); - - virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode); - virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity); - virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient); - virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy); - virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib); - virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance); - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents); - virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset); - virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable); - virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable); - virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable); - virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers); - virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution); - - virtual AABB reflection_probe_get_aabb(RID p_probe) const; - virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; - virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const; - - virtual Vector3 reflection_probe_get_extents(RID p_probe) const; - virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const; - virtual float reflection_probe_get_origin_max_distance(RID p_probe) const; - virtual bool reflection_probe_renders_shadows(RID p_probe) const; - - /* GI PROBE API */ - - struct GIProbe : public Instantiable { - - AABB bounds; - Transform to_cell; - float cell_size; - - int dynamic_range; - float energy; - float bias; - float normal_bias; - float propagation; - bool interior; - bool compress; - - uint32_t version; - - PoolVector<int> dynamic_data; - }; - - mutable RID_PtrOwner<GIProbe> gi_probe_owner; - - virtual RID gi_probe_create(); - - virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds); - virtual AABB gi_probe_get_bounds(RID p_probe) const; - - virtual void gi_probe_set_cell_size(RID p_probe, float p_size); - virtual float gi_probe_get_cell_size(RID p_probe) const; - - virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform); - virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const; - - virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data); - virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const; - - virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range); - virtual int gi_probe_get_dynamic_range(RID p_probe) const; - - virtual void gi_probe_set_energy(RID p_probe, float p_range); - virtual float gi_probe_get_energy(RID p_probe) const; - - virtual void gi_probe_set_bias(RID p_probe, float p_range); - virtual float gi_probe_get_bias(RID p_probe) const; - - virtual void gi_probe_set_normal_bias(RID p_probe, float p_range); - virtual float gi_probe_get_normal_bias(RID p_probe) const; - - virtual void gi_probe_set_propagation(RID p_probe, float p_range); - virtual float gi_probe_get_propagation(RID p_probe) const; - - virtual void gi_probe_set_interior(RID p_probe, bool p_enable); - virtual bool gi_probe_is_interior(RID p_probe) const; - - virtual void gi_probe_set_compress(RID p_probe, bool p_enable); - virtual bool gi_probe_is_compressed(RID p_probe) const; - - virtual uint32_t gi_probe_get_version(RID p_probe); - - struct GIProbeData { - - int width; - int height; - int depth; - int levels; - GLuint tex_id; - GIProbeCompression compression; - - GIProbeData() { - } - }; - - mutable RID_PtrOwner<GIProbeData> gi_probe_data_owner; - - virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const; - virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression); - virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data); - - /* LIGHTMAP CAPTURE */ - - virtual RID lightmap_capture_create(); - virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds); - virtual AABB lightmap_capture_get_bounds(RID p_capture) const; - virtual void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree); - virtual PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const; - virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform); - virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const; - virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv); - virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const; - - virtual void lightmap_capture_set_energy(RID p_capture, float p_energy); - virtual float lightmap_capture_get_energy(RID p_capture) const; - - virtual const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const; - - struct LightmapCapture : public Instantiable { - - PoolVector<LightmapCaptureOctree> octree; - AABB bounds; - Transform cell_xform; - int cell_subdiv; - float energy; - LightmapCapture() { - energy = 1.0; - cell_subdiv = 1; - } - }; - - mutable RID_PtrOwner<LightmapCapture> lightmap_capture_data_owner; - - /* PARTICLES */ - - struct Particles : public GeometryOwner { - - bool inactive; - float inactive_time; - bool emitting; - bool one_shot; - int amount; - float lifetime; - float pre_process_time; - float explosiveness; - float randomness; - bool restart_request; - AABB custom_aabb; - bool use_local_coords; - RID process_material; - - VS::ParticlesDrawOrder draw_order; - - Vector<RID> draw_passes; - - GLuint particle_buffers[2]; - GLuint particle_vaos[2]; - - GLuint particle_buffer_histories[2]; - GLuint particle_vao_histories[2]; - bool particle_valid_histories[2]; - bool histories_enabled; - - SelfList<Particles> particle_element; - - float phase; - float prev_phase; - uint64_t prev_ticks; - uint32_t random_seed; - - uint32_t cycle_number; - - float speed_scale; - - int fixed_fps; - bool fractional_delta; - float frame_remainder; - - bool clear; - - Transform emission_transform; - - Particles() : - inactive(true), - inactive_time(0.0), - emitting(false), - one_shot(false), - amount(0), - lifetime(1.0), - pre_process_time(0.0), - explosiveness(0.0), - randomness(0.0), - restart_request(false), - custom_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))), - use_local_coords(true), - draw_order(VS::PARTICLES_DRAW_ORDER_INDEX), - histories_enabled(false), - particle_element(this), - prev_ticks(0), - random_seed(0), - cycle_number(0), - speed_scale(1.0), - fixed_fps(0), - fractional_delta(false), - frame_remainder(0), - clear(true) { - particle_buffers[0] = 0; - particle_buffers[1] = 0; - glGenBuffers(2, particle_buffers); - glGenVertexArrays(2, particle_vaos); - } - - ~Particles() { - - glDeleteBuffers(2, particle_buffers); - glDeleteVertexArrays(2, particle_vaos); - if (histories_enabled) { - glDeleteBuffers(2, particle_buffer_histories); - glDeleteVertexArrays(2, particle_vao_histories); - } - } - }; - - SelfList<Particles>::List particle_update_list; - - void update_particles(); - - mutable RID_PtrOwner<Particles> particles_owner; - - virtual RID particles_create(); - - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_get_emitting(RID p_particles); - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual void particles_set_lifetime(RID p_particles, float p_lifetime); - virtual void particles_set_one_shot(RID p_particles, bool p_one_shot); - virtual void particles_set_pre_process_time(RID p_particles, float p_time); - virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio); - virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio); - virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb); - virtual void particles_set_speed_scale(RID p_particles, float p_scale); - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual void particles_set_process_material(RID p_particles, RID p_material); - virtual void particles_set_fixed_fps(RID p_particles, int p_fps); - virtual void particles_set_fractional_delta(RID p_particles, bool p_enable); - virtual void particles_restart(RID p_particles); - - virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order); - - virtual void particles_set_draw_passes(RID p_particles, int p_passes); - virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh); - - virtual void particles_request_process(RID p_particles); - virtual AABB particles_get_current_aabb(RID p_particles); - virtual AABB particles_get_aabb(RID p_particles) const; - - virtual void _particles_update_histories(Particles *particles); - - virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform); - void _particles_process(Particles *p_particles, float p_delta); - - virtual int particles_get_draw_passes(RID p_particles) const; - virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const; - - virtual bool particles_is_inactive(RID p_particles) const; - - /* INSTANCE */ - - virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); - virtual void instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); - - virtual void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); - virtual void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); - - /* RENDER TARGET */ - - struct RenderTarget { - - GLuint fbo; - GLuint color; - GLuint depth; - - struct Buffers { - - bool active; - bool effects_active; - GLuint fbo; - GLuint depth; - GLuint specular; - GLuint diffuse; - GLuint normal_rough; - GLuint sss; - - GLuint effect_fbo; - GLuint effect; - - } buffers; - - struct Effects { - - struct MipMaps { - - struct Size { - GLuint fbo; - int width; - int height; - }; - - Vector<Size> sizes; - GLuint color; - int levels; - - MipMaps() : - color(0), - levels(0) { - } - }; - - MipMaps mip_maps[2]; //first mipmap chain starts from full-screen - //GLuint depth2; //depth for the second mipmap chain, in case of desiring upsampling - - struct SSAO { - GLuint blur_fbo[2]; // blur fbo - GLuint blur_red[2]; // 8 bits red buffer - - GLuint linear_depth; - - Vector<GLuint> depth_mipmap_fbos; //fbos for depth mipmapsla ver - - SSAO() : - linear_depth(0) { - blur_fbo[0] = 0; - blur_fbo[1] = 0; - } - } ssao; - - Effects() {} - - } effects; - - struct Exposure { - GLuint fbo; - GLuint color; - - Exposure() : - fbo(0) {} - } exposure; - - // External FBO to render our final result to (mostly used for ARVR) - struct External { - GLuint fbo; - RID texture; - - External() : - fbo(0) {} - } external; - - uint64_t last_exposure_tick; - - int width, height; - - bool flags[RENDER_TARGET_FLAG_MAX]; - - bool used_in_frame; - VS::ViewportMSAA msaa; - - RID texture; - - RenderTarget() : - fbo(0), - depth(0), - last_exposure_tick(0), - width(0), - height(0), - used_in_frame(false), - msaa(VS::VIEWPORT_MSAA_DISABLED) { - exposure.fbo = 0; - buffers.fbo = 0; - external.fbo = 0; - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { - flags[i] = false; - } - flags[RENDER_TARGET_HDR] = true; - buffers.active = false; - buffers.effects_active = false; - } - }; - - mutable RID_PtrOwner<RenderTarget> render_target_owner; - - void _render_target_clear(RenderTarget *rt); - void _render_target_allocate(RenderTarget *rt); - - virtual RID render_target_create(); - virtual void render_target_set_position(RID p_render_target, int p_x, int p_y); - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height); - virtual RID render_target_get_texture(RID p_render_target) const; - virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id); - - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value); - virtual bool render_target_was_used(RID p_render_target); - virtual void render_target_set_as_unused(RID p_render_target); - virtual void render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa); - - /* CANVAS SHADOW */ - - struct CanvasLightShadow { - - 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 { - - GLuint array_id; // 0 means, unconfigured - GLuint vertex_id; // 0 means, unconfigured - GLuint index_id; // 0 means, unconfigured - PoolVector<Vector2> lines; - int len; - }; - - RID_PtrOwner<CanvasOccluder> canvas_occluder_owner; - - virtual RID canvas_light_occluder_create(); - virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines); - - virtual VS::InstanceType get_base_type(RID p_rid) const; - - virtual bool free(RID p_rid); - - struct Frame { - - RenderTarget *current_rt; - - bool clear_request; - Color clear_request_color; - int canvas_draw_commands; - float time[4]; - float delta; - uint64_t count; - - } frame; - - void initialize(); - void finalize(); - - virtual bool has_os_feature(const String &p_feature) const; - - virtual void update_dirty_resources(); - - virtual void set_debug_generate_wireframes(bool p_generate); - - virtual void render_info_begin_capture(); - virtual void render_info_end_capture(); - virtual int get_captured_render_info(VS::RenderInfo p_info); - - virtual int get_render_info(VS::RenderInfo p_info); - virtual String get_video_adapter_name() const; - virtual String get_video_adapter_vendor() const; - - RasterizerStorageGLES3(); -}; - -#endif // RASTERIZERSTORAGEGLES3_H diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp deleted file mode 100644 index a881e2eff8..0000000000 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ /dev/null @@ -1,1076 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_gles3.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_gles3.h" - -#include "core/os/os.h" -#include "core/project_settings.h" - -#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 int _get_datatype_size(SL::DataType p_type) { - - switch (p_type) { - - case SL::TYPE_VOID: return 0; - case SL::TYPE_BOOL: return 4; - case SL::TYPE_BVEC2: return 8; - case SL::TYPE_BVEC3: return 12; - case SL::TYPE_BVEC4: return 16; - case SL::TYPE_INT: return 4; - case SL::TYPE_IVEC2: return 8; - case SL::TYPE_IVEC3: return 12; - case SL::TYPE_IVEC4: return 16; - case SL::TYPE_UINT: return 4; - case SL::TYPE_UVEC2: return 8; - case SL::TYPE_UVEC3: return 12; - case SL::TYPE_UVEC4: return 16; - case SL::TYPE_FLOAT: return 4; - case SL::TYPE_VEC2: return 8; - case SL::TYPE_VEC3: return 12; - case SL::TYPE_VEC4: return 16; - case SL::TYPE_MAT2: - return 32; //4 * 4 + 4 * 4 - case SL::TYPE_MAT3: - return 48; // 4 * 4 + 4 * 4 + 4 * 4 - case SL::TYPE_MAT4: return 64; - case SL::TYPE_SAMPLER2D: return 16; - case SL::TYPE_ISAMPLER2D: return 16; - case SL::TYPE_USAMPLER2D: return 16; - case SL::TYPE_SAMPLER2DARRAY: return 16; - case SL::TYPE_ISAMPLER2DARRAY: return 16; - case SL::TYPE_USAMPLER2DARRAY: return 16; - case SL::TYPE_SAMPLER3D: return 16; - case SL::TYPE_ISAMPLER3D: return 16; - case SL::TYPE_USAMPLER3D: return 16; - case SL::TYPE_SAMPLERCUBE: return 16; - } - - ERR_FAIL_V(0); -} - -static int _get_datatype_alignment(SL::DataType p_type) { - - switch (p_type) { - - case SL::TYPE_VOID: return 0; - case SL::TYPE_BOOL: return 4; - case SL::TYPE_BVEC2: return 8; - case SL::TYPE_BVEC3: return 16; - case SL::TYPE_BVEC4: return 16; - case SL::TYPE_INT: return 4; - case SL::TYPE_IVEC2: return 8; - case SL::TYPE_IVEC3: return 16; - case SL::TYPE_IVEC4: return 16; - case SL::TYPE_UINT: return 4; - case SL::TYPE_UVEC2: return 8; - case SL::TYPE_UVEC3: return 16; - case SL::TYPE_UVEC4: return 16; - case SL::TYPE_FLOAT: return 4; - case SL::TYPE_VEC2: return 8; - case SL::TYPE_VEC3: return 16; - case SL::TYPE_VEC4: return 16; - case SL::TYPE_MAT2: return 16; - case SL::TYPE_MAT3: return 16; - case SL::TYPE_MAT4: return 16; - case SL::TYPE_SAMPLER2D: return 16; - case SL::TYPE_ISAMPLER2D: return 16; - case SL::TYPE_USAMPLER2D: return 16; - case SL::TYPE_SAMPLER2DARRAY: return 16; - case SL::TYPE_ISAMPLER2DARRAY: return 16; - case SL::TYPE_USAMPLER2DARRAY: return 16; - case SL::TYPE_SAMPLER3D: return 16; - case SL::TYPE_ISAMPLER3D: return 16; - case SL::TYPE_USAMPLER3D: return 16; - case SL::TYPE_SAMPLERCUBE: return 16; - } - - ERR_FAIL_V(0); -} -static String _interpstr(SL::DataInterpolation p_interp) { - - switch (p_interp) { - case SL::INTERPOLATION_FLAT: return "flat "; - case SL::INTERPOLATION_SMOOTH: return ""; - } - return ""; -} - -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 ""; - 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: { - - String text = "bvec" + itos(p_type - SL::TYPE_BOOL + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += p_values[i].boolean ? "true" : "false"; - } - text += ")"; - return text; - } - - case SL::TYPE_INT: return itos(p_values[0].sint); - case SL::TYPE_IVEC2: - case SL::TYPE_IVEC3: - case SL::TYPE_IVEC4: { - - String text = "ivec" + itos(p_type - SL::TYPE_INT + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += itos(p_values[i].sint); - } - text += ")"; - return text; - - } break; - case SL::TYPE_UINT: return itos(p_values[0].uint) + "u"; - case SL::TYPE_UVEC2: - case SL::TYPE_UVEC3: - case SL::TYPE_UVEC4: { - - String text = "uvec" + itos(p_type - SL::TYPE_UINT + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += itos(p_values[i].uint) + "u"; - } - text += ")"; - return text; - } break; - case SL::TYPE_FLOAT: return f2sp0(p_values[0].real); - case SL::TYPE_VEC2: - case SL::TYPE_VEC3: - case SL::TYPE_VEC4: { - - String text = "vec" + itos(p_type - SL::TYPE_FLOAT + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += f2sp0(p_values[i].real); - } - text += ")"; - return text; - - } break; - case SL::TYPE_MAT2: - case SL::TYPE_MAT3: - case SL::TYPE_MAT4: { - - String text = "mat" + itos(p_type - SL::TYPE_MAT2 + 2) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += f2sp0(p_values[i].real); - } - text += ")"; - return text; - - } break; - default: ERR_FAIL_V(String()); - } -} - -void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &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 (added.has(E->get())) { - continue; //was added already - } - - _dump_function_deps(p_node, E->get(), p_func_code, r_to_add, 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"; - - String header; - header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "("; - for (int i = 0; i < fnode->arguments.size(); i++) { - - if (i > 0) - header += ", "; - header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name); - } - - header += ")\n"; - r_to_add += header; - r_to_add += p_func_code[E->get()]; - - added.insert(E->get()); - } -} - -String ShaderCompilerGLES3::_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) { - - String code; - - switch (p_node->type) { - - case SL::Node::TYPE_SHADER: { - - SL::ShaderNode *pnode = (SL::ShaderNode *)p_node; - - for (int i = 0; i < pnode->render_modes.size(); i++) { - - if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) { - - r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]].utf8()); - used_rmode_defines.insert(pnode->render_modes[i]); - } - - if (p_actions.render_mode_flags.has(pnode->render_modes[i])) { - *p_actions.render_mode_flags[pnode->render_modes[i]] = true; - } - - if (p_actions.render_mode_values.has(pnode->render_modes[i])) { - Pair<int *, int> &p = p_actions.render_mode_values[pnode->render_modes[i]]; - *p.first = p.second; - } - } - - int max_texture_uniforms = 0; - int max_uniforms = 0; - - for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->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); - - Vector<int> uniform_sizes; - Vector<int> uniform_alignments; - Vector<StringName> uniform_defines; - uniform_sizes.resize(max_uniforms); - uniform_alignments.resize(max_uniforms); - uniform_defines.resize(max_uniforms); - bool uses_uniforms = false; - - for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) { - - String ucode; - - if (SL::is_sampler_type(E->get().type)) { - ucode = "uniform "; - } - - ucode += _prestr(E->get().precision); - ucode += _typestr(E->get().type); - ucode += " " + _mkid(E->key()); - ucode += ";\n"; - if (SL::is_sampler_type(E->get().type)) { - r_gen_code.vertex_global += ucode; - r_gen_code.fragment_global += ucode; - - GeneratedCode::Texture texture; - texture.name = _mkid(E->key()); - texture.hint = E->get().hint; - texture.type = E->get().type; - texture.filter = E->get().filter; - texture.repeat = E->get().repeat; - - r_gen_code.texture_uniforms.write[E->get().texture_order] = texture; - } else { - if (!uses_uniforms) { - - r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii()); - uses_uniforms = true; - } - uniform_defines.write[E->get().order] = ucode; - uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type); - uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type); - } - - p_actions.uniforms->insert(E->key(), E->get()); - } - - for (int i = 0; i < max_uniforms; i++) { - r_gen_code.uniforms += uniform_defines[i]; - } - - // add up - int offset = 0; - for (int i = 0; i < uniform_sizes.size(); i++) { - - int align = offset % uniform_alignments[i]; - - if (align != 0) { - offset += uniform_alignments[i] - align; - } - - r_gen_code.uniform_offsets.push_back(offset); - - offset += uniform_sizes[i]; - } - - r_gen_code.uniform_total_size = offset; - if (r_gen_code.uniform_total_size % 16 != 0) { //UBO sizes must be multiples of 16 - r_gen_code.uniform_total_size += r_gen_code.uniform_total_size % 16; - } - - for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) { - - String vcode; - String interp_mode = _interpstr(E->get().interpolation); - vcode += _prestr(E->get().precision); - vcode += _typestr(E->get().type); - vcode += " " + _mkid(E->key()); - if (E->get().array_size > 0) { - vcode += "["; - vcode += itos(E->get().array_size); - vcode += "]"; - } - vcode += ";\n"; - r_gen_code.vertex_global += interp_mode + "out " + vcode; - r_gen_code.fragment_global += interp_mode + "in " + vcode; - } - - for (Map<StringName, SL::ShaderNode::Constant>::Element *E = pnode->constants.front(); E; E = E->next()) { - String gcode; - gcode += "const "; - gcode += _prestr(E->get().precision); - gcode += _typestr(E->get().type); - gcode += " " + _mkid(E->key()); - gcode += "="; - gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - gcode += ";\n"; - r_gen_code.vertex_global += gcode; - r_gen_code.fragment_global += gcode; - } - - Map<StringName, String> function_code; - - //code for functions - for (int i = 0; i < pnode->functions.size(); i++) { - SL::FunctionNode *fnode = pnode->functions[i].function; - current_func_name = fnode->name; - function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } - - //place functions in actual code - - Set<StringName> added_vtx; - Set<StringName> added_fragment; //share for light - - for (int i = 0; i < pnode->functions.size(); i++) { - - SL::FunctionNode *fnode = pnode->functions[i].function; - - current_func_name = fnode->name; - - if (fnode->name == vertex_name) { - - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.vertex_global, added_vtx); - r_gen_code.vertex = function_code[vertex_name]; - } - - if (fnode->name == fragment_name) { - - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.fragment = function_code[fragment_name]; - } - - if (fnode->name == light_name) { - - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.light = function_code[light_name]; - } - } - - //code+=dump_node_code(pnode->body,p_level); - } break; - case SL::Node::TYPE_FUNCTION: { - - } break; - case SL::Node::TYPE_BLOCK: { - SL::BlockNode *bnode = (SL::BlockNode *)p_node; - - //variables - if (!bnode->single_statement) { - code += _mktab(p_level - 1) + "{\n"; - } - - for (int i = 0; i < bnode->statements.size(); i++) { - - String scode = _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 += scode; //use directly - } else { - code += _mktab(p_level) + scode + ";\n"; - } - } - if (!bnode->single_statement) { - code += _mktab(p_level - 1) + "}\n"; - } - - } break; - case SL::Node::TYPE_VARIABLE_DECLARATION: { - SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node; - - String declaration; - if (vdnode->is_const) { - declaration += "const "; - } - declaration += _prestr(vdnode->precision); - declaration += _typestr(vdnode->datatype); - for (int i = 0; i < vdnode->declarations.size(); i++) { - if (i > 0) { - declaration += ","; - } else { - declaration += " "; - } - declaration += _mkid(vdnode->declarations[i].name); - if (vdnode->declarations[i].initializer) { - declaration += "="; - declaration += _dump_node_code(vdnode->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - } - - code += declaration; - } break; - case SL::Node::TYPE_VARIABLE: { - SL::VariableNode *vnode = (SL::VariableNode *)p_node; - - if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) { - *p_actions.write_flag_pointers[vnode->name] = true; - } - - if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) { - String define = p_default_actions.usage_defines[vnode->name]; - if (define.begins_with("@")) { - define = p_default_actions.usage_defines[define.substr(1, define.length())]; - } - r_gen_code.defines.push_back(define.utf8()); - used_name_defines.insert(vnode->name); - } - - if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) { - *p_actions.usage_flag_pointers[vnode->name] = true; - used_flag_pointers.insert(vnode->name); - } - - if (p_default_actions.renames.has(vnode->name)) - code = p_default_actions.renames[vnode->name]; - else - code = _mkid(vnode->name); - - if (vnode->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 *adnode = (SL::ArrayDeclarationNode *)p_node; - - String declaration; - if (adnode->is_const) { - declaration += "const "; - } - declaration += _prestr(adnode->precision); - declaration += _typestr(adnode->datatype); - for (int i = 0; i < adnode->declarations.size(); i++) { - if (i > 0) { - declaration += ","; - } else { - declaration += " "; - } - declaration += _mkid(adnode->declarations[i].name); - declaration += "["; - declaration += itos(adnode->declarations[i].size); - declaration += "]"; - int sz = adnode->declarations[i].initializer.size(); - if (sz > 0) { - declaration += "="; - declaration += _typestr(adnode->datatype); - declaration += "["; - declaration += itos(sz); - declaration += "]"; - declaration += "("; - for (int j = 0; j < sz; j++) { - declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (j != sz - 1) { - declaration += ", "; - } - } - declaration += ")"; - } - } - - code += declaration; - } break; - case SL::Node::TYPE_ARRAY: { - SL::ArrayNode *anode = (SL::ArrayNode *)p_node; - - if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) { - *p_actions.write_flag_pointers[anode->name] = true; - } - - if (p_default_actions.usage_defines.has(anode->name) && !used_name_defines.has(anode->name)) { - String define = p_default_actions.usage_defines[anode->name]; - if (define.begins_with("@")) { - define = p_default_actions.usage_defines[define.substr(1, define.length())]; - } - r_gen_code.defines.push_back(define.utf8()); - used_name_defines.insert(anode->name); - } - - if (p_actions.usage_flag_pointers.has(anode->name) && !used_flag_pointers.has(anode->name)) { - *p_actions.usage_flag_pointers[anode->name] = true; - used_flag_pointers.insert(anode->name); - } - - if (p_default_actions.renames.has(anode->name)) - code = p_default_actions.renames[anode->name]; - else - code = _mkid(anode->name); - - if (anode->call_expression != NULL) { - code += "."; - code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - - if (anode->index_expression != NULL) { - code += "["; - code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "]"; - } - - if (anode->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 *cnode = (SL::ConstantNode *)p_node; - return get_constant_text(cnode->datatype, cnode->values); - - } break; - case SL::Node::TYPE_OPERATOR: { - SL::OperatorNode *onode = (SL::OperatorNode *)p_node; - - switch (onode->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_MOD: - case SL::OP_ASSIGN_BIT_AND: - case SL::OP_ASSIGN_BIT_OR: - case SL::OP_ASSIGN_BIT_XOR: - code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - break; - case SL::OP_BIT_INVERT: - case SL::OP_NEGATE: - case SL::OP_NOT: - case SL::OP_DECREMENT: - case SL::OP_INCREMENT: - code = _opstr(onode->op) + _dump_node_code(onode->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(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op); - break; - case SL::OP_CALL: - case SL::OP_CONSTRUCT: { - - ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String()); - - SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0]; - - if (onode->op == SL::OP_CONSTRUCT) { - code += String(vnode->name); - } else { - - if (internal_functions.has(vnode->name)) { - code += vnode->name; - } else if (p_default_actions.renames.has(vnode->name)) { - code += p_default_actions.renames[vnode->name]; - } else { - code += _mkid(vnode->name); - } - } - - code += "("; - - for (int i = 1; i < onode->arguments.size(); i++) { - if (i > 1) - code += ", "; - code += _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - code += ")"; - } break; - case SL::OP_INDEX: { - - code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "["; - code += _dump_node_code(onode->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(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "?"; - code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ":"; - code += _dump_node_code(onode->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ")"; - - } break; - - default: { - - code = "(" + _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")"; - break; - } - } - - } break; - case SL::Node::TYPE_CONTROL_FLOW: { - SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node; - if (cfnode->flow_op == SL::FLOW_OP_IF) { - - code += _mktab(p_level) + "if (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - if (cfnode->blocks.size() == 2) { - - code += _mktab(p_level) + "else\n"; - code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } - } else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) { - code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_CASE) { - code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) { - code += _mktab(p_level) + "default:\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_DO) { - code += _mktab(p_level) + "do"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ");"; - - } else if (cfnode->flow_op == SL::FLOW_OP_WHILE) { - - code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_FOR) { - - String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n"; - code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - - } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) { - - if (cfnode->expressions.size()) { - code = "return " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ";"; - } else { - code = "return;"; - } - } else if (cfnode->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 (cfnode->flow_op == SL::FLOW_OP_CONTINUE) { - - code = "continue;"; - } else if (cfnode->flow_op == SL::FLOW_OP_BREAK) { - - code = "break;"; - } - - } break; - case SL::Node::TYPE_MEMBER: { - SL::MemberNode *mnode = (SL::MemberNode *)p_node; - code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name; - - } break; - } - - return code; -} - -Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { - - Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types()); - - 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.defines.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); - - if (r_gen_code.uniform_total_size) { //uniforms used? - int md = sizeof(float) * 4; - if (r_gen_code.uniform_total_size % md) { - r_gen_code.uniform_total_size += md - (r_gen_code.uniform_total_size % md); - } - r_gen_code.uniform_total_size += md; //pad just in case - } - - return OK; -} - -ShaderCompilerGLES3::ShaderCompilerGLES3() { - - /** CANVAS ITEM SHADER **/ - - actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy"; - actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv"; - actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "point_size"; - - actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix"; - actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] = "extra_matrix"; - actions[VS::SHADER_CANVAS_ITEM].renames["TIME"] = "time"; - actions[VS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass"; - actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom"; - - actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; - actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture"; - actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture"; - actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv"; - actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; - actions[VS::SHADER_CANVAS_ITEM].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord"; - - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light"; - actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color"; - actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_VEC"] = "shadow_vec"; - - actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_VEC"] = "#define SHADOW_VEC_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - - /** SPATIAL SHADER **/ - - actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; - actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; - actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; - actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; - actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; - - actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; - actions[VS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; - actions[VS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; - actions[VS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; - actions[VS::SHADER_SPATIAL].renames["POSITION"] = "position"; - actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; - actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; - actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; - actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "point_size"; - actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID"; - - //builtins - - actions[VS::SHADER_SPATIAL].renames["TIME"] = "time"; - actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; - - actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; - actions[VS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; - actions[VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; - actions[VS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; - actions[VS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; - actions[VS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; - actions[VS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; - actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; - actions[VS::SHADER_SPATIAL].renames["RIM"] = "rim"; - actions[VS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; - actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; - actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; - actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; - actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; - actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; - actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; - actions[VS::SHADER_SPATIAL].renames["AO"] = "ao"; - actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; - actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; - actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; - actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; - actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; - actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; - actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; - actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - - //for light - actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view"; - actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; - actions[VS::SHADER_SPATIAL].renames["LIGHT"] = "light"; - actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; - actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; - actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; - - actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; - actions[VS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; - actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; - actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; - actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; - actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions[VS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; - actions[VS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; - actions[VS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; - actions[VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; - actions[VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - - actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; - actions[VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - - actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - - actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; - actions[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[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; - } - - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; - actions[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[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } - - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; - - /* PARTICLES SHADER */ - - actions[VS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; - actions[VS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; - actions[VS::SHADER_PARTICLES].renames["MASS"] = "mass"; - actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "shader_active"; - actions[VS::SHADER_PARTICLES].renames["RESTART"] = "restart"; - actions[VS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom"; - actions[VS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; - actions[VS::SHADER_PARTICLES].renames["TIME"] = "time"; - actions[VS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime"; - actions[VS::SHADER_PARTICLES].renames["DELTA"] = "local_delta"; - actions[VS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number"; - actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index"; - actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; - actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; - actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; - - actions[VS::SHADER_PARTICLES].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; - actions[VS::SHADER_PARTICLES].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; - actions[VS::SHADER_PARTICLES].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; - - 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()); - } -} diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h deleted file mode 100644 index 50fe4da097..0000000000 --- a/drivers/gles3/shader_compiler_gles3.h +++ /dev/null @@ -1,109 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_gles3.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. */ -/*************************************************************************/ - -#ifndef SHADERCOMPILERGLES3_H -#define SHADERCOMPILERGLES3_H - -#include "core/pair.h" -#include "servers/visual/shader_language.h" -#include "servers/visual/shader_types.h" -#include "servers/visual_server.h" - -class ShaderCompilerGLES3 { -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> defines; - struct Texture { - StringName name; - ShaderLanguage::DataType type; - ShaderLanguage::ShaderNode::Uniform::Hint hint; - ShaderLanguage::ShaderNode::Uniform::Filter filter; - ShaderLanguage::ShaderNode::Uniform::Repeat repeat; - }; - - Vector<Texture> texture_uniforms; - - Vector<uint32_t> uniform_offsets; - uint32_t uniform_total_size; - String uniforms; - 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, String &r_to_add, Set<StringName> &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); - - 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[VS::SHADER_MAX]; - -public: - Error compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); - - ShaderCompilerGLES3(); -}; - -#endif // SHADERCOMPILERGLES3_H diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp deleted file mode 100644 index 69f42c4d6d..0000000000 --- a/drivers/gles3/shader_gles3.cpp +++ /dev/null @@ -1,777 +0,0 @@ -/*************************************************************************/ -/* shader_gles3.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_gles3.h" - -#include "core/print_string.h" - -//#define DEBUG_OPENGL - -#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 - -ShaderGLES3 *ShaderGLES3::active = NULL; - -//#define DEBUG_SHADER - -#ifdef DEBUG_SHADER - -#define DEBUG_PRINT(m_text) print_line(m_text); - -#else - -#define DEBUG_PRINT(m_text) - -#endif - -void ShaderGLES3::bind_uniforms() { - - if (!uniforms_dirty) { - return; - }; - - // upload default uniforms - const Map<uint32_t, Variant>::Element *E = uniform_defaults.front(); - - while (E) { - int idx = E->key(); - int location = version->uniform_location[idx]; - - if (location < 0) { - E = E->next(); - continue; - } - - const Variant &v = E->value(); - _set_uniform_variant(location, v); - //print_line("uniform "+itos(location)+" value "+v+ " type "+Variant::get_type_name(v.get_type())); - E = E->next(); - }; - - const Map<uint32_t, CameraMatrix>::Element *C = uniform_cameras.front(); - while (C) { - - int location = version->uniform_location[C->key()]; - if (location < 0) { - C = C->next(); - continue; - } - - glUniformMatrix4fv(location, 1, false, &(C->get().matrix[0][0])); - C = C->next(); - }; - - uniforms_dirty = false; -} - -GLint ShaderGLES3::get_uniform_location(int p_index) const { - - ERR_FAIL_COND_V(!version, -1); - - return version->uniform_location[p_index]; -} - -bool ShaderGLES3::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 ShaderGLES3::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); -} - -ShaderGLES3::Version *ShaderGLES3::get_current_version() { - - 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) { - //bye bye shaders - glDeleteShader(v.vert_id); - glDeleteShader(v.frag_id); - glDeleteProgram(v.id); - v.id = 0; - } - } - - v.ok = false; - /* SETUP CONDITIONALS */ - - Vector<const char *> strings; -#ifdef GLES_OVER_GL - strings.push_back("#version 330\n"); - strings.push_back("#define GLES_OVER_GL\n"); -#else - strings.push_back("#version 300 es\n"); -#endif - - for (int i = 0; i < custom_defines.size(); i++) { - - strings.push_back(custom_defines[i].get_data()); - } - - for (int j = 0; j < conditional_count; j++) { - - bool enable = ((1 << j) & conditional_version.version); - strings.push_back(enable ? conditional_defines[j] : ""); - - if (enable) { - DEBUG_PRINT(conditional_defines[j]); - } - } - - //keep them around during the function - CharString code_string; - CharString code_string2; - CharString code_globals; - CharString material_string; - - CustomCode *cc = NULL; - - if (conditional_version.code_version > 0) { - //do custom code related stuff - - ERR_FAIL_COND_V(!custom_code_map.has(conditional_version.code_version), NULL); - cc = &custom_code_map[conditional_version.code_version]; - v.code_version = cc->version; - } - - /* CREATE PROGRAM */ - - v.id = glCreateProgram(); - - ERR_FAIL_COND_V(v.id == 0, NULL); - - /* VERTEX SHADER */ - - if (cc) { - for (int i = 0; i < cc->custom_defines.size(); i++) { - - strings.push_back(cc->custom_defines[i].get_data()); - DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i])); - } - } - - int strings_base_size = strings.size(); - - //vertex precision is high - strings.push_back("precision highp float;\n"); - strings.push_back("precision highp int;\n"); -#ifndef GLES_OVER_GL - strings.push_back("precision highp sampler2D;\n"); - strings.push_back("precision highp samplerCube;\n"); - strings.push_back("precision highp sampler2DArray;\n"); -#endif - - strings.push_back(vertex_code0.get_data()); - - if (cc) { - material_string = cc->uniforms.ascii(); - strings.push_back(material_string.get_data()); - } - - strings.push_back(vertex_code1.get_data()); - - if (cc) { - code_globals = cc->vertex_globals.ascii(); - strings.push_back(code_globals.get_data()); - } - - strings.push_back(vertex_code2.get_data()); - - if (cc) { - code_string = cc->vertex.ascii(); - strings.push_back(code_string.get_data()); - } - - strings.push_back(vertex_code3.get_data()); -#ifdef DEBUG_SHADER - - DEBUG_PRINT("\nVertex Code:\n\n" + String(code_string.get_data())); - for (int i = 0; i < strings.size(); i++) { - - //print_line("vert strings "+itos(i)+":"+String(strings[i])); - } -#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) { - // error compiling - 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("Vertex shader compilation failed with empty log"); - } else { - - if (iloglen == 0) { - - iloglen = 4096; //buggy driver (Adreno 220+....) - } - - char *ilogmem = (char *)memalloc(iloglen + 1); - ilogmem[iloglen] = 0; - glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem); - - String err_string = get_shader_name() + ": Vertex Program Compilation Failed:\n"; - - err_string += ilogmem; - _display_error_with_code(err_string, strings); - memfree(ilogmem); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - } - - ERR_FAIL_V(NULL); - } - - //_display_error_with_code("pepo", strings); - - /* FRAGMENT SHADER */ - - strings.resize(strings_base_size); - //fragment precision is medium - strings.push_back("precision highp float;\n"); - strings.push_back("precision highp int;\n"); -#ifndef GLES_OVER_GL - strings.push_back("precision highp sampler2D;\n"); - strings.push_back("precision highp samplerCube;\n"); - strings.push_back("precision highp sampler2DArray;\n"); -#endif - - strings.push_back(fragment_code0.get_data()); - if (cc) { - material_string = cc->uniforms.ascii(); - strings.push_back(material_string.get_data()); - } - - strings.push_back(fragment_code1.get_data()); - - if (cc) { - code_globals = cc->fragment_globals.ascii(); - strings.push_back(code_globals.get_data()); - } - - strings.push_back(fragment_code2.get_data()); - - if (cc) { - code_string = cc->light.ascii(); - strings.push_back(code_string.get_data()); - } - - strings.push_back(fragment_code3.get_data()); - - if (cc) { - code_string2 = cc->fragment.ascii(); - strings.push_back(code_string2.get_data()); - } - - strings.push_back(fragment_code4.get_data()); - -#ifdef DEBUG_SHADER - DEBUG_PRINT("\nFragment Globals:\n\n" + String(code_globals.get_data())); - DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string2.get_data())); - for (int i = 0; i < strings.size(); i++) { - - //print_line("frag strings "+itos(i)+":"+String(strings[i])); - } -#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) { - // error compiling - 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("Fragment shader compilation failed with empty log"); - } else { - - if (iloglen == 0) { - - iloglen = 4096; //buggy driver (Adreno 220+....) - } - - char *ilogmem = (char *)memalloc(iloglen + 1); - ilogmem[iloglen] = 0; - glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem); - - String err_string = get_shader_name() + ": Fragment Program Compilation Failed:\n"; - - err_string += ilogmem; - _display_error_with_code(err_string, strings); - ERR_PRINT(err_string.ascii().get_data()); - memfree(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 attributes before linking - for (int i = 0; i < attribute_pair_count; i++) { - - glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name); - } - - //if feedback exists, set it up - - if (feedback_count) { - Vector<const char *> feedback; - for (int i = 0; i < feedback_count; i++) { - - if (feedbacks[i].conditional == -1 || (1 << feedbacks[i].conditional) & conditional_version.version) { - //conditional for this feedback is enabled - feedback.push_back(feedbacks[i].name); - } - } - - if (feedback.size()) { - glTransformFeedbackVaryings(v.id, feedback.size(), feedback.ptr(), GL_INTERLEAVED_ATTRIBS); - } - } - - glLinkProgram(v.id); - - glGetProgramiv(v.id, GL_LINK_STATUS, &status); - - if (status == GL_FALSE) { - // error linking - 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_FAIL_COND_V(iloglen < 0, 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 LINK FAILED:\n"; - - err_string += ilogmem; - _display_error_with_code(err_string, strings); - ERR_PRINT(err_string.ascii().get_data()); - Memory::free_static(ilogmem); - glDeleteShader(v.frag_id); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - - ERR_FAIL_V(NULL); - } - - /* UNIFORMS */ - - glUseProgram(v.id); - - //print_line("uniforms: "); - for (int j = 0; j < uniform_count; j++) { - - v.uniform_location[j] = glGetUniformLocation(v.id, uniform_names[j]); - //print_line("uniform "+String(uniform_names[j])+" location "+itos(v.uniform_location[j])); - } - - // set texture uniforms - 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); //negative, goes down - } else { - - glUniform1i(loc, texunit_pairs[i].index); - } - } - } - - // assign uniform block bind points - for (int i = 0; i < ubo_count; i++) { - - GLint loc = glGetUniformBlockIndex(v.id, ubo_pairs[i].name); - if (loc >= 0) - glUniformBlockBinding(v.id, loc, ubo_pairs[i].index); - } - - if (cc) { - - v.texture_uniform_locations.resize(cc->texture_uniforms.size()); - for (int i = 0; i < cc->texture_uniforms.size(); i++) { - - v.texture_uniform_locations.write[i] = glGetUniformLocation(v.id, String(cc->texture_uniforms[i]).ascii().get_data()); - glUniform1i(v.texture_uniform_locations[i], i + base_material_tex_index); - } - } - - glUseProgram(0); - - v.ok = true; - if (cc) { - cc->versions.insert(conditional_version.version); - } - - return &v; -} - -GLint ShaderGLES3::get_uniform_location(const String &p_name) const { - - ERR_FAIL_COND_V(!version, -1); - return glGetUniformLocation(version->id, p_name.ascii().get_data()); -} - -void ShaderGLES3::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 UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_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; - ubo_pairs = p_ubo_pairs; - ubo_count = p_ubo_pair_count; - feedbacks = p_feedback; - feedback_count = p_feedback_count; - - //split vertex and shader code (thank you, shader compiler programmers from you know what company). - { - String globals_tag = "\nVERTEX_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nVERTEX_SHADER_CODE"; - String code = vertex_code; - int cpos = code.find(material_tag); - if (cpos == -1) { - vertex_code0 = code.ascii(); - } else { - vertex_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + material_tag.length(), code.length()); - - cpos = code.find(globals_tag); - - if (cpos == -1) { - vertex_code1 = code.ascii(); - } else { - - vertex_code1 = code.substr(0, cpos).ascii(); - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code2.find(code_tag); - if (cpos == -1) { - vertex_code2 = code2.ascii(); - } else { - - vertex_code2 = code2.substr(0, cpos).ascii(); - vertex_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); - } - } - } - } - - { - String globals_tag = "\nFRAGMENT_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nFRAGMENT_SHADER_CODE"; - String light_code_tag = "\nLIGHT_SHADER_CODE"; - String code = fragment_code; - int cpos = code.find(material_tag); - if (cpos == -1) { - fragment_code0 = code.ascii(); - } else { - fragment_code0 = code.substr(0, cpos).ascii(); - //print_line("CODE0:\n"+String(fragment_code0.get_data())); - code = code.substr(cpos + material_tag.length(), code.length()); - cpos = code.find(globals_tag); - - if (cpos == -1) { - fragment_code1 = code.ascii(); - } else { - - fragment_code1 = code.substr(0, cpos).ascii(); - //print_line("CODE1:\n"+String(fragment_code1.get_data())); - - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - cpos = code2.find(light_code_tag); - - if (cpos == -1) { - fragment_code2 = code2.ascii(); - } else { - - fragment_code2 = code2.substr(0, cpos).ascii(); - //print_line("CODE2:\n"+String(fragment_code2.get_data())); - - String code3 = code2.substr(cpos + light_code_tag.length(), code2.length()); - - cpos = code3.find(code_tag); - if (cpos == -1) { - fragment_code3 = code3.ascii(); - } else { - - fragment_code3 = code3.substr(0, cpos).ascii(); - //print_line("CODE3:\n"+String(fragment_code3.get_data())); - fragment_code4 = code3.substr(cpos + code_tag.length(), code3.length()).ascii(); - //print_line("CODE4:\n"+String(fragment_code4.get_data())); - } - } - } - } - } - - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units); -} - -void ShaderGLES3::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); - memdelete_arr(v.uniform_location); - } -} - -void ShaderGLES3::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 ShaderGLES3::create_custom_shader() { - - custom_code_map[last_custom_code] = CustomCode(); - custom_code_map[last_custom_code].version = 1; - return last_custom_code++; -} - -void ShaderGLES3::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 String &p_uniforms, const Vector<StringName> &p_texture_uniforms, const Vector<CharString> &p_custom_defines) { - - ERR_FAIL_COND(!custom_code_map.has(p_code_id)); - CustomCode *cc = &custom_code_map[p_code_id]; - - cc->vertex = p_vertex; - cc->vertex_globals = p_vertex_globals; - cc->fragment = p_fragment; - cc->fragment_globals = p_fragment_globals; - cc->light = p_light; - cc->texture_uniforms = p_texture_uniforms; - cc->uniforms = p_uniforms; - cc->custom_defines = p_custom_defines; - cc->version++; -} - -void ShaderGLES3::set_custom_shader(uint32_t p_code_id) { - - new_conditional_version.code_version = p_code_id; -} - -void ShaderGLES3::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 ShaderGLES3::set_base_material_tex_index(int p_idx) { - - base_material_tex_index = p_idx; -} - -ShaderGLES3::ShaderGLES3() { - version = NULL; - last_custom_code = 1; - uniforms_dirty = true; - base_material_tex_index = 0; -} - -ShaderGLES3::~ShaderGLES3() { - - finish(); -} diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h deleted file mode 100644 index 2bfe72fbc0..0000000000 --- a/drivers/gles3/shader_gles3.h +++ /dev/null @@ -1,392 +0,0 @@ -/*************************************************************************/ -/* shader_gles3.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. */ -/*************************************************************************/ - -#ifndef SHADER_GLES3_H -#define SHADER_GLES3_H - -#include "core/hash_map.h" -#include "core/map.h" -#include "core/math/camera_matrix.h" -#include "core/variant.h" - -#include "platform_config.h" -#ifndef GLES3_INCLUDE_H -#include <GLES3/gl3.h> -#else -#include GLES3_INCLUDE_H -#endif - -#include <stdio.h> - -class ShaderGLES3 { -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; - }; - - struct UBOPair { - - const char *name; - int index; - }; - - struct Feedback { - - const char *name; - int conditional; - }; - - bool uniforms_dirty; - -private: - //@TODO Optimize to a fixed set of shader pools and use a LRU - int uniform_count; - int texunit_pair_count; - int conditional_count; - int ubo_count; - int feedback_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; - String uniforms; - uint32_t version; - Vector<StringName> texture_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; - 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 UBOPair *ubo_pairs; - const Feedback *feedbacks; - const char *vertex_code; - const char *fragment_code; - CharString fragment_code0; - CharString fragment_code1; - CharString fragment_code2; - CharString fragment_code3; - CharString fragment_code4; - - CharString vertex_code0; - CharString vertex_code1; - CharString vertex_code2; - CharString vertex_code3; - - Vector<CharString> custom_defines; - - int base_material_tex_index; - - Version *get_current_version(); - - static ShaderGLES3 *active; - - int max_image_units; - - _FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform, const Variant &p_value) { - - if (p_uniform < 0) - return; // do none - switch (p_value.get_type()) { - - case Variant::BOOL: - case Variant::INT: { - - int val = p_value; - glUniform1i(p_uniform, val); - } break; - case Variant::REAL: { - - real_t val = p_value; - glUniform1f(p_uniform, val); - } break; - case Variant::COLOR: { - - Color val = p_value; - glUniform4f(p_uniform, val.r, val.g, val.b, val.a); - } break; - case Variant::VECTOR2: { - - Vector2 val = p_value; - glUniform2f(p_uniform, val.x, val.y); - } break; - case Variant::VECTOR3: { - - Vector3 val = p_value; - glUniform3f(p_uniform, val.x, val.y, val.z); - } break; - case Variant::PLANE: { - - Plane val = p_value; - glUniform4f(p_uniform, val.normal.x, val.normal.y, val.normal.z, val.d); - } break; - case Variant::QUAT: { - - Quat val = p_value; - glUniform4f(p_uniform, val.x, val.y, val.z, val.w); - } break; - - case Variant::TRANSFORM2D: { - - Transform2D tr = p_value; - 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(p_uniform, 1, false, matrix); - - } break; - case Variant::BASIS: - case Variant::TRANSFORM: { - - Transform tr = p_value; - GLfloat matrix[16] = { /* build a 16x16 matrix */ - tr.basis.elements[0][0], - tr.basis.elements[1][0], - tr.basis.elements[2][0], - 0, - tr.basis.elements[0][1], - tr.basis.elements[1][1], - tr.basis.elements[2][1], - 0, - tr.basis.elements[0][2], - tr.basis.elements[1][2], - tr.basis.elements[2][2], - 0, - tr.origin.x, - tr.origin.y, - tr.origin.z, - 1 - }; - - glUniformMatrix4fv(p_uniform, 1, false, matrix); - } break; - default: { - ERR_FAIL(); - } // do nothing - } - } - - Map<uint32_t, Variant> uniform_defaults; - Map<uint32_t, CameraMatrix> uniform_cameras; - -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 UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start); - - ShaderGLES3(); - -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_ ShaderGLES3 *get_active() { return active; }; - bool bind(); - void unbind(); - void bind_uniforms(); - - 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 String &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); - - void set_uniform_default(int p_idx, const Variant &p_value) { - - if (p_value.get_type() == Variant::NIL) { - - uniform_defaults.erase(p_idx); - } else { - - uniform_defaults[p_idx] = p_value; - } - uniforms_dirty = true; - } - - uint32_t get_version() const { return new_conditional_version.version; } - _FORCE_INLINE_ bool is_version_valid() const { return version && version->ok; } - - void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) { - - uniform_cameras[p_idx] = p_mat; - uniforms_dirty = true; - }; - - _FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant &p_value) { - - ERR_FAIL_COND(!version); - ERR_FAIL_INDEX(p_idx, version->texture_uniform_locations.size()); - _set_uniform_variant(version->texture_uniform_locations[p_idx], p_value); - } - - _FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) { - - ERR_FAIL_COND_V(!version, -1); - ERR_FAIL_INDEX_V(p_idx, version->texture_uniform_locations.size(), -1); - return version->texture_uniform_locations[p_idx]; - } - - virtual void init() = 0; - void finish(); - - void set_base_material_tex_index(int p_idx); - - void add_custom_define(const String &p_define) { - custom_defines.push_back(p_define.utf8()); - } - - virtual ~ShaderGLES3(); -}; - -// called a lot, made inline - -int ShaderGLES3::_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 ShaderGLES3::_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 diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub deleted file mode 100644 index 27fd1514e7..0000000000 --- a/drivers/gles3/shaders/SCsub +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -if 'GLES3_GLSL' in env['BUILDERS']: - env.GLES3_GLSL('copy.glsl'); - env.GLES3_GLSL('resolve.glsl'); - env.GLES3_GLSL('canvas.glsl'); - env.GLES3_GLSL('canvas_shadow.glsl'); - env.GLES3_GLSL('scene.glsl'); - env.GLES3_GLSL('cubemap_filter.glsl'); - env.GLES3_GLSL('cube_to_dp.glsl'); - env.GLES3_GLSL('blend_shape.glsl'); - env.GLES3_GLSL('screen_space_reflection.glsl'); - env.GLES3_GLSL('effect_blur.glsl'); - env.GLES3_GLSL('subsurf_scattering.glsl'); - env.GLES3_GLSL('ssao.glsl'); - env.GLES3_GLSL('ssao_minify.glsl'); - env.GLES3_GLSL('ssao_blur.glsl'); - env.GLES3_GLSL('exposure.glsl'); - env.GLES3_GLSL('tonemap.glsl'); - env.GLES3_GLSL('particles.glsl'); - env.GLES3_GLSL('lens_distorted.glsl'); diff --git a/drivers/gles3/shaders/blend_shape.glsl b/drivers/gles3/shaders/blend_shape.glsl deleted file mode 100644 index a1e954e33d..0000000000 --- a/drivers/gles3/shaders/blend_shape.glsl +++ /dev/null @@ -1,194 +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/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl deleted file mode 100644 index 07ee9cd010..0000000000 --- a/drivers/gles3/shaders/canvas.glsl +++ /dev/null @@ -1,726 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec2 vertex; -/* clang-format on */ -layout(location = 3) in vec4 color_attrib; - -#ifdef USE_SKELETON -layout(location = 6) in uvec4 bone_indices; // attrib:6 -layout(location = 7) in vec4 bone_weights; // attrib:7 -#endif - -#ifdef USE_TEXTURE_RECT - -uniform vec4 dst_rect; -uniform vec4 src_rect; - -#else - -#ifdef USE_INSTANCING - -layout(location = 8) in highp vec4 instance_xform0; -layout(location = 9) in highp vec4 instance_xform1; -layout(location = 10) in highp vec4 instance_xform2; -layout(location = 11) in lowp vec4 instance_color; - -#ifdef USE_INSTANCE_CUSTOM -layout(location = 12) in highp vec4 instance_custom_data; -#endif - -#endif - -layout(location = 4) in highp vec2 uv_attrib; - -// skeleton -#endif - -uniform highp vec2 color_texpixel_size; - -layout(std140) uniform CanvasItemData { //ubo:0 - - highp mat4 projection_matrix; - highp float time; -}; - -uniform highp mat4 modelview_matrix; -uniform highp mat4 extra_matrix; - -out highp vec2 uv_interp; -out mediump vec4 color_interp; - -#ifdef USE_NINEPATCH - -out highp vec2 pixel_size_interp; -#endif - -#ifdef USE_SKELETON -uniform mediump sampler2D skeleton_texture; // texunit:-4 -uniform highp mat4 skeleton_transform; -uniform highp mat4 skeleton_transform_inverse; -#endif - -#ifdef USE_LIGHTING - -layout(std140) uniform LightData { //ubo:1 - - // light matrices - highp mat4 light_matrix; - highp mat4 light_local_matrix; - highp mat4 shadow_matrix; - highp vec4 light_color; - highp vec4 light_shadow_color; - highp vec2 light_pos; - highp float shadowpixel_size; - highp float shadow_gradient; - highp float light_height; - highp float light_outside_alpha; - highp float shadow_distance_mult; -}; - -out vec4 light_uv_interp; -out vec2 transformed_light_uv; - -out vec4 local_rot; - -#ifdef USE_SHADOWS -out highp vec2 pos; -#endif - -const bool at_light_pass = true; -#else -const bool at_light_pass = false; -#endif - -#if defined(USE_MATERIAL) - -/* clang-format off */ -layout(std140) uniform UniformData { //ubo:2 - -MATERIAL_UNIFORMS - -}; -/* clang-format on */ - -#endif - -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ - -void main() { - - vec4 color = color_attrib; - -#ifdef USE_INSTANCING - mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0))); - color *= instance_color; - -#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_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx; - } else { - uv_interp = src_rect.xy + abs(src_rect.zw) * vertex; - } - highp vec4 outvec = vec4(dst_rect.xy + abs(dst_rect.zw) * mix(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0))), 0.0, 1.0); - -#else - uv_interp = uv_attrib; - highp vec4 outvec = vec4(vertex, 0.0, 1.0); -#endif - -#ifdef USE_PARTICLES - //scale by texture size - outvec.xy /= color_texpixel_size; -#endif - -#define extra_matrix extra_matrix_instance - - float point_size = 1.0; - //for compatibility with the fragment shader we need to use uv here - vec2 uv = uv_interp; - { - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ - } - - gl_PointSize = point_size; - uv_interp = uv; - -#ifdef USE_NINEPATCH - - pixel_size_interp = abs(dst_rect.zw) * vertex; -#endif - -#if !defined(SKIP_TRANSFORM_USED) - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; -#endif - -#undef extra_matrix - - 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_interp += 1e-5; -#endif - -#ifdef USE_SKELETON - - if (bone_weights != vec4(0.0)) { //must be a valid bone - //skeleton transform - - ivec4 bone_indicesi = ivec4(bone_indices); - - ivec2 tex_ofs = ivec2(bone_indicesi.x % 256, (bone_indicesi.x / 256) * 2); - - highp mat2x4 m; - m = mat2x4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) * - bone_weights.x; - - tex_ofs = ivec2(bone_indicesi.y % 256, (bone_indicesi.y / 256) * 2); - - m += mat2x4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) * - bone_weights.y; - - tex_ofs = ivec2(bone_indicesi.z % 256, (bone_indicesi.z / 256) * 2); - - m += mat2x4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) * - bone_weights.z; - - tex_ofs = ivec2(bone_indicesi.w % 256, (bone_indicesi.w / 256) * 2); - - m += mat2x4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) * - bone_weights.w; - - mat4 bone_matrix = skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_transform_inverse; - - outvec = bone_matrix * outvec; - } - -#endif - - gl_Position = projection_matrix * outvec; - -#ifdef USE_LIGHTING - - light_uv_interp.xy = (light_matrix * outvec).xy; - light_uv_interp.zw = (light_local_matrix * outvec).xy; - - mat3 inverse_light_matrix = mat3(inverse(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]); - transformed_light_uv = (inverse_light_matrix * vec3(light_uv_interp.zw, 0.0)).xy; //for normal mapping - -#ifdef USE_SHADOWS - pos = outvec.xy; -#endif - - local_rot.xy = normalize((modelview_matrix * (extra_matrix_instance * vec4(1.0, 0.0, 0.0, 0.0))).xy); - local_rot.zw = normalize((modelview_matrix * (extra_matrix_instance * vec4(0.0, 1.0, 0.0, 0.0))).xy); -#ifdef USE_TEXTURE_RECT - local_rot.xy *= sign(src_rect.z); - local_rot.zw *= sign(src_rect.w); -#endif - -#endif -} - -/* clang-format off */ -[fragment] - -uniform mediump sampler2D color_texture; // texunit:0 -/* clang-format on */ -uniform highp vec2 color_texpixel_size; -uniform mediump sampler2D normal_texture; // texunit:1 - -in highp vec2 uv_interp; -in mediump vec4 color_interp; - -#if defined(SCREEN_TEXTURE_USED) - -uniform sampler2D screen_texture; // texunit:-3 - -#endif - -#if defined(SCREEN_UV_USED) - -uniform vec2 screen_pixel_size; -#endif - -layout(std140) uniform CanvasItemData { - - highp mat4 projection_matrix; - highp float time; -}; - -#ifdef USE_LIGHTING - -layout(std140) uniform LightData { - - highp mat4 light_matrix; - highp mat4 light_local_matrix; - highp mat4 shadow_matrix; - highp vec4 light_color; - highp vec4 light_shadow_color; - highp vec2 light_pos; - highp float shadowpixel_size; - highp float shadow_gradient; - highp float light_height; - highp float light_outside_alpha; - highp float shadow_distance_mult; -}; - -uniform lowp sampler2D light_texture; // texunit:-1 -in vec4 light_uv_interp; -in vec2 transformed_light_uv; - -in vec4 local_rot; - -#ifdef USE_SHADOWS - -uniform highp sampler2D shadow_texture; // texunit:-2 -in highp vec2 pos; - -#endif - -const bool at_light_pass = true; -#else -const bool at_light_pass = false; -#endif - -uniform mediump vec4 final_modulate; - -layout(location = 0) out mediump vec4 frag_color; - -#if defined(USE_MATERIAL) - -/* clang-format off */ -layout(std140) uniform UniformData { - -MATERIAL_UNIFORMS - -}; -/* clang-format on */ - -#endif - -/* 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 -} - -#ifdef USE_TEXTURE_RECT - -uniform vec4 dst_rect; -uniform vec4 src_rect; -uniform bool clip_rect_uv; - -#ifdef USE_NINEPATCH - -in highp vec2 pixel_size_interp; - -uniform int np_repeat_v; -uniform int np_repeat_h; -uniform bool np_draw_center; -// left top right bottom in pixel coordinates -uniform vec4 np_margins; - -float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, float s_ratio, int np_repeat, inout int draw_center) { - - float tex_size = 1.0 / tex_pixel_size; - - float screen_margin_begin = margin_begin / s_ratio; - float screen_margin_end = margin_end / s_ratio; - if (pixel < screen_margin_begin) { - return pixel * s_ratio * tex_pixel_size; - } else if (pixel >= draw_size - screen_margin_end) { - return (tex_size - (draw_size - pixel) * s_ratio) * tex_pixel_size; - } else { - if (!np_draw_center) { - draw_center--; - } - - // np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum. - if (np_repeat == 0) { // Stretch. - // Convert to ratio. - float ratio = (pixel - screen_margin_begin) / (draw_size - screen_margin_begin - screen_margin_end); - // Scale to source texture. - return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size; - } else if (np_repeat == 1) { // Tile. - // Convert to offset. - float ofs = mod((pixel - screen_margin_begin), tex_size - margin_begin - margin_end); - // Scale to source texture. - return (margin_begin + ofs) * tex_pixel_size; - } else if (np_repeat == 2) { // Tile Fit. - // Calculate scale. - float src_area = draw_size - screen_margin_begin - screen_margin_end; - float dst_area = tex_size - margin_begin - margin_end; - float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5)); - // Convert to ratio. - float ratio = (pixel - screen_margin_begin) / src_area; - ratio = mod(ratio * scale, 1.0); - // Scale to source texture. - return (margin_begin + ratio * dst_area) * tex_pixel_size; - } else { // Shouldn't happen, but silences compiler warning. - return 0.0; - } - } -} - -#endif -#endif - -uniform bool use_default_normal; - -void main() { - - vec4 color = color_interp; - vec2 uv = uv_interp; - -#ifdef USE_TEXTURE_RECT - -#ifdef USE_NINEPATCH - - int draw_center = 2; - float s_ratio = max((1.0 / color_texpixel_size.x) / abs(dst_rect.z), (1.0 / color_texpixel_size.y) / abs(dst_rect.w)); - s_ratio = max(1.0, s_ratio); - uv = vec2( - map_ninepatch_axis(pixel_size_interp.x, abs(dst_rect.z), color_texpixel_size.x, np_margins.x, np_margins.z, s_ratio, np_repeat_h, draw_center), - map_ninepatch_axis(pixel_size_interp.y, abs(dst_rect.w), color_texpixel_size.y, np_margins.y, np_margins.w, s_ratio, np_repeat_v, draw_center)); - - if (draw_center == 0) { - color.a = 0.0; - } - - uv = uv * src_rect.zw + src_rect.xy; //apply region if needed -#endif - - if (clip_rect_uv) { - - uv = clamp(uv, src_rect.xy, src_rect.xy + abs(src_rect.zw)); - } - -#endif - -#if !defined(COLOR_USED) - //default behavior, texture by color - -#ifdef USE_DISTANCE_FIELD - const float smoothing = 1.0 / 32.0; - float distance = textureLod(color_texture, uv, 0.0).a; - color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance) * color.a; -#else - color *= texture(color_texture, uv); - -#endif - -#endif - - vec3 normal; - -#if defined(NORMAL_USED) - - bool normal_used = true; -#else - bool normal_used = false; -#endif - - if (use_default_normal) { - normal.xy = textureLod(normal_texture, uv, 0.0).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); - } - -#if defined(SCREEN_UV_USED) - vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; -#endif - - { - 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 DEBUG_ENCODED_32 - highp float enc32 = dot(color, highp vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0)); - color = vec4(vec3(enc32), 1.0); -#endif - - color *= final_modulate; - -#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 = texture(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 = (mat3(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(texture((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) (texture((m_tex), (m_uv)).r) - -#endif - -#ifdef SHADOW_USE_GRADIENT - -#define SHADOW_TEST(m_ofs) \ - { \ - highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \ - shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); \ - } - -#else - -#define SHADOW_TEST(m_ofs) \ - { \ - highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \ - shadow_attenuation += step(sz, sd); \ - } - -#endif - -#ifdef SHADOW_FILTER_NEAREST - - SHADOW_TEST(su); - -#endif - -#ifdef SHADOW_FILTER_PCF3 - - SHADOW_TEST(su + shadowpixel_size); - SHADOW_TEST(su); - SHADOW_TEST(su - shadowpixel_size); - shadow_attenuation /= 3.0; - -#endif - -#ifdef SHADOW_FILTER_PCF5 - - SHADOW_TEST(su + shadowpixel_size * 2.0); - SHADOW_TEST(su + shadowpixel_size); - SHADOW_TEST(su); - SHADOW_TEST(su - shadowpixel_size); - SHADOW_TEST(su - shadowpixel_size * 2.0); - shadow_attenuation /= 5.0; - -#endif - -#ifdef SHADOW_FILTER_PCF7 - - SHADOW_TEST(su + shadowpixel_size * 3.0); - SHADOW_TEST(su + shadowpixel_size * 2.0); - SHADOW_TEST(su + shadowpixel_size); - SHADOW_TEST(su); - SHADOW_TEST(su - shadowpixel_size); - SHADOW_TEST(su - shadowpixel_size * 2.0); - SHADOW_TEST(su - shadowpixel_size * 3.0); - shadow_attenuation /= 7.0; - -#endif - -#ifdef SHADOW_FILTER_PCF9 - - SHADOW_TEST(su + shadowpixel_size * 4.0); - SHADOW_TEST(su + shadowpixel_size * 3.0); - SHADOW_TEST(su + shadowpixel_size * 2.0); - SHADOW_TEST(su + shadowpixel_size); - SHADOW_TEST(su); - SHADOW_TEST(su - shadowpixel_size); - SHADOW_TEST(su - shadowpixel_size * 2.0); - SHADOW_TEST(su - shadowpixel_size * 3.0); - SHADOW_TEST(su - shadowpixel_size * 4.0); - shadow_attenuation /= 9.0; - -#endif - -#ifdef SHADOW_FILTER_PCF13 - - SHADOW_TEST(su + shadowpixel_size * 6.0); - SHADOW_TEST(su + shadowpixel_size * 5.0); - SHADOW_TEST(su + shadowpixel_size * 4.0); - SHADOW_TEST(su + shadowpixel_size * 3.0); - SHADOW_TEST(su + shadowpixel_size * 2.0); - SHADOW_TEST(su + shadowpixel_size); - SHADOW_TEST(su); - SHADOW_TEST(su - shadowpixel_size); - SHADOW_TEST(su - shadowpixel_size * 2.0); - SHADOW_TEST(su - shadowpixel_size * 3.0); - SHADOW_TEST(su - shadowpixel_size * 4.0); - SHADOW_TEST(su - shadowpixel_size * 5.0); - SHADOW_TEST(su - shadowpixel_size * 6.0); - shadow_attenuation /= 13.0; - -#endif - - //color *= shadow_attenuation; - color = mix(real_light_shadow_color, color, shadow_attenuation); -//use shadows -#endif - } - -//use lighting -#endif - //color.rgb *= color.a; - frag_color = color; -} diff --git a/drivers/gles3/shaders/canvas_shadow.glsl b/drivers/gles3/shaders/canvas_shadow.glsl deleted file mode 100644 index 4f706c5505..0000000000 --- a/drivers/gles3/shaders/canvas_shadow.glsl +++ /dev/null @@ -1,45 +0,0 @@ -/* clang-format off */ -[vertex] - -uniform highp mat4 projection_matrix; -/* clang-format on */ -uniform highp mat4 light_matrix; -uniform highp mat4 world_matrix; -uniform highp float distance_norm; - -layout(location = 0) in highp vec3 vertex; - -out highp vec4 position_interp; - -void main() { - - gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex, 1.0))); - position_interp = gl_Position; -} - -/* clang-format off */ -[fragment] - -in highp vec4 position_interp; -/* clang-format on */ - -#ifdef USE_RGBA_SHADOWS -layout(location = 0) out lowp vec4 distance_buf; -#else -layout(location = 0) out highp float distance_buf; -#endif - -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); - distance_buf = comp; -#else - - distance_buf = depth; -#endif -} diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl deleted file mode 100644 index a3cdb3a543..0000000000 --- a/drivers/gles3/shaders/copy.glsl +++ /dev/null @@ -1,270 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -layout(location = 4) in vec3 cube_in; -#else -layout(location = 4) in vec2 uv_in; -#endif -layout(location = 5) in vec2 uv2_in; - -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -out vec3 cube_interp; -#else -out vec2 uv_interp; -#endif - -out 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 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; -#ifdef V_FLIP - uv_interp.y = 1.0 - uv_interp.y; -#endif - -#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 - -#if !defined(USE_GLES_OVER_GL) -precision mediump float; -#endif - -#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) -in vec3 cube_interp; -#else -in vec2 uv_interp; -#endif - -#ifdef USE_ASYM_PANO -uniform highp mat4 pano_transform; -uniform highp vec4 asym_proj; -#endif - -// These definitions are here because the shader-wrapper builder does -// not understand `#elif defined()` -#ifdef USE_TEXTURE3D -#endif -#ifdef USE_TEXTURE2DARRAY -#endif -#ifdef YCBCR_TO_SRGB -#endif - -#ifdef USE_CUBEMAP -uniform samplerCube source_cube; //texunit:0 -#elif defined(USE_TEXTURE3D) -uniform sampler3D source_3d; //texunit:0 -#elif defined(USE_TEXTURE2DARRAY) -uniform sampler2DArray source_2d_array; //texunit:0 -#else -uniform sampler2D source; //texunit:0 -#endif - -#ifdef SEP_CBCR_TEXTURE -uniform sampler2D CbCr; //texunit:1 -#endif - -/* clang-format on */ - -#ifdef USE_LOD -uniform float mip_level; -#endif - -#if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY) -uniform float layer; -#endif - -#ifdef USE_MULTIPLIER -uniform float multiplier; -#endif - -#if defined(USE_PANORAMA) || defined(USE_ASYM_PANO) -uniform highp mat4 sky_transform; - -vec4 texturePanorama(vec3 normal, sampler2D pano) { - - 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 textureLod(pano, st, 0.0); -} - -#endif - -uniform vec2 pixel_size; - -in vec2 uv2_interp; - -#ifdef USE_BCS - -uniform vec3 bcs; - -#endif - -#ifdef USE_COLOR_CORRECTION - -uniform sampler2D color_correction; //texunit:1 - -#endif - -layout(location = 0) out vec4 frag_color; - -void main() { - - //vec4 color = color_interp; - -#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(cube_normal, source); - -#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(normalize(cube_normal.xyz), source); - -#elif defined(USE_CUBEMAP) - vec4 color = texture(source_cube, normalize(cube_interp)); - -#elif defined(USE_TEXTURE3D) - vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0); -#elif defined(USE_TEXTURE2DARRAY) - vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0); -#elif defined(SEP_CBCR_TEXTURE) - vec4 color; - color.r = textureLod(source, uv_interp, 0.0).r; - color.gb = textureLod(CbCr, uv_interp, 0.0).rg - vec2(0.5, 0.5); - color.a = 1.0; -#else -#ifdef USE_LOD - vec4 color = textureLod(source, uv_interp, mip_level); -#else - vec4 color = textureLod(source, uv_interp, 0.0); -#endif -#endif - -#ifdef LINEAR_TO_SRGB - // regular Linear -> SRGB conversion - vec3 a = vec3(0.055); - color.rgb = mix((vec3(1.0) + a) * pow(color.rgb, vec3(1.0 / 2.4)) - a, 12.92 * color.rgb, lessThan(color.rgb, vec3(0.0031308))); - -#elif defined(YCBCR_TO_SRGB) - - // YCbCr -> SRGB conversion - // Using BT.709 which is the standard for HDTV - color.rgb = mat3( - vec3(1.00000, 1.00000, 1.00000), - vec3(0.00000, -0.18732, 1.85560), - vec3(1.57481, -0.46813, 0.00000)) * - color.rgb; - -#endif - -#ifdef SRGB_TO_LINEAR - - color.rgb = mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045))); -#endif - -#ifdef DEBUG_GRADIENT - color.rg = uv_interp; - color.b = 0.0; -#endif - -#ifdef DISABLE_ALPHA - color.a = 1.0; -#endif - -#ifdef GAUSSIAN_HORIZONTAL - color *= 0.38774; - color += texture(source, uv_interp + vec2(1.0, 0.0) * pixel_size) * 0.24477; - color += texture(source, uv_interp + vec2(2.0, 0.0) * pixel_size) * 0.06136; - color += texture(source, uv_interp + vec2(-1.0, 0.0) * pixel_size) * 0.24477; - color += texture(source, uv_interp + vec2(-2.0, 0.0) * pixel_size) * 0.06136; -#endif - -#ifdef GAUSSIAN_VERTICAL - color *= 0.38774; - color += texture(source, uv_interp + vec2(0.0, 1.0) * pixel_size) * 0.24477; - color += texture(source, uv_interp + vec2(0.0, 2.0) * pixel_size) * 0.06136; - color += texture(source, uv_interp + vec2(0.0, -1.0) * pixel_size) * 0.24477; - color += texture(source, uv_interp + vec2(0.0, -2.0) * pixel_size) * 0.06136; -#endif - -#ifdef USE_BCS - - color.rgb = mix(vec3(0.0), color.rgb, bcs.x); - color.rgb = mix(vec3(0.5), color.rgb, bcs.y); - color.rgb = mix(vec3(dot(vec3(1.0), color.rgb) * 0.33333), color.rgb, bcs.z); - -#endif - -#ifdef USE_COLOR_CORRECTION - - color.r = texture(color_correction, vec2(color.r, 0.0)).r; - color.g = texture(color_correction, vec2(color.g, 0.0)).g; - color.b = texture(color_correction, vec2(color.b, 0.0)).b; -#endif - -#ifdef USE_MULTIPLIER - color.rgb *= multiplier; -#endif - frag_color = color; -} diff --git a/drivers/gles3/shaders/cube_to_dp.glsl b/drivers/gles3/shaders/cube_to_dp.glsl deleted file mode 100644 index 2b74f054f9..0000000000 --- a/drivers/gles3/shaders/cube_to_dp.glsl +++ /dev/null @@ -1,79 +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] - -uniform highp samplerCube source_cube; //texunit:0 -/* clang-format on */ -in 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 = texture(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/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl deleted file mode 100644 index e1872eb433..0000000000 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ /dev/null @@ -1,370 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec2 vertex; -/* clang-format on */ - -layout(location = 4) in highp vec2 uv; - -out highp vec2 uv_interp; - -void main() { - - uv_interp = uv; - gl_Position = vec4(vertex, 0, 1); -} - -/* clang-format off */ -[fragment] - -precision highp float; -/* clang-format on */ -precision highp int; - -#ifdef USE_SOURCE_PANORAMA -uniform sampler2D source_panorama; //texunit:0 -uniform float source_resolution; -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY -uniform sampler2DArray source_dual_paraboloid_array; //texunit:0 -uniform int source_array_index; -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID -uniform sampler2D source_dual_paraboloid; //texunit:0 -#endif - -#if defined(USE_SOURCE_DUAL_PARABOLOID) || defined(COMPUTE_IRRADIANCE) -uniform float source_mip_level; -#endif - -#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID) -uniform samplerCube source_cube; //texunit:0 -#endif - -uniform int face_id; -uniform float roughness; - -in highp vec2 uv_interp; - -layout(location = 0) out vec4 frag_color; - -#define M_PI 3.14159265359 - -vec3 texelCoordToVec(vec2 uv, int faceID) { - mat3 faceUvVectors[6]; - /* - // -x - faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z - faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face - - // +x - faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z - faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face - - // -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 - - // +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 - - // -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 - - // +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 - */ - - // -x - faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z - faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face - - // +x - faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z - faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face - - // -y - faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z - faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face - - // +y - faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z - faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face - - // -z - faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x - faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face - - // +z - faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face - - // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. - vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; - 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 DistributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - - float nom = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = M_PI * denom * denom; - - return nom / denom; -} - -// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float GGX(float NdotV, float a) { - float k = a / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float G_Smith(float a, float nDotV, float nDotL) { - return GGX(nDotL, a * a) * GGX(nDotV, a * a); -} - -float radicalInverse_VdC(uint bits) { - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // / 0x100000000 -} - -vec2 Hammersley(uint i, uint N) { - return vec2(float(i) / float(N), radicalInverse_VdC(i)); -} - -#ifdef LOW_QUALITY - -#define SAMPLE_COUNT 64u -#define SAMPLE_DELTA 0.1 - -#else - -#define SAMPLE_COUNT 512u -#define SAMPLE_DELTA 0.03 - -#endif - -uniform bool z_flip; - -#ifdef USE_SOURCE_PANORAMA - -vec4 texturePanorama(vec3 normal, sampler2D pano, float mipLevel) { - - 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 textureLod(pano, st, mipLevel); -} - -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY - -vec4 textureDualParaboloidArray(vec3 normal) { - - vec3 norm = normalize(normal); - norm.xy /= 1.0 + abs(norm.z); - norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); - if (norm.z < 0.0) { - norm.y = 0.5 - norm.y + 0.5; - } - return textureLod(source_dual_paraboloid_array, vec3(norm.xy, float(source_array_index)), 0.0); -} - -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID -vec4 textureDualParaboloid(vec3 normal) { - - vec3 norm = normalize(normal); - norm.xy /= 1.0 + abs(norm.z); - norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); - if (norm.z < 0.0) { - norm.y = 0.5 - norm.y + 0.5; - } - return textureLod(source_dual_paraboloid, norm.xy, source_mip_level); -} - -#endif - -void main() { - -#ifdef USE_DUAL_PARABOLOID - - vec3 N = vec3(uv_interp * 2.0 - 1.0, 0.0); - N.z = 0.5 - 0.5 * ((N.x * N.x) + (N.y * N.y)); - N = normalize(N); - - if (z_flip) { - N.y = -N.y; //y is flipped to improve blending between both sides - N.z = -N.z; - } - -#else - vec2 uv = (uv_interp * 2.0) - 1.0; - vec3 N = texelCoordToVec(uv, face_id); -#endif - //vec4 color = color_interp; - -#ifdef USE_DIRECT_WRITE - -#ifdef USE_SOURCE_PANORAMA - - frag_color = vec4(texturePanorama(N, source_panorama, 0.0).rgb, 1.0); -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY - - frag_color = vec4(textureDualParaboloidArray(N).rgb, 1.0); -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID - - frag_color = vec4(textureDualParaboloid(N).rgb, 1.0); -#endif - -#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID) - - N.y = -N.y; - frag_color = vec4(texture(N, source_cube).rgb, 1.0); -#endif - -#else // USE_DIRECT_WRITE - -#ifdef COMPUTE_IRRADIANCE - - vec3 irradiance = vec3(0.0); - - // tangent space calculation from origin point - vec3 UpVector = vec3(0.0, 1.0, 0.0); - vec3 TangentX = cross(UpVector, N); - vec3 TangentY = cross(N, TangentX); - - float num_samples = 0.0f; - - for (float phi = 0.0; phi < 2.0 * M_PI; phi += SAMPLE_DELTA) { - for (float theta = 0.0; theta < 0.5 * M_PI; theta += SAMPLE_DELTA) { - // Calculate sample positions - vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); - // Find world vector of sample position - vec3 H = tangentSample.x * TangentX + tangentSample.y * TangentY + tangentSample.z * N; - - vec2 st = vec2(atan(H.x, H.z), acos(H.y)); - if (st.x < 0.0) { - st.x += M_PI * 2.0; - } - st /= vec2(M_PI * 2.0, M_PI); - - irradiance += textureLod(source_panorama, st, source_mip_level).rgb * cos(theta) * sin(theta); - num_samples++; - } - } - irradiance = M_PI * irradiance * (1.0 / float(num_samples)); - - frag_color = vec4(irradiance, 1.0); - -#else - - vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); - - for (uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) { - vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT); - - vec3 H = normalize(ImportanceSampleGGX(xi, roughness, N)); - vec3 V = N; - vec3 L = normalize(2.0 * dot(V, H) * H - V); - - float ndotl = max(dot(N, L), 0.0); - - if (ndotl > 0.0) { - -#ifdef USE_SOURCE_PANORAMA - float D = DistributionGGX(N, H, roughness); - float ndoth = max(dot(N, H), 0.0); - float hdotv = max(dot(H, V), 0.0); - float pdf = D * ndoth / (4.0 * hdotv) + 0.0001; - - float saTexel = 4.0 * M_PI / (6.0 * source_resolution * source_resolution); - float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); - - float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); - - sum.rgb += texturePanorama(L, source_panorama, mipLevel).rgb * ndotl; -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY - sum.rgb += textureDualParaboloidArray(L).rgb * ndotl; -#endif - -#ifdef USE_SOURCE_DUAL_PARABOLOID - sum.rgb += textureDualParaboloid(L).rgb * ndotl; -#endif - -#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID) - L.y = -L.y; - sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl; -#endif - sum.a += ndotl; - } - } - sum /= sum.a; - - frag_color = vec4(sum.rgb, 1.0); - -#endif // COMPUTE_IRRADIANCE -#endif // USE_DIRECT_WRITE -} diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl deleted file mode 100644 index ff5a9f326f..0000000000 --- a/drivers/gles3/shaders/effect_blur.glsl +++ /dev/null @@ -1,293 +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; - -#ifdef USE_BLUR_SECTION - -uniform vec4 blur_section; - -#endif - -void main() { - - uv_interp = uv_in; - gl_Position = vertex_attrib; -#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] - -#if !defined(GLES_OVER_GL) -precision mediump float; -#endif -/* clang-format on */ - -in vec2 uv_interp; -uniform sampler2D source_color; //texunit:0 - -#ifdef SSAO_MERGE -uniform sampler2D source_ssao; //texunit:1 -#endif - -uniform float lod; -uniform vec2 pixel_size; - -layout(location = 0) out vec4 frag_color; - -#ifdef SSAO_MERGE - -uniform vec4 ssao_color; - -#endif - -#if defined(GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL) - -uniform float glow_strength; - -#endif - -#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; -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 - -uniform sampler2D dof_source_depth; //texunit:1 -uniform float dof_begin; -uniform float dof_end; -uniform vec2 dof_dir; -uniform float dof_radius; - -#ifdef DOF_NEAR_BLUR_MERGE - -uniform sampler2D source_dof_original; //texunit:2 -#endif - -#endif - -#ifdef GLOW_FIRST_PASS - -uniform float exposure; -uniform float white; -uniform highp float luminance_cap; - -#ifdef GLOW_USE_AUTO_EXPOSURE - -uniform highp sampler2D source_auto_exposure; //texunit:1 -uniform highp float auto_exposure_grey; - -#endif - -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 GAUSSIAN_HORIZONTAL - vec2 pix_size = pixel_size; - pix_size *= 0.5; //reading from larger buffer, so use more samples - // sigma 2 - vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.214607; - color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.189879; - color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.131514; - color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.071303; - color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.189879; - color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.131514; - color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.071303; - frag_color = color; -#endif - -#ifdef GAUSSIAN_VERTICAL - vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.38774; - color += textureLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.24477; - color += textureLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.06136; - color += textureLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.24477; - color += textureLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.06136; - frag_color = color; -#endif - - //glow uses larger sigma for a more rounded blur effect - -#ifdef GLOW_GAUSSIAN_HORIZONTAL - vec2 pix_size = pixel_size; - pix_size *= 0.5; //reading from larger buffer, so use more samples - vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.174938; - color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.165569; - color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.140367; - color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.106595; - color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.165569; - color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.140367; - color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.106595; - color *= glow_strength; - frag_color = color; -#endif - -#ifdef GLOW_GAUSSIAN_VERTICAL - vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.288713; - color += textureLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.233062; - color += textureLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.122581; - color += textureLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062; - color += textureLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581; - color *= glow_strength; - frag_color = color; -#endif - -#ifdef DOF_FAR_BLUR - - vec4 color_accum = vec4(0.0); - - float depth = textureLod(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 = texture(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 = mix(smoothstep(dof_begin, dof_end, tap_depth), 1.0, int_ofs == 0); - tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect - - vec4 tap_color = textureLod(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; - } - - frag_color = 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 - float(abs(int_ofs)) / float(dof_kernel_from)); - - float tap_k = dof_kernel[i]; - - vec4 tap_color = textureLod(source_color, tap_uv, 0.0); - - float tap_depth = texture(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)); - -#ifdef DOF_NEAR_BLUR_MERGE - - vec4 original = textureLod(source_dof_original, uv_interp, 0.0); - color_accum = mix(original, color_accum, color_accum.a); - -#endif - -#ifndef DOF_NEAR_FIRST_TAP - //color_accum=vec4(vec3(color_accum.a),1.0); -#endif - frag_color = color_accum; - -#endif - -#ifdef GLOW_FIRST_PASS - -#ifdef GLOW_USE_AUTO_EXPOSURE - - frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / auto_exposure_grey; -#endif - frag_color *= exposure; - - float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); - float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom); - - frag_color = min(frag_color * feedback, vec4(luminance_cap)); - -#endif - -#ifdef SIMPLE_COPY - vec4 color = textureLod(source_color, uv_interp, 0.0); - frag_color = color; -#endif - -#ifdef SSAO_MERGE - - vec4 color = textureLod(source_color, uv_interp, 0.0); - float ssao = textureLod(source_ssao, uv_interp, 0.0).r; - - frag_color = vec4(mix(color.rgb, color.rgb * mix(ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0); - -#endif -} diff --git a/drivers/gles3/shaders/exposure.glsl b/drivers/gles3/shaders/exposure.glsl deleted file mode 100644 index 759adcda06..0000000000 --- a/drivers/gles3/shaders/exposure.glsl +++ /dev/null @@ -1,88 +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/gles3/shaders/lens_distorted.glsl b/drivers/gles3/shaders/lens_distorted.glsl deleted file mode 100644 index 7b9d0b347f..0000000000 --- a/drivers/gles3/shaders/lens_distorted.glsl +++ /dev/null @@ -1,64 +0,0 @@ -/* clang-format off */ -[vertex] - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ - -uniform vec2 offset; -uniform vec2 scale; - -out vec2 uv_interp; - -void main() { - - uv_interp = vertex_attrib.xy * 2.0 - 1.0; - - vec2 v = vertex_attrib.xy * scale + offset; - gl_Position = vec4(v, 0.0, 1.0); -} - -/* clang-format off */ -[fragment] - -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; - -in vec2 uv_interp; - -layout(location = 0) out vec4 frag_color; - -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) { - frag_color = vec4(0.0, 0.0, 0.0, 1.0); - } else { - coords = (coords + vec2(1.0)) / vec2(2.0); - frag_color = textureLod(source, coords, 0.0); - } -} diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl deleted file mode 100644 index 8523c08597..0000000000 --- a/drivers/gles3/shaders/particles.glsl +++ /dev/null @@ -1,267 +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 (delta > 0.0) { - 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/gles3/shaders/resolve.glsl b/drivers/gles3/shaders/resolve.glsl deleted file mode 100644 index d64d8308c1..0000000000 --- a/drivers/gles3/shaders/resolve.glsl +++ /dev/null @@ -1,44 +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 -/* clang-format on */ - -in vec2 uv_interp; -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/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl deleted file mode 100644 index a45ac2eb8a..0000000000 --- a/drivers/gles3/shaders/scene.glsl +++ /dev/null @@ -1,2187 +0,0 @@ -/* clang-format off */ -[vertex] - -#define M_PI 3.14159265359 - -#define SHADER_IS_SRGB false - -/* -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, -*/ - -// hack to use uv if no uv present so it works with lightmap - -/* INPUT ATTRIBS */ - -layout(location = 0) in highp vec4 vertex_attrib; -/* clang-format on */ -layout(location = 1) in vec3 normal_attrib; -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) -layout(location = 2) in vec4 tangent_attrib; -#endif - -#if defined(ENABLE_COLOR_INTERP) -layout(location = 3) in vec4 color_attrib; -#endif - -#if defined(ENABLE_UV_INTERP) -layout(location = 4) in vec2 uv_attrib; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -layout(location = 5) in vec2 uv2_attrib; -#endif - -#ifdef USE_SKELETON -layout(location = 6) in uvec4 bone_indices; // attrib:6 -layout(location = 7) in highp vec4 bone_weights; // attrib:7 -#endif - -#ifdef USE_INSTANCING - -layout(location = 8) in highp vec4 instance_xform0; -layout(location = 9) in highp vec4 instance_xform1; -layout(location = 10) in highp vec4 instance_xform2; -layout(location = 11) in lowp vec4 instance_color; - -#if defined(ENABLE_INSTANCE_CUSTOM) -layout(location = 12) in highp vec4 instance_custom_data; -#endif - -#endif - -layout(std140) uniform SceneData { // ubo:0 - - highp mat4 projection_matrix; - highp mat4 inv_projection_matrix; - highp mat4 camera_inverse_matrix; - highp mat4 camera_matrix; - - mediump vec4 ambient_light_color; - mediump vec4 bg_color; - - mediump vec4 fog_color_enabled; - mediump vec4 fog_sun_color_amount; - - mediump float ambient_energy; - mediump float bg_energy; - - mediump float z_offset; - mediump float z_slope_scale; - highp float shadow_dual_paraboloid_render_zfar; - highp float shadow_dual_paraboloid_render_side; - - highp vec2 viewport_size; - highp vec2 screen_pixel_size; - highp vec2 shadow_atlas_pixel_size; - highp vec2 directional_shadow_pixel_size; - - highp float time; - highp float z_far; - mediump float reflection_multiplier; - mediump float subsurface_scatter_width; - mediump float ambient_occlusion_affect_light; - mediump float ambient_occlusion_affect_ao_channel; - mediump float opaque_prepass_threshold; - - bool fog_depth_enabled; - highp float fog_depth_begin; - highp float fog_depth_end; - mediump float fog_density; - highp float fog_depth_curve; - bool fog_transmit_enabled; - highp float fog_transmit_curve; - bool fog_height_enabled; - highp float fog_height_min; - highp float fog_height_max; - highp float fog_height_curve; -}; - -uniform highp mat4 world_transform; - -#ifdef USE_LIGHT_DIRECTIONAL - -layout(std140) uniform DirectionalLightData { //ubo:3 - - highp vec4 light_pos_inv_radius; - mediump vec4 light_direction_attenuation; - mediump vec4 light_color_energy; - mediump vec4 light_params; // cone attenuation, angle, specular, shadow enabled, - mediump vec4 light_clamp; - mediump vec4 shadow_color_contact; - highp mat4 shadow_matrix1; - highp mat4 shadow_matrix2; - highp mat4 shadow_matrix3; - highp mat4 shadow_matrix4; - mediump vec4 shadow_split_offsets; -}; - -#endif - -#ifdef USE_VERTEX_LIGHTING -//omni and spot - -struct LightData { - - highp vec4 light_pos_inv_radius; - mediump vec4 light_direction_attenuation; - mediump vec4 light_color_energy; - mediump vec4 light_params; // cone attenuation, angle, specular, shadow enabled, - mediump vec4 light_clamp; - mediump vec4 shadow_color_contact; - highp mat4 shadow_matrix; -}; - -layout(std140) uniform OmniLightData { //ubo:4 - - LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; -}; - -layout(std140) uniform SpotLightData { //ubo:5 - - LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; -}; - -#ifdef USE_FORWARD_LIGHTING - -uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; -uniform int omni_light_count; - -uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; -uniform int spot_light_count; - -#endif - -out vec4 diffuse_light_interp; -out vec4 specular_light_interp; - -void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - - 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 - - diffuse += light_color * diffuse_brdf_NL; - - 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 - - specular += specular_brdf_NL * light_color * (1.0 / M_PI); - } -} - -void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) { - - vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length * omni_lights[idx].light_pos_inv_radius.w; - vec3 light_attenuation = vec3(pow(max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w)); - - light_compute(normal, normalize(light_rel_vec), eye_vec, omni_lights[idx].light_color_energy.rgb * light_attenuation, roughness, diffuse, specular); -} - -void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) { - - vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length * spot_lights[idx].light_pos_inv_radius.w; - vec3 light_attenuation = vec3(pow(max(1.0 - normalized_distance, 0.001), spot_lights[idx].light_direction_attenuation.w)); - vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz; - float spot_cutoff = spot_lights[idx].light_params.y; - float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_cutoff); - float spot_rim = (1.0 - scos) / (1.0 - spot_cutoff); - light_attenuation *= 1.0 - pow(max(spot_rim, 0.001), spot_lights[idx].light_params.x); - - light_compute(normal, normalize(light_rel_vec), eye_vec, spot_lights[idx].light_color_energy.rgb * light_attenuation, roughness, diffuse, specular); -} - -#endif - -/* Varyings */ - -out highp vec3 vertex_interp; -out vec3 normal_interp; - -#if defined(ENABLE_COLOR_INTERP) -out vec4 color_interp; -#endif - -#if defined(ENABLE_UV_INTERP) -out vec2 uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -out vec2 uv2_interp; -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) -out vec3 tangent_interp; -out vec3 binormal_interp; -#endif - -#if defined(USE_MATERIAL) - -/* clang-format off */ -layout(std140) uniform UniformData { // ubo:1 - -MATERIAL_UNIFORMS - -}; -/* clang-format on */ - -#endif - -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -out highp float dp_clip; - -#endif - -#define SKELETON_TEXTURE_WIDTH 256 - -#ifdef USE_SKELETON -uniform highp sampler2D skeleton_texture; // texunit:-1 -#endif - -out highp vec4 position_interp; - -// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now. -// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316 -//invariant gl_Position; - -void main() { - - highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); - - highp mat4 world_matrix = world_transform; - -#ifdef USE_INSTANCING - - { - highp mat4 m = mat4(instance_xform0, instance_xform1, instance_xform2, 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) || defined(LIGHT_USE_ANISOTROPY) - vec3 tangent = tangent_attrib.xyz; - float binormalf = tangent_attrib.a; -#endif - -#if defined(ENABLE_COLOR_INTERP) - color_interp = color_attrib; -#if defined(USE_INSTANCING) - color_interp *= instance_color; -#endif - -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - - vec3 binormal = normalize(cross(normal, tangent) * binormalf); -#endif - -#if defined(ENABLE_UV_INTERP) - uv_interp = uv_attrib; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) - uv2_interp = uv2_attrib; -#endif - -#ifdef OVERRIDE_POSITION - highp vec4 position; -#endif - -#if defined(USE_INSTANCING) && defined(ENABLE_INSTANCE_CUSTOM) - vec4 instance_custom = instance_custom_data; -#else - vec4 instance_custom = vec4(0.0); -#endif - - highp mat4 local_projection = projection_matrix; - -//using world coordinates -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - - vertex = world_matrix * vertex; - -#if defined(ENSURE_CORRECT_NORMALS) - mat3 normal_matrix = mat3(transpose(inverse(world_matrix))); - normal = normal_matrix * normal; -#else - normal = normalize((world_matrix * vec4(normal, 0.0)).xyz); -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - - tangent = normalize((world_matrix * vec4(tangent, 0.0)).xyz); - binormal = normalize((world_matrix * vec4(binormal, 0.0)).xyz); -#endif -#endif - - float roughness = 1.0; - -//defines that make writing custom shaders easier -#define projection_matrix local_projection -#define world_transform world_matrix - -#ifdef USE_SKELETON - { - //skeleton transform - ivec4 bone_indicesi = ivec4(bone_indices); // cast to signed int - - ivec2 tex_ofs = ivec2(bone_indicesi.x % 256, (bone_indicesi.x / 256) * 3); - highp mat4 m; - m = mat4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), - vec4(0.0, 0.0, 0.0, 1.0)) * - bone_weights.x; - - tex_ofs = ivec2(bone_indicesi.y % 256, (bone_indicesi.y / 256) * 3); - - m += mat4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), - vec4(0.0, 0.0, 0.0, 1.0)) * - bone_weights.y; - - tex_ofs = ivec2(bone_indicesi.z % 256, (bone_indicesi.z / 256) * 3); - - m += mat4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), - vec4(0.0, 0.0, 0.0, 1.0)) * - bone_weights.z; - - tex_ofs = ivec2(bone_indicesi.w % 256, (bone_indicesi.w / 256) * 3); - - m += mat4( - texelFetch(skeleton_texture, tex_ofs, 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), - vec4(0.0, 0.0, 0.0, 1.0)) * - bone_weights.w; - - world_matrix = world_matrix * transpose(m); - } -#endif - - float point_size = 1.0; - - highp mat4 modelview = camera_inverse_matrix * world_matrix; - { - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ - } - - gl_PointSize = point_size; - -// using local coordinates (default) -#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) - - vertex = modelview * vertex; - -#if defined(ENSURE_CORRECT_NORMALS) - mat3 normal_matrix = mat3(transpose(inverse(modelview))); - normal = normal_matrix * normal; -#else - normal = normalize((modelview * vec4(normal, 0.0)).xyz); -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - - tangent = normalize((modelview * vec4(tangent, 0.0)).xyz); - binormal = normalize((modelview * vec4(binormal, 0.0)).xyz); -#endif -#endif - -//using world coordinates -#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) || defined(LIGHT_USE_ANISOTROPY) - - 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) || defined(LIGHT_USE_ANISOTROPY) - 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) * z_offset; - 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 = z_offset; - z_ofs += (1.0 - abs(normal_interp.z)) * z_slope_scale; - vertex_interp.z -= z_ofs; - -#endif //RENDER_DEPTH_DUAL_PARABOLOID - -#endif //RENDER_DEPTH - -#ifdef OVERRIDE_POSITION - gl_Position = position; -#else - gl_Position = projection_matrix * vec4(vertex_interp, 1.0); -#endif - - position_interp = gl_Position; - -#ifdef USE_VERTEX_LIGHTING - - diffuse_light_interp = vec4(0.0); - specular_light_interp = vec4(0.0); - -#ifdef USE_FORWARD_LIGHTING - - for (int i = 0; i < omni_light_count; i++) { - light_process_omni(omni_light_indices[i], vertex_interp, -normalize(vertex_interp), normal_interp, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb); - } - - for (int i = 0; i < spot_light_count; i++) { - light_process_spot(spot_light_indices[i], vertex_interp, -normalize(vertex_interp), normal_interp, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb); - } -#endif - -#ifdef USE_LIGHT_DIRECTIONAL - - vec3 directional_diffuse = vec3(0.0); - vec3 directional_specular = vec3(0.0); - light_compute(normal_interp, -light_direction_attenuation.xyz, -normalize(vertex_interp), light_color_energy.rgb, roughness, directional_diffuse, directional_specular); - - float diff_avg = dot(diffuse_light_interp.rgb, vec3(0.33333)); - float diff_dir_avg = dot(directional_diffuse, vec3(0.33333)); - if (diff_avg > 0.0) { - diffuse_light_interp.a = diff_dir_avg / (diff_avg + diff_dir_avg); - } else { - diffuse_light_interp.a = 1.0; - } - - diffuse_light_interp.rgb += directional_diffuse; - - float spec_avg = dot(specular_light_interp.rgb, vec3(0.33333)); - float spec_dir_avg = dot(directional_specular, vec3(0.33333)); - if (spec_avg > 0.0) { - specular_light_interp.a = spec_dir_avg / (spec_avg + spec_dir_avg); - } else { - specular_light_interp.a = 1.0; - } - - specular_light_interp.rgb += directional_specular; - -#endif //USE_LIGHT_DIRECTIONAL - -#endif // USE_VERTEX_LIGHTING -} - -/* clang-format off */ -[fragment] - - -/* texture unit usage, N is max_texture_unity-N - -1-skeleton -2-radiance -3-reflection_atlas -4-directional_shadow -5-shadow_atlas -6-decal_atlas -7-screen -8-depth -9-probe1 -10-probe2 - -*/ - -uniform highp mat4 world_transform; -/* clang-format on */ - -#define M_PI 3.14159265359 -#define SHADER_IS_SRGB false - -/* Varyings */ - -#if defined(ENABLE_COLOR_INTERP) -in vec4 color_interp; -#endif - -#if defined(ENABLE_UV_INTERP) -in vec2 uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -in vec2 uv2_interp; -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) -in vec3 tangent_interp; -in vec3 binormal_interp; -#endif - -in highp vec3 vertex_interp; -in vec3 normal_interp; - -/* PBR CHANNELS */ - -#ifdef USE_RADIANCE_MAP - -layout(std140) uniform Radiance { // ubo:2 - - mat4 radiance_inverse_xform; - float radiance_ambient_contribution; -}; - -#define RADIANCE_MAX_LOD 5.0 - -uniform sampler2D irradiance_map; // texunit:-6 - -#ifdef USE_RADIANCE_MAP_ARRAY - -uniform sampler2DArray radiance_map; // texunit:-2 - -vec3 textureDualParaboloid(sampler2DArray p_tex, vec3 p_vec, float p_roughness) { - - vec3 norm = normalize(p_vec); - norm.xy /= 1.0 + abs(norm.z); - norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); - - // we need to lie the derivatives (normg) and assume that DP side is always the same - // to get proper texture filtering - vec2 normg = norm.xy; - if (norm.z > 0.0) { - norm.y = 0.5 - norm.y + 0.5; - } - - // thanks to OpenGL spec using floor(layer + 0.5) for texture arrays, - // it's easy to have precision errors using fract() to interpolate layers - // as such, using fixed point to ensure it works. - - float index = p_roughness * RADIANCE_MAX_LOD; - int indexi = int(index * 256.0); - vec3 base = textureGrad(p_tex, vec3(norm.xy, float(indexi / 256)), dFdx(normg), dFdy(normg)).xyz; - vec3 next = textureGrad(p_tex, vec3(norm.xy, float(indexi / 256 + 1)), dFdx(normg), dFdy(normg)).xyz; - return mix(base, next, float(indexi % 256) / 256.0); -} - -#else - -uniform sampler2D radiance_map; // texunit:-2 - -vec3 textureDualParaboloid(sampler2D p_tex, vec3 p_vec, float p_roughness) { - - vec3 norm = normalize(p_vec); - norm.xy /= 1.0 + abs(norm.z); - norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); - if (norm.z > 0.0) { - norm.y = 0.5 - norm.y + 0.5; - } - return textureLod(p_tex, norm.xy, p_roughness * RADIANCE_MAX_LOD).xyz; -} - -#endif - -#endif - -/* Material Uniforms */ - -#if defined(USE_MATERIAL) - -/* clang-format off */ -layout(std140) uniform UniformData { - -MATERIAL_UNIFORMS - -}; -/* clang-format on */ - -#endif - -/* clang-format off */ - -FRAGMENT_SHADER_GLOBALS - -/* clang-format on */ - -layout(std140) uniform SceneData { - - highp mat4 projection_matrix; - highp mat4 inv_projection_matrix; - highp mat4 camera_inverse_matrix; - highp mat4 camera_matrix; - - mediump vec4 ambient_light_color; - mediump vec4 bg_color; - - mediump vec4 fog_color_enabled; - mediump vec4 fog_sun_color_amount; - - mediump float ambient_energy; - mediump float bg_energy; - - mediump float z_offset; - mediump float z_slope_scale; - highp float shadow_dual_paraboloid_render_zfar; - highp float shadow_dual_paraboloid_render_side; - - highp vec2 viewport_size; - highp vec2 screen_pixel_size; - highp vec2 shadow_atlas_pixel_size; - highp vec2 directional_shadow_pixel_size; - - highp float time; - highp float z_far; - mediump float reflection_multiplier; - mediump float subsurface_scatter_width; - mediump float ambient_occlusion_affect_light; - mediump float ambient_occlusion_affect_ao_channel; - mediump float opaque_prepass_threshold; - - bool fog_depth_enabled; - highp float fog_depth_begin; - highp float fog_depth_end; - mediump float fog_density; - highp float fog_depth_curve; - bool fog_transmit_enabled; - highp float fog_transmit_curve; - bool fog_height_enabled; - highp float fog_height_min; - highp float fog_height_max; - highp float fog_height_curve; -}; - - //directional light data - -#ifdef USE_LIGHT_DIRECTIONAL - -layout(std140) uniform DirectionalLightData { - - highp vec4 light_pos_inv_radius; - mediump vec4 light_direction_attenuation; - mediump vec4 light_color_energy; - mediump vec4 light_params; // cone attenuation, angle, specular, shadow enabled, - mediump vec4 light_clamp; - mediump vec4 shadow_color_contact; - highp mat4 shadow_matrix1; - highp mat4 shadow_matrix2; - highp mat4 shadow_matrix3; - highp mat4 shadow_matrix4; - mediump vec4 shadow_split_offsets; -}; - -uniform highp sampler2DShadow directional_shadow; // texunit:-4 - -#endif - -#ifdef USE_VERTEX_LIGHTING -in vec4 diffuse_light_interp; -in vec4 specular_light_interp; -#endif -// omni and spot - -struct LightData { - - highp vec4 light_pos_inv_radius; - mediump vec4 light_direction_attenuation; - mediump vec4 light_color_energy; - mediump vec4 light_params; // cone attenuation, angle, specular, shadow enabled, - mediump vec4 light_clamp; - mediump vec4 shadow_color_contact; - highp mat4 shadow_matrix; -}; - -layout(std140) uniform OmniLightData { // ubo:4 - - LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; -}; - -layout(std140) uniform SpotLightData { // ubo:5 - - LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; -}; - -uniform highp sampler2DShadow shadow_atlas; // texunit:-5 - -struct ReflectionData { - - mediump vec4 box_extents; - mediump vec4 box_offset; - mediump vec4 params; // intensity, 0, interior , boxproject - mediump vec4 ambient; // ambient color, energy - mediump vec4 atlas_clamp; - highp mat4 local_matrix; // up to here for spot and omni, rest is for directional - // notes: for ambientblend, use distance to edge to blend between already existing global environment -}; - -layout(std140) uniform ReflectionProbeData { //ubo:6 - - ReflectionData reflections[MAX_REFLECTION_DATA_STRUCTS]; -}; -uniform mediump sampler2D reflection_atlas; // texunit:-3 - -#ifdef USE_FORWARD_LIGHTING - -uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; -uniform int omni_light_count; - -uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; -uniform int spot_light_count; - -uniform int reflection_indices[MAX_FORWARD_LIGHTS]; -uniform int reflection_count; - -#endif - -#if defined(SCREEN_TEXTURE_USED) - -uniform highp sampler2D screen_texture; // texunit:-7 - -#endif - -#ifdef USE_MULTIPLE_RENDER_TARGETS - -layout(location = 0) out vec4 diffuse_buffer; -layout(location = 1) out vec4 specular_buffer; -layout(location = 2) out vec4 normal_mr_buffer; -#if defined(ENABLE_SSS) -layout(location = 3) out float sss_buffer; -#endif - -#else - -layout(location = 0) out vec4 frag_color; - -#endif - -in highp vec4 position_interp; -uniform highp sampler2D depth_buffer; // texunit:-8 - -#ifdef USE_CONTACT_SHADOWS - -float contact_shadow_compute(vec3 pos, vec3 dir, float max_distance) { - - if (abs(dir.z) > 0.99) - return 1.0; - - vec3 endpoint = pos + dir * max_distance; - vec4 source = position_interp; - vec4 dest = projection_matrix * vec4(endpoint, 1.0); - - vec2 from_screen = (source.xy / source.w) * 0.5 + 0.5; - vec2 to_screen = (dest.xy / dest.w) * 0.5 + 0.5; - - vec2 screen_rel = to_screen - from_screen; - - if (length(screen_rel) < 0.00001) - return 1.0; // too small, don't do anything - - /* - float pixel_size; // approximate pixel size - - if (screen_rel.x > screen_rel.y) { - - pixel_size = abs((pos.x - endpoint.x) / (screen_rel.x / screen_pixel_size.x)); - } else { - pixel_size = abs((pos.y - endpoint.y) / (screen_rel.y / screen_pixel_size.y)); - } - */ - vec4 bias = projection_matrix * vec4(pos + vec3(0.0, 0.0, max_distance * 0.5), 1.0); - - vec2 pixel_incr = normalize(screen_rel) * screen_pixel_size; - - float steps = length(screen_rel) / length(pixel_incr); - steps = min(2000.0, steps); // put a limit to avoid freezing in some strange situation - //steps = 10.0; - - vec4 incr = (dest - source) / steps; - float ratio = 0.0; - float ratio_incr = 1.0 / steps; - - while (steps > 0.0) { - source += incr * 2.0; - bias += incr * 2.0; - - vec3 uv_depth = (source.xyz / source.w) * 0.5 + 0.5; - if (uv_depth.x > 0.0 && uv_depth.x < 1.0 && uv_depth.y > 0.0 && uv_depth.y < 1.0) { - float depth = texture(depth_buffer, uv_depth.xy).r; - - if (depth < uv_depth.z) { - if (depth > (bias.z / bias.w) * 0.5 + 0.5) { - return min(pow(ratio, 4.0), 1.0); - } else { - return 1.0; - } - } - - ratio += ratio_incr; - steps -= 1.0; - } else { - return 1.0; - } - } - - return 1.0; -} - -#endif - -// 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)); -} - -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); -} - -float D_GGX_anisotropic(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 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); -} - -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)); -} - -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) { - -#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(NdotV, 0.0); - -#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 - - 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) { // FIXME: roughness == 0 should not disable specular light entirely - - // D - -#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)); - float intensity = blinn; - - specular_light += light_color * intensity * specular_blob_intensity * attenuation; - -#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)); - float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); - - specular_light += light_color * intensity * specular_blob_intensity * attenuation; - -#elif defined(SPECULAR_TOON) - - vec3 R = normalize(-reflect(L, N)); - float RdotV = dot(R, V); - float mid = 1.0 - roughness; - mid *= mid; - float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; - diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection - -#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); - float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); - -#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); -#endif - // F - vec3 f0 = F0(metallic, specular, diffuse_color); - float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); - - vec3 specular_brdf_NL = cNdotL * D * F * G; - - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; -#endif - -#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 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) -} - -float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) { - -#ifdef SHADOW_MODE_PCF_13 - - float avg = textureProj(shadow, vec4(pos, depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0)); - return avg * (1.0 / 13.0); -#endif - -#ifdef SHADOW_MODE_PCF_5 - - float avg = textureProj(shadow, vec4(pos, depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(shadow, vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); - return avg * (1.0 / 5.0); - -#endif - -#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) - - return textureProj(shadow, vec4(pos, depth, 1.0)); - -#endif -} - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -in highp float dp_clip; - -#endif - -void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) { - - vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length * omni_lights[idx].light_pos_inv_radius.w; - float omni_attenuation; - if (normalized_distance < 1.0) { - omni_attenuation = pow(1.0 - normalized_distance, omni_lights[idx].light_direction_attenuation.w); - } else { - omni_attenuation = 0.0; - } - vec3 light_attenuation = vec3(omni_attenuation); - -#if !defined(SHADOWS_DISABLED) -#ifdef USE_SHADOW - if (omni_lights[idx].light_params.w > 0.5) { - // there is a shadowmap - - highp vec3 splane = (omni_lights[idx].shadow_matrix * vec4(vertex, 1.0)).xyz; - float shadow_len = length(splane); - splane = normalize(splane); - vec4 clamp_rect = omni_lights[idx].light_clamp; - - if (splane.z >= 0.0) { - - splane.z += 1.0; - - clamp_rect.y += clamp_rect.w; - - } else { - - splane.z = 1.0 - splane.z; - - /* - if (clamp_rect.z < clamp_rect.w) { - clamp_rect.x += clamp_rect.z; - } else { - clamp_rect.y += clamp_rect.w; - } - */ - } - - splane.xy /= splane.z; - splane.xy = splane.xy * 0.5 + 0.5; - splane.z = shadow_len * omni_lights[idx].light_pos_inv_radius.w; - - splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; - float shadow = sample_shadow(shadow_atlas, shadow_atlas_pixel_size, splane.xy, splane.z, clamp_rect); - -#ifdef USE_CONTACT_SHADOWS - - if (shadow > 0.01 && omni_lights[idx].shadow_color_contact.a > 0.0) { - - float contact_shadow = contact_shadow_compute(vertex, normalize(light_rel_vec), min(light_length, omni_lights[idx].shadow_color_contact.a)); - shadow = min(shadow, contact_shadow); - } -#endif - light_attenuation *= mix(omni_lights[idx].shadow_color_contact.rgb, vec3(1.0), shadow); - } -#endif //USE_SHADOW -#endif //SHADOWS_DISABLED - light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, omni_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, omni_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * omni_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); -} - -void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) { - - vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length * spot_lights[idx].light_pos_inv_radius.w; - float spot_attenuation; - if (normalized_distance < 1.0) { - spot_attenuation = pow(1.0 - normalized_distance, spot_lights[idx].light_direction_attenuation.w); - } else { - spot_attenuation = 0.0; - } - vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz; - float spot_cutoff = spot_lights[idx].light_params.y; - float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_cutoff); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); - spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].light_params.x); - vec3 light_attenuation = vec3(spot_attenuation); - -#if !defined(SHADOWS_DISABLED) -#ifdef USE_SHADOW - if (spot_lights[idx].light_params.w > 0.5) { - //there is a shadowmap - highp vec4 splane = (spot_lights[idx].shadow_matrix * vec4(vertex, 1.0)); - splane.xyz /= splane.w; - - float shadow = sample_shadow(shadow_atlas, shadow_atlas_pixel_size, splane.xy, splane.z, spot_lights[idx].light_clamp); - -#ifdef USE_CONTACT_SHADOWS - if (shadow > 0.01 && spot_lights[idx].shadow_color_contact.a > 0.0) { - - float contact_shadow = contact_shadow_compute(vertex, normalize(light_rel_vec), min(light_length, spot_lights[idx].shadow_color_contact.a)); - shadow = min(shadow, contact_shadow); - } -#endif - light_attenuation *= mix(spot_lights[idx].shadow_color_contact.rgb, vec3(1.0), shadow); - } -#endif //USE_SHADOW -#endif //SHADOWS_DISABLED - - light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, spot_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, spot_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * spot_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); -} - -void reflection_process(int idx, vec3 vertex, vec3 normal, vec3 binormal, vec3 tangent, float roughness, float anisotropy, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) { - - vec3 ref_vec = normalize(reflect(vertex, normal)); - vec3 local_pos = (reflections[idx].local_matrix * vec4(vertex, 1.0)).xyz; - vec3 box_extents = reflections[idx].box_extents.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)); - //make blend more rounded - blend = mix(length(inner_pos), blend, blend); - blend *= blend; - blend = max(0.0, 1.0 - blend); - - if (reflections[idx].params.x > 0.0) { // compute reflection - - vec3 local_ref_vec = (reflections[idx].local_matrix * vec4(ref_vec, 0.0)).xyz; - - if (reflections[idx].params.w > 0.5) { //box project - - vec3 nrdir = normalize(local_ref_vec); - vec3 rbmax = (box_extents - local_pos) / nrdir; - vec3 rbmin = (-box_extents - local_pos) / nrdir; - - vec3 rbminmax = mix(rbmin, rbmax, 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; - local_ref_vec = posonbox - reflections[idx].box_offset.xyz; - } - - vec4 clamp_rect = reflections[idx].atlas_clamp; - vec3 norm = normalize(local_ref_vec); - norm.xy /= 1.0 + abs(norm.z); - norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); - if (norm.z > 0.0) { - norm.y = 0.5 - norm.y + 0.5; - } - - vec2 atlas_uv = norm.xy * clamp_rect.zw + clamp_rect.xy; - atlas_uv = clamp(atlas_uv, clamp_rect.xy, clamp_rect.xy + clamp_rect.zw); - - highp vec4 reflection; - reflection.rgb = textureLod(reflection_atlas, atlas_uv, roughness * 5.0).rgb; - - if (reflections[idx].params.z < 0.5) { - reflection.rgb = mix(skybox, reflection.rgb, blend); - } - reflection.rgb *= reflections[idx].params.x; - reflection.a = blend; - reflection.rgb *= reflection.a; - - reflection_accum += reflection; - } -#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) - if (reflections[idx].ambient.a > 0.0) { //compute ambient using skybox - - vec3 local_amb_vec = (reflections[idx].local_matrix * vec4(normal, 0.0)).xyz; - - vec3 splane = normalize(local_amb_vec); - vec4 clamp_rect = reflections[idx].atlas_clamp; - - splane.z *= -1.0; - if (splane.z >= 0.0) { - splane.z += 1.0; - clamp_rect.y += clamp_rect.w; - } else { - splane.z = 1.0 - splane.z; - splane.y = -splane.y; - } - - splane.xy /= splane.z; - splane.xy = splane.xy * 0.5 + 0.5; - - splane.xy = splane.xy * clamp_rect.zw + clamp_rect.xy; - splane.xy = clamp(splane.xy, clamp_rect.xy, clamp_rect.xy + clamp_rect.zw); - - highp vec4 ambient_out; - ambient_out.a = blend; - ambient_out.rgb = textureLod(reflection_atlas, splane.xy, 5.0).rgb; - ambient_out.rgb = mix(reflections[idx].ambient.rgb, ambient_out.rgb, reflections[idx].ambient.a); - if (reflections[idx].params.z < 0.5) { - ambient_out.rgb = mix(ambient, ambient_out.rgb, blend); - } - - ambient_out.rgb *= ambient_out.a; - ambient_accum += ambient_out; - } else { - - highp vec4 ambient_out; - ambient_out.a = blend; - ambient_out.rgb = reflections[idx].ambient.rgb; - if (reflections[idx].params.z < 0.5) { - ambient_out.rgb = mix(ambient, ambient_out.rgb, blend); - } - ambient_out.rgb *= ambient_out.a; - ambient_accum += ambient_out; - } -#endif -} - -#ifdef USE_LIGHTMAP -uniform mediump sampler2D lightmap; //texunit:-9 -uniform mediump float lightmap_energy; -#endif - -#ifdef USE_LIGHTMAP_CAPTURE -uniform mediump vec4[12] lightmap_captures; -uniform bool lightmap_capture_sky; - -#endif - -#ifdef USE_GI_PROBES - -uniform mediump sampler3D gi_probe1; //texunit:-9 -uniform highp mat4 gi_probe_xform1; -uniform highp vec3 gi_probe_bounds1; -uniform highp vec3 gi_probe_cell_size1; -uniform highp float gi_probe_multiplier1; -uniform highp float gi_probe_bias1; -uniform highp float gi_probe_normal_bias1; -uniform bool gi_probe_blend_ambient1; - -uniform mediump sampler3D gi_probe2; //texunit:-10 -uniform highp mat4 gi_probe_xform2; -uniform highp vec3 gi_probe_bounds2; -uniform highp vec3 gi_probe_cell_size2; -uniform highp float gi_probe_multiplier2; -uniform highp float gi_probe_bias2; -uniform highp float gi_probe_normal_bias2; -uniform bool gi_probe2_enabled; -uniform bool gi_probe_blend_ambient2; - -vec3 voxel_cone_trace(mediump sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { - - float dist = p_bias; //1.0; //dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0; - float alpha = 0.0; - vec3 color = vec3(0.0); - - while (dist < max_distance && alpha < 0.95) { - float diameter = max(1.0, 2.0 * tan_half_angle * dist); - vec4 scolor = textureLod(probe, (pos + dist * direction) * cell_size, log2(diameter)); - float a = (1.0 - alpha); - color += scolor.rgb * a; - alpha += a * scolor.a; - dist += diameter * 0.5; - } - - if (blend_ambient) { - color.rgb = mix(ambient, color.rgb, min(1.0, alpha / 0.95)); - } - - return color; -} - -void gi_probe_compute(mediump sampler3D probe, mat4 probe_xform, vec3 bounds, vec3 cell_size, vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient, float multiplier, mat3 normal_mtx, vec3 ref_vec, float roughness, float p_bias, float p_normal_bias, inout vec4 out_spec, inout vec4 out_diff) { - - vec3 probe_pos = (probe_xform * vec4(pos, 1.0)).xyz; - vec3 ref_pos = (probe_xform * vec4(pos + ref_vec, 1.0)).xyz; - ref_vec = normalize(ref_pos - probe_pos); - - probe_pos += (probe_xform * vec4(normal_mtx[2], 0.0)).xyz * p_normal_bias; - - /* out_diff.rgb = voxel_cone_trace(probe,cell_size,probe_pos,normalize((probe_xform * vec4(ref_vec,0.0)).xyz),0.0 ,100.0); - out_diff.a = 1.0; - return;*/ - //out_diff = vec4(textureLod(probe,probe_pos*cell_size,3.0).rgb,1.0); - //return; - - //this causes corrupted pixels, i have no idea why.. - if (any(bvec2(any(lessThan(probe_pos, vec3(0.0))), any(greaterThan(probe_pos, bounds))))) { - return; - } - - vec3 blendv = abs(probe_pos / bounds * 2.0 - 1.0); - float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0); - //float blend=1.0; - - float max_distance = length(bounds); - - //radiance -#ifdef VCT_QUALITY_HIGH - -#define MAX_CONE_DIRS 6 - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5)); - - float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); - float cone_angle_tan = 0.577; - float min_ref_tan = 0.0; -#else - -#define MAX_CONE_DIRS 4 - - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.707107, 0.0, 0.707107), - vec3(0.0, 0.707107, 0.707107), - vec3(-0.707107, 0.0, 0.707107), - vec3(0.0, -0.707107, 0.707107)); - - float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); - float cone_angle_tan = 0.98269; - max_distance *= 0.5; - float min_ref_tan = 0.2; - -#endif - vec3 light = vec3(0.0); - for (int i = 0; i < MAX_CONE_DIRS; i++) { - - vec3 dir = normalize((probe_xform * vec4(pos + normal_mtx * cone_dirs[i], 1.0)).xyz - probe_pos); - light += cone_weights[i] * voxel_cone_trace(probe, cell_size, probe_pos, ambient, blend_ambient, dir, cone_angle_tan, max_distance, p_bias); - } - - light *= multiplier; - - out_diff += vec4(light * blend, blend); - - //irradiance - - vec3 irr_light = voxel_cone_trace(probe, cell_size, probe_pos, environment, blend_ambient, ref_vec, max(min_ref_tan, tan(roughness * 0.5 * M_PI * 0.99)), max_distance, p_bias); - - irr_light *= multiplier; - //irr_light=vec3(0.0); - - out_spec += vec4(irr_light * blend, blend); -} - -void gi_probes_compute(vec3 pos, vec3 normal, float roughness, inout vec3 out_specular, inout vec3 out_ambient) { - - roughness = roughness * roughness; - - vec3 ref_vec = normalize(reflect(normalize(pos), normal)); - - //find arbitrary tangent and bitangent, then build a matrix - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); - vec3 tangent = normalize(cross(v0, normal)); - vec3 bitangent = normalize(cross(tangent, normal)); - mat3 normal_mat = mat3(tangent, bitangent, normal); - - vec4 diff_accum = vec4(0.0); - vec4 spec_accum = vec4(0.0); - - vec3 ambient = out_ambient; - out_ambient = vec3(0.0); - - vec3 environment = out_specular; - - out_specular = vec3(0.0); - - gi_probe_compute(gi_probe1, gi_probe_xform1, gi_probe_bounds1, gi_probe_cell_size1, pos, ambient, environment, gi_probe_blend_ambient1, gi_probe_multiplier1, normal_mat, ref_vec, roughness, gi_probe_bias1, gi_probe_normal_bias1, spec_accum, diff_accum); - - if (gi_probe2_enabled) { - - gi_probe_compute(gi_probe2, gi_probe_xform2, gi_probe_bounds2, gi_probe_cell_size2, pos, ambient, environment, gi_probe_blend_ambient2, gi_probe_multiplier2, normal_mat, ref_vec, roughness, gi_probe_bias2, gi_probe_normal_bias2, spec_accum, diff_accum); - } - - if (diff_accum.a > 0.0) { - diff_accum.rgb /= diff_accum.a; - } - - if (spec_accum.a > 0.0) { - spec_accum.rgb /= spec_accum.a; - } - - out_specular += spec_accum.rgb; - out_ambient += diff_accum.rgb; -} - -#endif - -void main() { - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - - if (dp_clip > 0.0) - discard; -#endif - - //lay out everything, whathever is unused is optimized away anyway - 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); - -#if defined(ENABLE_AO) - float ao = 1.0; - float ao_light_affect = 0.0; -#endif - - float alpha = 1.0; - -#if defined(ALPHA_SCISSOR_USED) - float alpha_scissor = 0.5; -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - vec3 binormal = normalize(binormal_interp); - vec3 tangent = normalize(tangent_interp); -#else - vec3 binormal = vec3(0.0); - vec3 tangent = vec3(0.0); -#endif - vec3 normal = normalize(normal_interp); - -#if defined(DO_SIDE_CHECK) - if (!gl_FrontFacing) { - normal = -normal; - } -#endif - -#if defined(ENABLE_UV_INTERP) - vec2 uv = uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) - vec2 uv2 = uv2_interp; -#endif - -#if defined(ENABLE_COLOR_INTERP) - vec4 color = color_interp; -#endif - -#if defined(ENABLE_NORMALMAP) - - vec3 normalmap = vec3(0.5); -#endif - - float normaldepth = 1.0; - -#if defined(SCREEN_UV_USED) - vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; -#endif - -#if defined(ENABLE_SSS) - float sss_strength = 0.0; -#endif - - { - /* clang-format off */ - -FRAGMENT_SHADER_CODE - - /* clang-format on */ - } - -#if !defined(USE_SHADOW_TO_OPACITY) - -#if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { - discard; - } -#endif // ALPHA_SCISSOR_USED - -#ifdef USE_OPAQUE_PREPASS - - if (alpha < opaque_prepass_threshold) { - discard; - } - -#endif // USE_OPAQUE_PREPASS - -#endif // !USE_SHADOW_TO_OPACITY - -#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))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. - - normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)); - -#endif - -#if defined(LIGHT_USE_ANISOTROPY) - - if (anisotropy > 0.01) { - //rotation matrix - mat3 rot = mat3(tangent, binormal, normal); - //make local to space - tangent = normalize(rot * vec3(anisotropy_flow.x, anisotropy_flow.y, 0.0)); - binormal = normalize(rot * vec3(-anisotropy_flow.y, anisotropy_flow.x, 0.0)); - } - -#endif - -#ifdef ENABLE_CLIP_ALPHA - if (albedo.a < 0.99) { - //used for doublepass and shadowmapping - discard; - } -#endif - - /////////////////////// LIGHTING ////////////////////////////// - - //apply energy conservation - -#ifdef USE_VERTEX_LIGHTING - - vec3 specular_light = specular_light_interp.rgb; - vec3 diffuse_light = diffuse_light_interp.rgb; -#else - - vec3 specular_light = vec3(0.0, 0.0, 0.0); - vec3 diffuse_light = vec3(0.0, 0.0, 0.0); - -#endif - - vec3 ambient_light; - vec3 env_reflection_light = vec3(0.0, 0.0, 0.0); - - vec3 eye_vec = view; - - // IBL precalculations - float ndotv = clamp(dot(normal, eye_vec), 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 USE_RADIANCE_MAP - -#ifdef AMBIENT_LIGHT_DISABLED - ambient_light = vec3(0.0, 0.0, 0.0); -#else - { - - { //read radiance from dual paraboloid - - vec3 ref_vec = reflect(-eye_vec, normal); - ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); - vec3 radiance = textureDualParaboloid(radiance_map, ref_vec, roughness) * bg_energy; - env_reflection_light = radiance; - } - } -#ifndef USE_LIGHTMAP - { - - vec3 norm = normal; - norm = normalize((radiance_inverse_xform * vec4(norm, 0.0)).xyz); - norm.xy /= 1.0 + abs(norm.z); - norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); - if (norm.z > 0.0) { - norm.y = 0.5 - norm.y + 0.5; - } - - vec3 env_ambient = texture(irradiance_map, norm.xy).rgb * bg_energy; - env_ambient *= 1.0 - F; - - ambient_light = mix(ambient_light_color.rgb, env_ambient, radiance_ambient_contribution); - } -#endif -#endif //AMBIENT_LIGHT_DISABLED - -#else - -#ifdef AMBIENT_LIGHT_DISABLED - ambient_light = vec3(0.0, 0.0, 0.0); -#else - ambient_light = ambient_light_color.rgb; - env_reflection_light = bg_color.rgb * bg_energy; -#endif //AMBIENT_LIGHT_DISABLED - -#endif - - ambient_light *= ambient_energy; - - float specular_blob_intensity = 1.0; - -#if defined(SPECULAR_TOON) - specular_blob_intensity *= specular * 2.0; -#endif - -#ifdef USE_GI_PROBES - gi_probes_compute(vertex, normal, roughness, env_reflection_light, ambient_light); - -#endif - -#ifdef USE_LIGHTMAP - ambient_light = texture(lightmap, uv2).rgb * lightmap_energy; -#endif - -#ifdef USE_LIGHTMAP_CAPTURE - { - vec3 cone_dirs[12] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5), - vec3(0.0, 0.0, -1.0), - vec3(0.866025, 0.0, -0.5), - vec3(0.267617, 0.823639, -0.5), - vec3(-0.700629, 0.509037, -0.5), - vec3(-0.700629, -0.509037, -0.5), - 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 - -#ifdef USE_FORWARD_LIGHTING - - highp vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); - highp vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < reflection_count; i++) { - reflection_process(reflection_indices[i], vertex, normal, binormal, tangent, roughness, anisotropy, ambient_light, env_reflection_light, reflection_accum, ambient_accum); - } - - if (reflection_accum.a > 0.0) { - specular_light += reflection_accum.rgb / reflection_accum.a; - } else { - specular_light += env_reflection_light; - } -#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) - if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; - } -#endif -#endif - - { - -#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, GI, and reflection probes are added - // Environment brdf approximation (Lazarov 2013) - // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile - 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 - } - -#if defined(USE_LIGHT_DIRECTIONAL) - - vec3 light_attenuation = vec3(1.0); - - float depth_z = -vertex.z; -#ifdef LIGHT_DIRECTIONAL_SHADOW -#if !defined(SHADOWS_DISABLED) - -#ifdef LIGHT_USE_PSSM4 - if (depth_z < shadow_split_offsets.w) { -#elif defined(LIGHT_USE_PSSM2) - if (depth_z < shadow_split_offsets.y) { -#else - if (depth_z < shadow_split_offsets.x) { -#endif //LIGHT_USE_PSSM4 - - vec3 pssm_coord; - float pssm_fade = 0.0; - -#ifdef LIGHT_USE_PSSM_BLEND - float pssm_blend; - vec3 pssm_coord2; - bool use_blend = true; -#endif - -#ifdef LIGHT_USE_PSSM4 - - if (depth_z < shadow_split_offsets.y) { - - if (depth_z < shadow_split_offsets.x) { - - highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - -#if defined(LIGHT_USE_PSSM_BLEND) - - splane = (shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; - pssm_blend = smoothstep(0.0, shadow_split_offsets.x, depth_z); -#endif - - } else { - - highp vec4 splane = (shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - -#if defined(LIGHT_USE_PSSM_BLEND) - splane = (shadow_matrix3 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; - pssm_blend = smoothstep(shadow_split_offsets.x, shadow_split_offsets.y, depth_z); -#endif - } - } else { - - if (depth_z < shadow_split_offsets.z) { - - highp vec4 splane = (shadow_matrix3 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - -#if defined(LIGHT_USE_PSSM_BLEND) - splane = (shadow_matrix4 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; - pssm_blend = smoothstep(shadow_split_offsets.y, shadow_split_offsets.z, depth_z); -#endif - - } else { - - highp vec4 splane = (shadow_matrix4 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - pssm_fade = smoothstep(shadow_split_offsets.z, shadow_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 < shadow_split_offsets.x) { - - highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - -#if defined(LIGHT_USE_PSSM_BLEND) - - splane = (shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; - pssm_blend = smoothstep(0.0, shadow_split_offsets.x, depth_z); -#endif - - } else { - highp vec4 splane = (shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - pssm_fade = smoothstep(shadow_split_offsets.x, shadow_split_offsets.y, depth_z); -#if defined(LIGHT_USE_PSSM_BLEND) - use_blend = false; - -#endif - } - -#endif //LIGHT_USE_PSSM2 - -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) - { //regular orthogonal - highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - } -#endif - - //one one sample - - float shadow = sample_shadow(directional_shadow, directional_shadow_pixel_size, pssm_coord.xy, pssm_coord.z, light_clamp); - -#if defined(LIGHT_USE_PSSM_BLEND) - - if (use_blend) { - shadow = mix(shadow, sample_shadow(directional_shadow, directional_shadow_pixel_size, pssm_coord2.xy, pssm_coord2.z, light_clamp), pssm_blend); - } -#endif - -#ifdef USE_CONTACT_SHADOWS - if (shadow > 0.01 && shadow_color_contact.a > 0.0) { - - float contact_shadow = contact_shadow_compute(vertex, -light_direction_attenuation.xyz, shadow_color_contact.a); - shadow = min(shadow, contact_shadow); - } -#endif - light_attenuation = mix(mix(shadow_color_contact.rgb, vec3(1.0), shadow), vec3(1.0), pssm_fade); - } - -#endif // !defined(SHADOWS_DISABLED) -#endif //LIGHT_DIRECTIONAL_SHADOW - -#ifdef USE_VERTEX_LIGHTING - diffuse_light *= mix(vec3(1.0), light_attenuation, diffuse_light_interp.a); - specular_light *= mix(vec3(1.0), light_attenuation, specular_light_interp.a); - -#else - light_compute(normal, -light_direction_attenuation.xyz, eye_vec, binormal, tangent, light_color_energy.rgb, light_attenuation, albedo, transmission, light_params.z * specular_blob_intensity, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); -#endif - -#endif //#USE_LIGHT_DIRECTIONAL - -#ifdef USE_FORWARD_LIGHTING - -#ifdef USE_VERTEX_LIGHTING - - diffuse_light *= albedo; -#else - - for (int i = 0; i < omni_light_count; i++) { - light_process_omni(omni_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light, alpha); - } - - for (int i = 0; i < spot_light_count; i++) { - light_process_spot(spot_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light, alpha); - } - -#endif //USE_VERTEX_LIGHTING - -#endif - -#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_OPAQUE_PREPASS - - if (alpha < opaque_prepass_threshold) { - discard; - } - -#endif // USE_OPAQUE_PREPASS - -#endif // USE_SHADOW_TO_OPACITY - -#ifdef RENDER_DEPTH -//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) -#else - - specular_light *= reflection_multiplier; - ambient_light *= albedo; //ambient must be multiplied by albedo at the end - -#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 - - // base color remapping - diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point - ambient_light *= 1.0 - metallic; - - if (fog_color_enabled.a > 0.5) { - - float fog_amount = 0.0; - -#ifdef USE_LIGHT_DIRECTIONAL - - vec3 fog_color = mix(fog_color_enabled.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(normalize(vertex), -light_direction_attenuation.xyz), 0.0), 8.0)); -#else - - vec3 fog_color = fog_color_enabled.rgb; -#endif - - //apply fog - - if (fog_depth_enabled) { - float fog_far = fog_depth_end > 0.0 ? fog_depth_end : z_far; - - float fog_z = smoothstep(fog_depth_begin, fog_far, length(vertex)); - - fog_amount = pow(fog_z, fog_depth_curve) * fog_density; - if (fog_transmit_enabled) { - vec3 total_light = emission + ambient_light + specular_light + diffuse_light; - float transmit = pow(fog_z, fog_transmit_curve); - fog_color = mix(max(total_light, fog_color), fog_color, transmit); - } - } - - if (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)); - } - - float rev_amount = 1.0 - fog_amount; - - emission = emission * rev_amount + fog_color * fog_amount; - ambient_light *= rev_amount; - specular_light *= rev_amount; - diffuse_light *= rev_amount; - } - -#ifdef USE_MULTIPLE_RENDER_TARGETS - -#ifdef SHADELESS - diffuse_buffer = vec4(albedo.rgb, 0.0); - specular_buffer = vec4(0.0); - -#else - - //approximate ambient scale for SSAO, since we will lack full ambient - float max_emission = max(emission.r, max(emission.g, emission.b)); - float max_ambient = max(ambient_light.r, max(ambient_light.g, ambient_light.b)); - float max_diffuse = max(diffuse_light.r, max(diffuse_light.g, diffuse_light.b)); - float total_ambient = max_ambient + max_diffuse + max_emission; - float ambient_scale = (total_ambient > 0.0) ? (max_ambient + ambient_occlusion_affect_light * max_diffuse) / total_ambient : 0.0; - -#if defined(ENABLE_AO) - ambient_scale = mix(0.0, ambient_scale, ambient_occlusion_affect_ao_channel); -#endif - diffuse_buffer = vec4(emission + diffuse_light + ambient_light, ambient_scale); - specular_buffer = vec4(specular_light, metallic); - -#endif //SHADELESS - - normal_mr_buffer = vec4(normalize(normal) * 0.5 + 0.5, roughness); - -#if defined(ENABLE_SSS) - sss_buffer = sss_strength; -#endif - -#else //USE_MULTIPLE_RENDER_TARGETS - -#ifdef SHADELESS - frag_color = vec4(albedo, alpha); -#else - frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); -#endif //SHADELESS - -#endif //USE_MULTIPLE_RENDER_TARGETS - -#endif //RENDER_DEPTH -} diff --git a/drivers/gles3/shaders/screen_space_reflection.glsl b/drivers/gles3/shaders/screen_space_reflection.glsl deleted file mode 100644 index 39f1ea6155..0000000000 --- a/drivers/gles3/shaders/screen_space_reflection.glsl +++ /dev/null @@ -1,286 +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.0, 1.0, -1.0)); - - //////////////// - - // 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/gles3/shaders/ssao.glsl b/drivers/gles3/shaders/ssao.glsl deleted file mode 100644 index d9cdc3fc1f..0000000000 --- a/drivers/gles3/shaders/ssao.glsl +++ /dev/null @@ -1,277 +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 (16) -#endif - -#ifdef SSAO_QUALITY_LOW -#define NUM_SAMPLES (8) -#endif - -#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) -#define NUM_SAMPLES (12) -#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/gles3/shaders/ssao_blur.glsl b/drivers/gles3/shaders/ssao_blur.glsl deleted file mode 100644 index c49ea1e957..0000000000 --- a/drivers/gles3/shaders/ssao_blur.glsl +++ /dev/null @@ -1,119 +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/gles3/shaders/ssao_minify.glsl b/drivers/gles3/shaders/ssao_minify.glsl deleted file mode 100644 index 1696648dae..0000000000 --- a/drivers/gles3/shaders/ssao_minify.glsl +++ /dev/null @@ -1,56 +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; -/* clang-format on */ -uniform float camera_z_near; - -#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/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl deleted file mode 100644 index f40fb3a244..0000000000 --- a/drivers/gles3/shaders/subsurf_scattering.glsl +++ /dev/null @@ -1,174 +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/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl deleted file mode 100644 index f1fe1742eb..0000000000 --- a/drivers/gles3/shaders/tonemap.glsl +++ /dev/null @@ -1,309 +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() { - gl_Position = vertex_attrib; - - uv_interp = uv_in; - -#ifdef V_FLIP - uv_interp.y = 1.0f - uv_interp.y; -#endif -} - -/* clang-format off */ -[fragment] - -#if !defined(GLES_OVER_GL) -precision mediump float; -#endif -/* clang-format on */ - -in vec2 uv_interp; - -uniform highp sampler2D source; //texunit:0 - -uniform float exposure; -uniform float white; - -#ifdef USE_AUTO_EXPOSURE -uniform highp sampler2D source_auto_exposure; //texunit:1 -uniform highp float auto_exposure_grey; -#endif - -#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 - -uniform highp sampler2D source_glow; //texunit:2 -uniform highp float glow_intensity; -#endif - -#ifdef USE_BCS -uniform vec3 bcs; -#endif - -#ifdef USE_COLOR_CORRECTION -uniform sampler2D color_correction; //texunit:3 -#endif - -layout(location = 0) out vec4 frag_color; - -#ifdef USE_GLOW_FILTER_BICUBIC -// w0, w1, w2, and w3 are the four cubic B-spline basis functions -float w0(float a) { - return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); -} - -float w1(float a) { - return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f); -} - -float w2(float a) { - return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f); -} - -float w3(float a) { - return (1.0f / 6.0f) * (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.0f + w1(a) / (w0(a) + w1(a)); -} - -float h1(float a) { - return 1.0f + 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 pixel_size = vec2(1.0f) / tex_size; - - uv = uv * tex_size + vec2(0.5f); - - 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.5f)) * pixel_size; - vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size; - vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size; - vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size; - - return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) + - (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod))); -} - -#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) -#else -#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod)) -#endif - -vec3 tonemap_filmic(vec3 color, float white) { - // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers - // also useful to scale the input to the range that the tonemapper is designed for (some require very high input values) - // has no effect on the curve's general shape or visual properties - const float exposure_bias = 2.0f; - const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance - const float B = 0.30f * exposure_bias; - const float C = 0.10f; - const float D = 0.20f; - const float E = 0.01f; - const float F = 0.30f; - - vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; - float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F; - - return clamp(color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f)); -} - -vec3 tonemap_aces(vec3 color, float white) { - const float exposure_bias = 0.85f; - const float A = 2.51f * exposure_bias * exposure_bias; - const float B = 0.03f * exposure_bias; - const float C = 2.43f * exposure_bias * exposure_bias; - const float D = 0.59f * exposure_bias; - const float E = 0.14f; - - vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E); - float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E); - - return clamp(color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f)); -} - -vec3 tonemap_reinhard(vec3 color, float white) { - return clamp((white * color + color) / (color * white + white), vec3(0.0f), vec3(1.0f)); -} - -vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped input in range [0;1] - const vec3 a = vec3(0.055f); - return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); -} - -// inputs are LINEAR, If Linear tonemapping is selected no transform is performed else outputs are clamped [0, 1] color -vec3 apply_tonemapping(vec3 color, float white) { -#ifdef USE_REINHARD_TONEMAPPER - return tonemap_reinhard(color, white); -#endif - -#ifdef USE_FILMIC_TONEMAPPER - return tonemap_filmic(color, white); -#endif - -#ifdef USE_ACES_TONEMAPPER - return tonemap_aces(color, white); -#endif - - return color; // no other selected -> linear: no color transform applied -} - -vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels - vec3 glow = vec3(0.0f); - -#ifdef USE_GLOW_LEVEL1 - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb; -#endif - -#ifdef USE_GLOW_LEVEL2 - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb; -#endif - -#ifdef USE_GLOW_LEVEL3 - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb; -#endif - -#ifdef USE_GLOW_LEVEL4 - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb; -#endif - -#ifdef USE_GLOW_LEVEL5 - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb; -#endif - -#ifdef USE_GLOW_LEVEL6 - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb; -#endif - -#ifdef USE_GLOW_LEVEL7 - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 7).rgb; -#endif - - return glow; -} - -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 - //need color clamping - color = clamp(color, vec3(0.0f), vec3(1.0f)); - color = max((color + glow) - (color * glow), vec3(0.0)); -#endif - -#ifdef USE_GLOW_SOFTLIGHT - //need color clamping - color = clamp(color, vec3(0.0f), vec3(1.0)); - glow = glow * vec3(0.5f) + vec3(0.5f); - - color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r))); - color.g = (glow.g <= 0.5f) ? (color.g - (1.0f - 2.0f * glow.g) * color.g * (1.0f - color.g)) : (((glow.g > 0.5f) && (color.g <= 0.25f)) ? (color.g + (2.0f * glow.g - 1.0f) * (4.0f * color.g * (4.0f * color.g + 1.0f) * (color.g - 1.0f) + 7.0f * color.g)) : (color.g + (2.0f * glow.g - 1.0f) * (sqrt(color.g) - color.g))); - color.b = (glow.b <= 0.5f) ? (color.b - (1.0f - 2.0f * glow.b) * color.b * (1.0f - color.b)) : (((glow.b > 0.5f) && (color.b <= 0.25f)) ? (color.b + (2.0f * glow.b - 1.0f) * (4.0f * color.b * (4.0f * color.b + 1.0f) * (color.b - 1.0f) + 7.0f * color.b)) : (color.b + (2.0f * glow.b - 1.0f) * (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.0f), color, bcs.x); - color = mix(vec3(0.5f), color, bcs.y); - color = mix(vec3(dot(vec3(1.0f), color) * 0.33333f), color, bcs.z); - - return color; -} - -vec3 apply_color_correction(vec3 color, sampler2D correction_tex) { - color.r = texture(correction_tex, vec2(color.r, 0.0f)).r; - color.g = texture(correction_tex, vec2(color.g, 0.0f)).g; - color.b = texture(correction_tex, vec2(color.b, 0.0f)).b; - - return color; -} - -void main() { - vec3 color = textureLod(source, uv_interp, 0.0f).rgb; - - // Exposure - -#ifdef USE_AUTO_EXPOSURE - color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / auto_exposure_grey; -#endif - - color *= exposure; - - // Early Tonemap & SRGB Conversion; note that Linear tonemapping does not clamp to [0, 1]; some operations below expect a [0, 1] range and will clamp - - color = apply_tonemapping(color, white); - -#ifdef KEEP_3D_LINEAR - // leave color as is (-> don't convert to SRGB) -#else - //need color clamping - color = clamp(color, vec3(0.0f), vec3(1.0f)); - color = linear_to_srgb(color); // regular linear -> SRGB conversion (needs clamped values) -#endif - - // Glow - -#ifdef USING_GLOW - vec3 glow = gather_glow(source_glow, uv_interp) * glow_intensity; - - // high dynamic range -> SRGB - glow = apply_tonemapping(glow, white); - glow = clamp(glow, vec3(0.0f), vec3(1.0f)); - glow = linear_to_srgb(glow); - - 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 - - frag_color = vec4(color, 1.0f); -} |