diff options
Diffstat (limited to 'drivers')
92 files changed, 824 insertions, 17460 deletions
diff --git a/drivers/SCsub b/drivers/SCsub index 73a3f7898a..b8bba91378 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -16,6 +16,7 @@ SConscript('alsa/SCsub') SConscript('pulseaudio/SCsub') if (env["platform"] == "windows"): SConscript("rtaudio/SCsub") + SConscript("wasapi/SCsub") if (env["xaudio2"] == "yes"): SConscript("xaudio2/SCsub") diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 4e6739e8c0..40c66b0bc5 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -87,7 +87,7 @@ Error AudioDriverALSA::init() { CHECK_FAIL(status < 0); int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = closest_power_of_2(latency * mix_rate / 1000); // set buffer size from project settings status = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size); diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h index 9e9413f3d9..83601be41b 100644 --- a/drivers/alsa/audio_driver_alsa.h +++ b/drivers/alsa/audio_driver_alsa.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/convex_decomp/b2d_decompose.cpp b/drivers/convex_decomp/b2d_decompose.cpp index d9011b8eab..14ab4d1072 100644 --- a/drivers/convex_decomp/b2d_decompose.cpp +++ b/drivers/convex_decomp/b2d_decompose.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/convex_decomp/b2d_decompose.h b/drivers/convex_decomp/b2d_decompose.h index 3a064e08d3..a87f5a656c 100644 --- a/drivers/convex_decomp/b2d_decompose.h +++ b/drivers/convex_decomp/b2d_decompose.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/gl_context/context_gl.cpp b/drivers/gl_context/context_gl.cpp index 935391d58e..a453eef227 100644 --- a/drivers/gl_context/context_gl.cpp +++ b/drivers/gl_context/context_gl.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/gl_context/context_gl.h b/drivers/gl_context/context_gl.h index c8eb0f93b4..399657eb52 100644 --- a/drivers/gl_context/context_gl.h +++ b/drivers/gl_context/context_gl.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp deleted file mode 100644 index 2abdbe9d0a..0000000000 --- a/drivers/gles2/rasterizer_gles2.cpp +++ /dev/null @@ -1,10767 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 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. */ -/*************************************************************************/ -#ifdef GLES2_ENABLED - -#include "rasterizer_gles2.h" -#include "gl_context/context_gl.h" -#include "os/os.h" -#include "project_settings.h" -#include "servers/visual/particle_system_sw.h" -#include "servers/visual/shader_language.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef GLEW_ENABLED -#define _GL_HALF_FLOAT_OES 0x140B -#else -#define _GL_HALF_FLOAT_OES 0x8D61 -#endif - -#define _GL_RGBA16F_EXT 0x881A -#define _GL_RGB16F_EXT 0x881B -#define _GL_RG16F_EXT 0x822F -#define _GL_R16F_EXT 0x822D -#define _GL_R32F_EXT 0x822E - -#define _GL_RED_EXT 0x1903 -#define _GL_RG_EXT 0x8227 -#define _GL_R8_EXT 0x8229 -#define _GL_RG8_EXT 0x822B - -#define _DEPTH_COMPONENT24_OES 0x81A6 - -#ifdef GLEW_ENABLED -#define _glClearDepth glClearDepth -#else -#define _glClearDepth glClearDepthf -#endif - -#define _GL_SRGB_EXT 0x8C40 -#define _GL_SRGB_ALPHA_EXT 0x8C42 - -#define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF - -//#define DEBUG_OPENGL - -#ifdef DEBUG_OPENGL - -#define DEBUG_TEST_ERROR(m_section) \ - { \ - print_line("AT: " + String(m_section)); \ - glFlush(); \ - uint32_t err = glGetError(); \ - if (err) { \ - print_line("OpenGL Error #" + itos(err) + " at: " + m_section); \ - } \ - } - -#else - -#define DEBUG_TEST_ERROR(m_section) - -#endif - -static RasterizerGLES2 *_singleton = NULL; - -#ifdef GLES_NO_CLIENT_ARRAYS -static float GlobalVertexBuffer[MAX_POLYGON_VERTICES * 8] = { 0 }; -#endif - -static const GLenum prim_type[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; - -_FORCE_INLINE_ static void _set_color_attrib(const Color &p_color) { - - GLfloat c[4] = { p_color.r, p_color.g, p_color.b, p_color.a }; - glVertexAttrib4fv(VS::ARRAY_COLOR, c); -} - -static _FORCE_INLINE_ uint16_t make_half_float(float f) { - - union { - float fv; - uint32_t ui; - } ci; - ci.fv = f; - - unsigned int x = ci.ui; - unsigned int sign = (unsigned short)(x >> 31); - unsigned int mantissa; - unsigned int exp; - uint16_t hf; - - // get mantissa - mantissa = x & ((1 << 23) - 1); - // get exponent bits - exp = x & (0xFF << 23); - if (exp >= 0x47800000) { - // check if the original single precision float number is a NaN - if (mantissa && (exp == (0xFF << 23))) { - // we have a single precision NaN - mantissa = (1 << 23) - 1; - } else { - // 16-bit half-float representation stores number as Inf - mantissa = 0; - } - hf = (((uint16_t)sign) << 15) | (uint16_t)((0x1F << 10)) | - (uint16_t)(mantissa >> 13); - } - // check if exponent is <= -15 - else if (exp <= 0x38000000) { - - /*// store a denorm half-float value or zero - exp = (0x38000000 - exp) >> 23; - mantissa >>= (14 + exp); - - hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa); - */ - hf = 0; //denormals do not work for 3D, convert to zero - } else { - hf = (((uint16_t)sign) << 15) | - (uint16_t)((exp - 0x38000000) >> 13) | - (uint16_t)(mantissa >> 13); - } - - return hf; -} - -void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color *p_colors, const Vector3 *p_uvs, const Plane *p_tangents, int p_instanced) { - - ERR_FAIL_COND(!p_vertices); - ERR_FAIL_COND(p_points < 1 || p_points > 4); - - bool quad = false; - - GLenum type; - switch (p_points) { - - case 1: type = GL_POINTS; break; - case 2: type = GL_LINES; break; - case 4: quad = true; p_points = 3; - case 3: type = GL_TRIANGLES; break; - }; - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - GLfloat vert_array[18]; - GLfloat normal_array[18]; - GLfloat color_array[24]; - GLfloat tangent_array[24]; - GLfloat uv_array[18]; - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, vert_array); - - for (int i = 0; i < p_points; i++) { - - vert_array[i * 3 + 0] = p_vertices[i].x; - vert_array[i * 3 + 1] = p_vertices[i].y; - vert_array[i * 3 + 2] = p_vertices[i].z; - if (quad) { - int idx = 2 + i; - if (idx == 4) - idx = 0; - vert_array[9 + i * 3 + 0] = p_vertices[idx].x; - vert_array[9 + i * 3 + 1] = p_vertices[idx].y; - vert_array[9 + i * 3 + 2] = p_vertices[idx].z; - } - } - - if (p_normals) { - glEnableVertexAttribArray(VS::ARRAY_NORMAL); - glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false, 0, normal_array); - for (int i = 0; i < p_points; i++) { - - normal_array[i * 3 + 0] = p_normals[i].x; - normal_array[i * 3 + 1] = p_normals[i].y; - normal_array[i * 3 + 2] = p_normals[i].z; - if (quad) { - int idx = 2 + i; - if (idx == 4) - idx = 0; - normal_array[9 + i * 3 + 0] = p_normals[idx].x; - normal_array[9 + i * 3 + 1] = p_normals[idx].y; - normal_array[9 + i * 3 + 2] = p_normals[idx].z; - } - } - } else { - glDisableVertexAttribArray(VS::ARRAY_NORMAL); - } - - if (p_colors) { - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, 0, color_array); - for (int i = 0; i < p_points; i++) { - - color_array[i * 4 + 0] = p_colors[i].r; - color_array[i * 4 + 1] = p_colors[i].g; - color_array[i * 4 + 2] = p_colors[i].b; - color_array[i * 4 + 3] = p_colors[i].a; - if (quad) { - int idx = 2 + i; - if (idx == 4) - idx = 0; - color_array[12 + i * 4 + 0] = p_colors[idx].r; - color_array[12 + i * 4 + 1] = p_colors[idx].g; - color_array[12 + i * 4 + 2] = p_colors[idx].b; - color_array[12 + i * 4 + 3] = p_colors[idx].a; - } - } - } else { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - } - - if (p_tangents) { - glEnableVertexAttribArray(VS::ARRAY_TANGENT); - glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false, 0, tangent_array); - for (int i = 0; i < p_points; i++) { - - tangent_array[i * 4 + 0] = p_tangents[i].normal.x; - tangent_array[i * 4 + 1] = p_tangents[i].normal.y; - tangent_array[i * 4 + 2] = p_tangents[i].normal.z; - tangent_array[i * 4 + 3] = p_tangents[i].d; - if (quad) { - int idx = 2 + i; - if (idx == 4) - idx = 0; - tangent_array[12 + i * 4 + 0] = p_tangents[idx].normal.x; - tangent_array[12 + i * 4 + 1] = p_tangents[idx].normal.y; - tangent_array[12 + i * 4 + 2] = p_tangents[idx].normal.z; - tangent_array[12 + i * 4 + 3] = p_tangents[idx].d; - } - } - } else { - glDisableVertexAttribArray(VS::ARRAY_TANGENT); - } - - if (p_uvs) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, false, 0, uv_array); - for (int i = 0; i < p_points; i++) { - - uv_array[i * 3 + 0] = p_uvs[i].x; - uv_array[i * 3 + 1] = p_uvs[i].y; - uv_array[i * 3 + 2] = p_uvs[i].z; - if (quad) { - int idx = 2 + i; - if (idx == 4) - idx = 0; - uv_array[9 + i * 3 + 0] = p_uvs[idx].x; - uv_array[9 + i * 3 + 1] = p_uvs[idx].y; - uv_array[9 + i * 3 + 2] = p_uvs[idx].z; - } - } - - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - /* - if (p_instanced>1) - glDrawArraysInstanced(type,0,p_points,p_instanced); - else - */ - - glDrawArrays(type, 0, quad ? 6 : p_points); -}; - -/* 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 - -/* TEXTURE API */ - -Ref<Image> RasterizerGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, int &r_gl_components, bool &r_has_alpha_cache, bool &r_compressed) { - - r_has_alpha_cache = false; - r_compressed = false; - r_gl_format = 0; - Ref<Image> image = p_image; - - switch (p_format) { - - case Image::FORMAT_L8: { - r_gl_components = 1; - r_gl_format = GL_LUMINANCE; - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_SLUMINANCE_NV : GL_LUMINANCE; - - } break; - case Image::FORMAT_INTENSITY: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGBA8); - r_gl_components = 4; - r_gl_format = GL_RGBA; - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _GL_SRGB_ALPHA_EXT : GL_RGBA; - r_has_alpha_cache = true; - } break; - case Image::FORMAT_LA8: { - - //image.convert(Image::FORMAT_RGBA8); - r_gl_components = 2; - r_gl_format = GL_LUMINANCE_ALPHA; - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_SLUMINANCE_ALPHA_NV : GL_LUMINANCE_ALPHA; - r_has_alpha_cache = true; - } break; - - case Image::FORMAT_INDEXED: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGB8); - r_gl_components = 3; - r_gl_format = GL_RGB; - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _GL_SRGB_EXT : GL_RGB; - - } break; - - case Image::FORMAT_INDEXED_ALPHA: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGBA8); - r_gl_components = 4; - - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } break; - case Image::FORMAT_RGB8: { - - r_gl_components = 3; - - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_internal_format = _GL_SRGB_EXT; - r_gl_format = GL_RGB; - } else { - r_gl_internal_format = GL_RGB; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGB; - } - } break; - case Image::FORMAT_RGBA8: { - - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - r_gl_format = GL_RGBA; - //r_gl_internal_format=GL_RGBA; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - - r_has_alpha_cache = true; - } break; - case Image::FORMAT_DXT1: { - - if (!s3tc_supported || (!s3tc_srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - - r_gl_components = 1; //doesn't matter much - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; - r_compressed = true; - }; - - } break; - case Image::FORMAT_DXT3: { - - if (!s3tc_supported || (!s3tc_srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - r_gl_components = 1; //doesn't matter much - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; - - r_has_alpha_cache = true; - r_compressed = true; - }; - - } break; - case Image::FORMAT_DXT5: { - - if (!s3tc_supported || (!s3tc_srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - r_gl_components = 1; //doesn't matter much - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; - r_has_alpha_cache = true; - r_compressed = true; - }; - - } break; - case Image::FORMAT_ATI1: { - - if (!latc_supported) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - - r_gl_internal_format = _EXT_COMPRESSED_LUMINANCE_LATC1_EXT; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - }; - - } break; - case Image::FORMAT_ATI2: { - - if (!latc_supported) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - r_gl_internal_format = _EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - }; - } break; - case Image::FORMAT_PVRTC2: { - - if (!pvr_supported || (!pvr_srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_PVRTC2A: { - - if (!pvr_supported || (!pvr_srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - - if (!image.empty()) - image.decompress(); - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - - r_gl_internal_format = _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_PVRTC4: { - - if (!pvr_supported || (!pvr_srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - - if (!image.empty()) - image.decompress(); - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - } else { - - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_PVRTC4A: { - - if (!pvr_supported || (!pvr_srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - - if (!image.empty()) - image.decompress(); - r_gl_components = 4; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGBA; - r_gl_internal_format = _GL_SRGB_ALPHA_EXT; - } else { - r_gl_internal_format = GL_RGBA; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGBA; - } - r_has_alpha_cache = true; - - } else { - r_gl_internal_format = (srgb_supported && p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_ETC: { - - if (!etc_supported || p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 3; - if (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { - - if (srgb_supported) { - r_gl_format = GL_RGB; - r_gl_internal_format = _GL_SRGB_EXT; - } else { - r_gl_internal_format = GL_RGB; - if (!image.empty()) - image.srgb_to_linear(); - } - } else { - r_gl_internal_format = GL_RGB; - } - r_gl_internal_format = GL_RGB; - - } else { - - r_gl_internal_format = _EXT_ETC1_RGB8_OES; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_ATC: { - - if (!atitc_supported) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 3; - r_gl_internal_format = GL_RGB; - - } else { - - r_gl_internal_format = _EXT_ATC_RGB_AMD; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_ATC_ALPHA_EXPLICIT: { - - if (!atitc_supported) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - r_gl_internal_format = GL_RGBA; - - } else { - - r_gl_internal_format = _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_ATC_ALPHA_INTERPOLATED: { - - if (!atitc_supported) { - - if (!image.empty()) { - image.decompress(); - } - r_gl_components = 4; - r_gl_internal_format = GL_RGBA; - - } else { - - r_gl_internal_format = _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD; - r_gl_components = 1; //doesn't matter much - r_compressed = true; - } - - } break; - case Image::FORMAT_YUV_422: - case Image::FORMAT_YUV_444: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGB8); - r_gl_internal_format = GL_RGB; - r_gl_components = 3; - - } break; - - default: { - - ERR_FAIL_V(Image()); - } - } - - if (r_gl_format == 0) { - r_gl_format = r_gl_internal_format; - } - - 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 RasterizerGLES2::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 RasterizerGLES2::texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags) { - - bool has_alpha_cache; - int components; - GLenum format; - GLenum internal_format; - bool compressed; - - int po2_width = nearest_power_of_2(p_width); - int po2_height = nearest_power_of_2(p_height); - - if (p_flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) { - p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video - } - - Texture *texture = texture_owner.get(p_texture); - ERR_FAIL_COND(!texture); - texture->width = p_width; - texture->height = p_height; - texture->format = p_format; - texture->flags = p_flags; - texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; - - _get_gl_image_and_format(Image(), texture->format, texture->flags, format, internal_format, components, has_alpha_cache, compressed); - - bool scale_textures = !compressed && !(p_flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) && (!npo2_textures_available || p_flags & VS::TEXTURE_FLAG_MIPMAPS); - - if (scale_textures) { - texture->alloc_width = po2_width; - texture->alloc_height = po2_height; - //print_line("scale because npo2: "+itos(npo2_textures_available)+" mm: "+itos(p_format&VS::TEXTURE_FLAG_MIPMAPS)+" "+itos(p_mipmap_count) ); - } else { - - texture->alloc_width = texture->width; - texture->alloc_height = texture->height; - }; - - if (!(p_flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) && shrink_textures_x2) { - texture->alloc_height = MAX(1, texture->alloc_height / 2); - texture->alloc_width = MAX(1, texture->alloc_width / 2); - } - - texture->gl_components_cache = components; - texture->gl_format_cache = format; - texture->gl_internal_format_cache = internal_format; - texture->format_has_alpha = has_alpha_cache; - texture->compressed = compressed; - texture->has_alpha = false; //by default it doesn't have alpha unless something with alpha is blitteds - texture->data_size = 0; - texture->mipmaps = 0; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - if (p_flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) { - //prealloc if video - glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, GL_UNSIGNED_BYTE, NULL); - } - - texture->active = true; -} - -void RasterizerGLES2::texture_set_data(RID p_texture, const Image &p_image, VS::CubeMapSide p_cube_side) { - - Texture *texture = texture_owner.get(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.empty()); - - int components; - GLenum format; - GLenum internal_format; - bool alpha; - bool compressed; - - if (keep_copies && !(texture->flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) && !(use_reload_hooks && texture->reloader)) { - texture->image[p_cube_side] = p_image; - } - - Image img = _get_gl_image_and_format(p_image, p_image.get_format(), texture->flags, format, internal_format, components, alpha, compressed); - - if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) { - - 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_INDEXED_ALPHA) { - - img.resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); - } - }; - - if (!(texture->flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha() == Image::ALPHA_BLEND) { - texture->has_alpha = true; - } - - GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_cube_side] : GL_TEXTURE_2D; - - texture->data_size = img.get_data().size(); - PoolVector<uint8_t>::Read read = img.get_data().read(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - texture->ignore_mipmaps = compressed && img.get_mipmaps() == 0; - - if (texture->flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, 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 (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 - } - - bool force_clamp_to_edge = !(texture->flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height) != texture->alloc_height || nearest_power_of_2(texture->alloc_width) != texture->alloc_width); - - if (!force_clamp_to_edge && (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 (use_anisotropic_filter) { - - if (texture->flags & VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { - - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_level); - } else { - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); - } - } - - int mipmaps = (texture->flags & VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps() > 0) ? img.get_mipmaps() + 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); - - //print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h)); - - if (texture->compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glCompressedTexImage2D(blit_target, i, format, w, h, 0, size, &read[ofs]); - - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (texture->flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) { - glTexSubImage2D(blit_target, i, 0, 0, w, h, format, GL_UNSIGNED_BYTE, &read[ofs]); - } else { - glTexImage2D(blit_target, i, internal_format, w, h, 0, format, GL_UNSIGNED_BYTE, &read[ofs]); - } - } - tsize += size; - - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); - } - - _rinfo.texture_mem -= texture->total_data_size; - texture->total_data_size = tsize; - _rinfo.texture_mem += texture->total_data_size; - - //printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem); - - if (texture->flags & VS::TEXTURE_FLAG_MIPMAPS && mipmaps == 1 && !texture->ignore_mipmaps) { - //generate mipmaps if they were requested and the image does not contain them - glGenerateMipmap(texture->target); - } - - texture->mipmaps = mipmaps; - - if (mipmaps > 1) { - - //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmaps-1 ); - assumed to have all, always - } - - //texture_set_flags(p_texture,texture->flags); -} - -Image RasterizerGLES2::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const { - - Texture *texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture, Image()); - ERR_FAIL_COND_V(!texture->active, Image()); - ERR_FAIL_COND_V(texture->data_size == 0, Image()); - ERR_FAIL_COND_V(texture->render_target, Image()); - - return texture->image[p_cube_side]; - -#if 0 - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image()); - ERR_FAIL_COND_V(!texture->active,Image()); - ERR_FAIL_COND_V(texture->data_size==0,Image()); - - PoolVector<uint8_t> data; - GLenum format,type=GL_UNSIGNED_BYTE; - Image::Format fmt; - int pixelsize=0; - int pixelshift=0; - int minw=1,minh=1; - bool compressed=false; - - fmt=texture->format; - - switch(texture->format) { - - case Image::FORMAT_L8: { - - format=GL_LUMINANCE; - type=GL_UNSIGNED_BYTE; - data.resize(texture->alloc_width*texture->alloc_height); - pixelsize=1; - - } break; - case Image::FORMAT_INTENSITY: { - return Image(); - } break; - case Image::FORMAT_LA8: { - - format=GL_LUMINANCE_ALPHA; - type=GL_UNSIGNED_BYTE; - pixelsize=2; - - } break; - case Image::FORMAT_RGB8: { - format=GL_RGB; - type=GL_UNSIGNED_BYTE; - pixelsize=3; - } break; - case Image::FORMAT_RGBA8: { - - format=GL_RGBA; - type=GL_UNSIGNED_BYTE; - pixelsize=4; - } break; - case Image::FORMAT_INDEXED: { - - format=GL_RGB; - type=GL_UNSIGNED_BYTE; - fmt=Image::FORMAT_RGB8; - pixelsize=3; - } break; - case Image::FORMAT_INDEXED_ALPHA: { - - format=GL_RGBA; - type=GL_UNSIGNED_BYTE; - fmt=Image::FORMAT_RGBA8; - pixelsize=4; - - } break; - case Image::FORMAT_DXT1: { - - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - compressed=true; - pixelshift=1; - minw=minh=4; - - } break; - case Image::FORMAT_DXT3: { - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - compressed=true; - minw=minh=4; - - } break; - case Image::FORMAT_DXT5: { - - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - compressed=true; - minw=minh=4; - - } break; - case Image::FORMAT_ATI1: { - - format=GL_COMPRESSED_RED_RGTC1; - pixelsize=1; //doesn't matter much - compressed=true; - pixelshift=1; - minw=minh=4; - - } break; - case Image::FORMAT_ATI2: { - - format=GL_COMPRESSED_RG_RGTC2; - pixelsize=1; //doesn't matter much - compressed=true; - minw=minh=4; - - } break; - - default:{} - } - - data.resize(texture->data_size); - PoolVector<uint8_t>::Write wb = data.write(); - - glActiveTexture(GL_TEXTURE0); - int ofs=0; - glBindTexture(texture->target,texture->tex_id); - - int w=texture->alloc_width; - int h=texture->alloc_height; - for(int i=0;i<texture->mipmaps+1;i++) { - - if (compressed) { - - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetCompressedTexImage(texture->target,i,&wb[ofs]); - - } else { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glGetTexImage(texture->target,i,format,type,&wb[ofs]); - } - - int size = (w*h*pixelsize)>>pixelshift; - ofs+=size; - - w=MAX(minw,w>>1); - h=MAX(minh,h>>1); - - } - - - wb=PoolVector<uint8_t>::Write(); - - Image img(texture->alloc_width,texture->alloc_height,texture->mipmaps,fmt,data); - - if (texture->format<Image::FORMAT_INDEXED && (texture->alloc_width!=texture->width || texture->alloc_height!=texture->height)) - img.resize(texture->width,texture->height); - - return img; -#endif -} - -void RasterizerGLES2::texture_set_flags(RID p_texture, uint32_t p_flags) { - - Texture *texture = texture_owner.get(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; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; - texture->flags = p_flags | cube; // can't remove a cube from being a cube - - bool force_clamp_to_edge = !(p_flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height) != texture->alloc_height || nearest_power_of_2(texture->alloc_width) != texture->alloc_width); - - if (!force_clamp_to_edge && (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 (use_anisotropic_filter) { - - if (texture->flags & VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { - - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 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, 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 (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 RasterizerGLES2::texture_get_flags(RID p_texture) const { - - Texture *texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->flags; -} -Image::Format RasterizerGLES2::texture_get_format(RID p_texture) const { - - Texture *texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture, Image::FORMAT_L8); - - return texture->format; -} -uint32_t RasterizerGLES2::texture_get_width(RID p_texture) const { - - Texture *texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->width; -} -uint32_t RasterizerGLES2::texture_get_height(RID p_texture) const { - - Texture *texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->height; -} - -bool RasterizerGLES2::texture_has_alpha(RID p_texture) const { - - Texture *texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->has_alpha; -} - -void RasterizerGLES2::texture_set_size_override(RID p_texture, int p_width, int p_height) { - - Texture *texture = texture_owner.get(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 RasterizerGLES2::texture_set_reload_hook(RID p_texture, ObjectID p_owner, const StringName &p_function) const { - - Texture *texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->render_target); - - texture->reloader = p_owner; - texture->reloader_func = p_function; - if (use_reload_hooks && p_owner && keep_copies) { - - for (int i = 0; i < 6; i++) - texture->image[i] = Image(); - } -} - -GLuint RasterizerGLES2::_texture_get_name(RID p_tex) { - - Texture *texture = texture_owner.get(p_tex); - ERR_FAIL_COND_V(!texture, 0); - - return texture->tex_id; -}; - -void RasterizerGLES2::texture_set_path(RID p_texture, const String &p_path) { - Texture *texture = texture_owner.get(p_texture); - ERR_FAIL_COND(!texture); - - texture->path = p_path; -} - -String RasterizerGLES2::texture_get_path(RID p_texture) const { - - Texture *texture = texture_owner.get(p_texture); - ERR_FAIL_COND_V(!texture, String()); - return texture->path; -} -void RasterizerGLES2::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.get(E->get()); - if (!t) - continue; - VS::TextureInfo tinfo; - tinfo.path = t->path; - tinfo.format = t->format; - tinfo.size.x = t->alloc_width; - tinfo.size.y = t->alloc_height; - tinfo.bytes = t->total_data_size; - r_info->push_back(tinfo); - } -} - -void RasterizerGLES2::texture_set_shrink_all_x2_on_set_data(bool p_enable) { - - shrink_textures_x2 = p_enable; -} - -/* SHADER API */ - -RID RasterizerGLES2::shader_create(VS::ShaderMode p_mode) { - - Shader *shader = memnew(Shader); - shader->mode = p_mode; - RID rid = shader_owner.make_rid(shader); - shader_set_mode(rid, p_mode); - _shader_make_dirty(shader); - - return rid; -} - -void RasterizerGLES2::shader_set_mode(RID p_shader, VS::ShaderMode p_mode) { - - ERR_FAIL_INDEX(p_mode, 3); - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - if (shader->custom_code_id && p_mode == shader->mode) - return; - - if (shader->custom_code_id) { - - switch (shader->mode) { - case VS::SHADER_MATERIAL: { - material_shader.free_custom_shader(shader->custom_code_id); - } break; - case VS::SHADER_CANVAS_ITEM: { - canvas_shader.free_custom_shader(shader->custom_code_id); - } break; - } - - shader->custom_code_id = 0; - } - - shader->mode = p_mode; - - switch (shader->mode) { - case VS::SHADER_MATERIAL: { - shader->custom_code_id = material_shader.create_custom_shader(); - } break; - case VS::SHADER_CANVAS_ITEM: { - shader->custom_code_id = canvas_shader.create_custom_shader(); - } break; - } - _shader_make_dirty(shader); -} -VS::ShaderMode RasterizerGLES2::shader_get_mode(RID p_shader) const { - - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader, VS::SHADER_MATERIAL); - return shader->mode; -} - -void RasterizerGLES2::shader_set_code(RID p_shader, const String &p_vertex, const String &p_fragment, const String &p_light, int p_vertex_ofs, int p_fragment_ofs, int p_light_ofs) { - - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - -#ifdef DEBUG_ENABLED - if (shader->vertex_code == p_vertex && shader->fragment_code == p_fragment && shader->light_code == p_light) - return; -#endif - shader->fragment_code = p_fragment; - shader->vertex_code = p_vertex; - shader->light_code = p_light; - shader->fragment_line = p_fragment_ofs; - shader->vertex_line = p_vertex_ofs; - shader->light_line = p_light_ofs; - _shader_make_dirty(shader); -} - -String RasterizerGLES2::shader_get_vertex_code(RID p_shader) const { - - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader, String()); - return shader->vertex_code; -} - -String RasterizerGLES2::shader_get_fragment_code(RID p_shader) const { - - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader, String()); - return shader->fragment_code; -} - -String RasterizerGLES2::shader_get_light_code(RID p_shader) const { - - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader, String()); - return shader->light_code; -} - -void RasterizerGLES2::_shader_make_dirty(Shader *p_shader) { - - if (p_shader->dirty_list.in_list()) - return; - - _shader_dirty_list.add(&p_shader->dirty_list); -} - -void RasterizerGLES2::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - - Shader *shader = shader_owner.get(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::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { - - order[E->get().order] = E->key(); - } - - for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { - - PropertyInfo pi; - ShaderLanguage::Uniform &u = shader->uniforms[E->get()]; - pi.name = E->get(); - switch (u.type) { - - case ShaderLanguage::TYPE_VOID: - case ShaderLanguage::TYPE_BOOL: - case ShaderLanguage::TYPE_FLOAT: - case ShaderLanguage::TYPE_VEC2: - case ShaderLanguage::TYPE_VEC3: - case ShaderLanguage::TYPE_MAT3: - case ShaderLanguage::TYPE_MAT4: - case ShaderLanguage::TYPE_VEC4: - pi.type = u.default_value.get_type(); - break; - case ShaderLanguage::TYPE_TEXTURE: - pi.type = Variant::_RID; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture"; - break; - case ShaderLanguage::TYPE_CUBEMAP: - pi.type = Variant::_RID; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "CubeMap"; - break; - }; - - p_param_list->push_back(pi); - } -} - -void RasterizerGLES2::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { - - Shader *shader = shader_owner.get(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 RasterizerGLES2::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { - const Shader *shader = shader_owner.get(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(); -} - -Variant RasterizerGLES2::shader_get_default_param(RID p_shader, const StringName &p_name) { - - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader, Variant()); - - //update shader params if necessary - //make sure the shader is compiled and everything - //so the actual parameters can be properly retrieved! - if (shader->dirty_list.in_list()) { - _update_shader(shader); - } - if (shader->valid && shader->uniforms.has(p_name)) - return shader->uniforms[p_name].default_value; - - return Variant(); -} - -/* COMMON MATERIAL API */ - -RID RasterizerGLES2::material_create() { - - RID material = material_owner.make_rid(memnew(Material)); - return material; -} - -void RasterizerGLES2::material_set_shader(RID p_material, RID p_shader) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - if (material->shader == p_shader) - return; - material->shader = p_shader; - material->shader_version = 0; -} - -RID RasterizerGLES2::material_get_shader(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material, RID()); - return material->shader; -} - -void RasterizerGLES2::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - - Map<StringName, Material::UniformData>::Element *E = material->shader_params.find(p_param); - if (E) { - - if (p_value.get_type() == Variant::NIL) { - - material->shader_params.erase(E); - material->shader_version = 0; //get default! - } else { - E->get().value = p_value; - E->get().inuse = true; - } - } else { - - if (p_value.get_type() == Variant::NIL) - return; - - Material::UniformData ud; - ud.index = -1; - ud.value = p_value; - ud.istexture = p_value.get_type() == Variant::_RID; /// cache it being texture - ud.inuse = true; - material->shader_params[p_param] = ud; //may be got at some point, or erased - } -} -Variant RasterizerGLES2::material_get_param(RID p_material, const StringName &p_param) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material, Variant()); - - if (material->shader.is_valid()) { - //update shader params if necessary - //make sure the shader is compiled and everything - //so the actual parameters can be properly retrieved! - material->shader_cache = shader_owner.get(material->shader); - if (!material->shader_cache) { - //invalidate - material->shader = RID(); - material->shader_cache = NULL; - } else { - - if (material->shader_cache->dirty_list.in_list()) - _update_shader(material->shader_cache); - if (material->shader_cache->valid && material->shader_cache->version != material->shader_version) { - //validate - _update_material_shader_params(material); - } - } - } - - if (material->shader_params.has(p_param) && material->shader_params[p_param].inuse) - return material->shader_params[p_param].value; - else - return Variant(); -} - -void RasterizerGLES2::material_set_flag(RID p_material, VS::MaterialFlag p_flag, bool p_enabled) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - ERR_FAIL_INDEX(p_flag, VS::MATERIAL_FLAG_MAX); - - material->flags[p_flag] = p_enabled; -} -bool RasterizerGLES2::material_get_flag(RID p_material, VS::MaterialFlag p_flag) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material, false); - ERR_FAIL_INDEX_V(p_flag, VS::MATERIAL_FLAG_MAX, false); - return material->flags[p_flag]; -} - -void RasterizerGLES2::material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->depth_draw_mode = p_mode; -} - -VS::MaterialDepthDrawMode RasterizerGLES2::material_get_depth_draw_mode(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material, VS::MATERIAL_DEPTH_DRAW_ALWAYS); - return material->depth_draw_mode; -} - -void RasterizerGLES2::material_set_blend_mode(RID p_material, VS::MaterialBlendMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->blend_mode = p_mode; -} -VS::MaterialBlendMode RasterizerGLES2::material_get_blend_mode(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material, VS::MATERIAL_BLEND_MODE_ADD); - return material->blend_mode; -} - -void RasterizerGLES2::material_set_line_width(RID p_material, float p_line_width) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->line_width = p_line_width; -} -float RasterizerGLES2::material_get_line_width(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material, 0); - - return material->line_width; -} - -/* MESH API */ - -RID RasterizerGLES2::mesh_create() { - - return mesh_owner.make_rid(memnew(Mesh)); -} - -void RasterizerGLES2::mesh_add_surface(RID p_mesh, VS::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, bool p_alpha_sort) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_INDEX(p_primitive, VS::PRIMITIVE_MAX); - ERR_FAIL_COND(p_arrays.size() != VS::ARRAY_MAX); - - uint32_t format = 0; - - // validation - int index_array_len = 0; - int array_len = 0; - - for (int i = 0; i < p_arrays.size(); i++) { - - if (p_arrays[i].get_type() == Variant::NIL) - continue; - - format |= (1 << i); - - if (i == VS::ARRAY_VERTEX) { - - array_len = Vector3Array(p_arrays[i]).size(); - ERR_FAIL_COND(array_len == 0); - } else if (i == VS::ARRAY_INDEX) { - - index_array_len = IntArray(p_arrays[i]).size(); - } - } - - ERR_FAIL_COND((format & VS::ARRAY_FORMAT_VERTEX) == 0); // mandatory - - ERR_FAIL_COND(mesh->morph_target_count != p_blend_shapes.size()); - if (mesh->morph_target_count) { - //validate format for morphs - for (int i = 0; i < p_blend_shapes.size(); i++) { - - uint32_t bsformat = 0; - Array arr = p_blend_shapes[i]; - for (int j = 0; j < arr.size(); j++) { - - if (arr[j].get_type() != Variant::NIL) - bsformat |= (1 << j); - } - - ERR_FAIL_COND((bsformat) != (format & (VS::ARRAY_FORMAT_BONES - 1))); - } - } - - Surface *surface = memnew(Surface); - ERR_FAIL_COND(!surface); - - bool use_VBO = true; //glGenBuffersARB!=NULL; // TODO detect if it's in there - if ((!use_hw_skeleton_xform && format & VS::ARRAY_FORMAT_WEIGHTS) || mesh->morph_target_count > 0) { - - use_VBO = false; - } - - //surface->packed=pack_arrays && use_VBO; - - int total_elem_size = 0; - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - - Surface::ArrayData &ad = surface->array[i]; - ad.size = 0; - ad.ofs = 0; - int elem_size = 0; - int elem_count = 0; - bool valid_local = true; - GLenum datatype; - bool normalize = false; - bool bind = false; - - if (!(format & (1 << i))) // no array - continue; - - switch (i) { - - case VS::ARRAY_VERTEX: { - - if (use_VBO && use_half_float) { - elem_size = 3 * sizeof(int16_t); // vertex - datatype = _GL_HALF_FLOAT_OES; - } else { - - elem_size = 3 * sizeof(GLfloat); // vertex - datatype = GL_FLOAT; - } - bind = true; - elem_count = 3; - - } break; - case VS::ARRAY_NORMAL: { - - if (use_VBO) { - elem_size = 4 * sizeof(int8_t); // vertex - datatype = GL_BYTE; - normalize = true; - } else { - elem_size = 3 * sizeof(GLfloat); // vertex - datatype = GL_FLOAT; - } - bind = true; - elem_count = 3; - } break; - case VS::ARRAY_TANGENT: { - if (use_VBO) { - elem_size = 4 * sizeof(int8_t); // vertex - datatype = GL_BYTE; - normalize = true; - } else { - elem_size = 4 * sizeof(GLfloat); // vertex - datatype = GL_FLOAT; - } - bind = true; - elem_count = 4; - - } break; - case VS::ARRAY_COLOR: { - - elem_size = 4 * sizeof(uint8_t); /* RGBA */ - datatype = GL_UNSIGNED_BYTE; - elem_count = 4; - bind = true; - normalize = true; - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - if (use_VBO && use_half_float) { - elem_size = 2 * sizeof(int16_t); // vertex - datatype = _GL_HALF_FLOAT_OES; - } else { - elem_size = 2 * sizeof(GLfloat); // vertex - datatype = GL_FLOAT; - } - bind = true; - elem_count = 2; - - } break; - case VS::ARRAY_WEIGHTS: { - - if (use_VBO) { - - elem_size = VS::ARRAY_WEIGHTS_SIZE * sizeof(GLushort); - valid_local = false; - bind = true; - normalize = true; - datatype = GL_UNSIGNED_SHORT; - elem_count = 4; - - } else { - elem_size = VS::ARRAY_WEIGHTS_SIZE * sizeof(GLfloat); - valid_local = false; - bind = false; - datatype = GL_FLOAT; - elem_count = 4; - } - - } break; - case VS::ARRAY_BONES: { - - if (use_VBO) { - elem_size = VS::ARRAY_WEIGHTS_SIZE * sizeof(GLubyte); - valid_local = false; - bind = true; - datatype = GL_UNSIGNED_BYTE; - elem_count = 4; - } else { - - elem_size = VS::ARRAY_WEIGHTS_SIZE * sizeof(GLushort); - valid_local = false; - bind = false; - datatype = GL_UNSIGNED_SHORT; - elem_count = 4; - } - - } break; - case VS::ARRAY_INDEX: { - - if (index_array_len <= 0) { - ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); - break; - } - /* determine wether using 16 or 32 bits indices */ - if (array_len > (1 << 16)) { - - elem_size = 4; - datatype = GL_UNSIGNED_INT; - } else { - elem_size = 2; - datatype = GL_UNSIGNED_SHORT; - } - - /* - if (use_VBO) { - - glGenBuffers(1,&surface->index_id); - ERR_FAIL_COND(surface->index_id==0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_len*elem_size,NULL,GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - } else { - surface->index_array_local = (uint8_t*)memalloc(index_array_len*elem_size); - }; -*/ - surface->index_array_len = index_array_len; // only way it can exist - ad.ofs = 0; - ad.size = elem_size; - - continue; - } break; - default: { - ERR_FAIL(); - } - } - - ad.ofs = total_elem_size; - ad.size = elem_size; - ad.datatype = datatype; - ad.normalize = normalize; - ad.bind = bind; - ad.count = elem_count; - total_elem_size += elem_size; - if (valid_local) { - surface->local_stride += elem_size; - surface->morph_format |= (1 << i); - } - } - - surface->stride = total_elem_size; - surface->array_len = array_len; - surface->format = format; - surface->primitive = p_primitive; - surface->morph_target_count = mesh->morph_target_count; - surface->configured_format = 0; - surface->mesh = mesh; - if (keep_copies) { - surface->data = p_arrays; - surface->morph_data = p_blend_shapes; - } - - uint8_t *array_ptr = NULL; - uint8_t *index_array_ptr = NULL; - PoolVector<uint8_t> array_pre_vbo; - PoolVector<uint8_t>::Write vaw; - PoolVector<uint8_t> index_array_pre_vbo; - PoolVector<uint8_t>::Write iaw; - - /* create pointers */ - if (use_VBO) { - - array_pre_vbo.resize(surface->array_len * surface->stride); - vaw = array_pre_vbo.write(); - array_ptr = vaw.ptr(); - - if (surface->index_array_len) { - - index_array_pre_vbo.resize(surface->index_array_len * surface->array[VS::ARRAY_INDEX].size); - iaw = index_array_pre_vbo.write(); - index_array_ptr = iaw.ptr(); - } - - _surface_set_arrays(surface, array_ptr, index_array_ptr, p_arrays, true); - - } else { - - surface->array_local = (uint8_t *)memalloc(surface->array_len * surface->stride); - array_ptr = (uint8_t *)surface->array_local; - if (surface->index_array_len) { - surface->index_array_local = (uint8_t *)memalloc(index_array_len * surface->array[VS::ARRAY_INDEX].size); - index_array_ptr = (uint8_t *)surface->index_array_local; - } - - _surface_set_arrays(surface, array_ptr, index_array_ptr, p_arrays, true); - - if (mesh->morph_target_count) { - - surface->morph_targets_local = memnew_arr(Surface::MorphTarget, mesh->morph_target_count); - for (int i = 0; i < mesh->morph_target_count; i++) { - - surface->morph_targets_local[i].array = memnew_arr(uint8_t, surface->local_stride * surface->array_len); - surface->morph_targets_local[i].configured_format = surface->morph_format; - _surface_set_arrays(surface, surface->morph_targets_local[i].array, NULL, p_blend_shapes[i], false); - } - } - } - - /* create buffers!! */ - if (use_VBO) { - glGenBuffers(1, &surface->vertex_id); - ERR_FAIL_COND(surface->vertex_id == 0); - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - glBufferData(GL_ARRAY_BUFFER, surface->array_len * surface->stride, array_ptr, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - if (surface->index_array_len) { - - glGenBuffers(1, &surface->index_id); - ERR_FAIL_COND(surface->index_id == 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_array_len * surface->array[VS::ARRAY_INDEX].size, index_array_ptr, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind - } - } - - mesh->surfaces.push_back(surface); -} - -Error RasterizerGLES2::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem, uint8_t *p_index_mem, const Array &p_arrays, bool p_main) { - - uint32_t stride = p_main ? p_surface->stride : p_surface->local_stride; - - for (int ai = 0; ai < VS::ARRAY_MAX; ai++) { - if (ai >= p_arrays.size()) - break; - if (p_arrays[ai].get_type() == Variant::NIL) - continue; - Surface::ArrayData &a = p_surface->array[ai]; - - switch (ai) { - - case VS::ARRAY_VERTEX: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<Vector3> array = p_arrays[ai]; - ERR_FAIL_COND_V(array.size() != p_surface->array_len, ERR_INVALID_PARAMETER); - - PoolVector<Vector3>::Read read = array.read(); - const Vector3 *src = read.ptr(); - - // setting vertices means regenerating the AABB - AABB aabb; - - float scale = 1; - - if (p_surface->array[VS::ARRAY_VERTEX].datatype == _GL_HALF_FLOAT_OES) { - - for (int i = 0; i < p_surface->array_len; i++) { - - uint16_t vector[3] = { make_half_float(src[i].x), make_half_float(src[i].y), make_half_float(src[i].z) }; - - copymem(&p_mem[a.ofs + i * stride], vector, a.size); - - if (i == 0) { - - aabb = AABB(src[i], Vector3()); - } else { - - aabb.expand_to(src[i]); - } - } - - } else { - for (int i = 0; i < p_surface->array_len; i++) { - - GLfloat vector[3] = { src[i].x, src[i].y, src[i].z }; - - copymem(&p_mem[a.ofs + i * stride], vector, a.size); - - if (i == 0) { - - aabb = AABB(src[i], Vector3()); - } else { - - aabb.expand_to(src[i]); - } - } - } - - if (p_main) { - p_surface->aabb = aabb; - p_surface->vertex_scale = scale; - } - - } break; - case VS::ARRAY_NORMAL: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<Vector3> array = p_arrays[ai]; - ERR_FAIL_COND_V(array.size() != p_surface->array_len, ERR_INVALID_PARAMETER); - - PoolVector<Vector3>::Read read = array.read(); - const Vector3 *src = read.ptr(); - - // setting vertices means regenerating the AABB - - if (p_surface->array[VS::ARRAY_NORMAL].datatype == GL_BYTE) { - - for (int i = 0; i < p_surface->array_len; i++) { - - GLbyte vector[4] = { - CLAMP(src[i].x * 127, -128, 127), - CLAMP(src[i].y * 127, -128, 127), - CLAMP(src[i].z * 127, -128, 127), - 0, - }; - - copymem(&p_mem[a.ofs + i * stride], vector, a.size); - } - - } else { - for (int i = 0; i < p_surface->array_len; i++) { - - GLfloat vector[3] = { src[i].x, src[i].y, src[i].z }; - copymem(&p_mem[a.ofs + i * stride], vector, a.size); - } - } - - } break; - case VS::ARRAY_TANGENT: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<real_t> array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_surface->array_len * 4, ERR_INVALID_PARAMETER); - - PoolVector<real_t>::Read read = array.read(); - const real_t *src = read.ptr(); - - if (p_surface->array[VS::ARRAY_TANGENT].datatype == GL_BYTE) { - - for (int i = 0; i < p_surface->array_len; i++) { - - GLbyte xyzw[4] = { - CLAMP(src[i * 4 + 0] * 127, -128, 127), - CLAMP(src[i * 4 + 1] * 127, -128, 127), - CLAMP(src[i * 4 + 2] * 127, -128, 127), - CLAMP(src[i * 4 + 3] * 127, -128, 127) - }; - - copymem(&p_mem[a.ofs + i * stride], xyzw, a.size); - } - - } else { - for (int i = 0; i < p_surface->array_len; i++) { - - GLfloat xyzw[4] = { - src[i * 4 + 0], - src[i * 4 + 1], - src[i * 4 + 2], - src[i * 4 + 3] - }; - - copymem(&p_mem[a.ofs + i * stride], xyzw, a.size); - } - } - - } break; - case VS::ARRAY_COLOR: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::COLOR_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<Color> array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_surface->array_len, ERR_INVALID_PARAMETER); - - PoolVector<Color>::Read read = array.read(); - const Color *src = read.ptr(); - bool alpha = false; - - for (int i = 0; i < p_surface->array_len; i++) { - - if (src[i].a < 0.98) // tolerate alpha a bit, for crappy exporters - alpha = true; - - uint8_t colors[4]; - - for (int j = 0; j < 4; j++) { - - colors[j] = CLAMP(int((src[i][j]) * 255.0), 0, 255); - } - - copymem(&p_mem[a.ofs + i * stride], colors, a.size); - } - - if (p_main) - p_surface->has_alpha = alpha; - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::VECTOR2_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<Vector2> array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_surface->array_len, ERR_INVALID_PARAMETER); - - PoolVector<Vector2>::Read read = array.read(); - - const Vector2 *src = read.ptr(); - float scale = 1.0; - - if (p_surface->array[ai].datatype == _GL_HALF_FLOAT_OES) { - - for (int i = 0; i < p_surface->array_len; i++) { - - uint16_t uv[2] = { make_half_float(src[i].x), make_half_float(src[i].y) }; - copymem(&p_mem[a.ofs + i * stride], uv, a.size); - } - - } else { - for (int i = 0; i < p_surface->array_len; i++) { - - GLfloat uv[2] = { src[i].x, src[i].y }; - - copymem(&p_mem[a.ofs + i * stride], uv, a.size); - } - } - - if (p_main) { - - if (ai == VS::ARRAY_TEX_UV) { - - p_surface->uv_scale = scale; - } - if (ai == VS::ARRAY_TEX_UV2) { - - p_surface->uv2_scale = scale; - } - } - - } break; - case VS::ARRAY_WEIGHTS: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<real_t> array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_surface->array_len * VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER); - - PoolVector<real_t>::Read read = array.read(); - - const real_t *src = read.ptr(); - - if (p_surface->array[VS::ARRAY_WEIGHTS].datatype == GL_UNSIGNED_SHORT) { - - for (int i = 0; i < p_surface->array_len; i++) { - - GLushort data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) { - data[j] = CLAMP(src[i * VS::ARRAY_WEIGHTS_SIZE + j] * 65535, 0, 65535); - } - - copymem(&p_mem[a.ofs + i * stride], data, a.size); - } - } else { - - for (int i = 0; i < p_surface->array_len; i++) { - - GLfloat data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) { - data[j] = src[i * VS::ARRAY_WEIGHTS_SIZE + j]; - } - - copymem(&p_mem[a.ofs + i * stride], data, a.size); - } - } - - } break; - case VS::ARRAY_BONES: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<int> array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_surface->array_len * VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER); - - PoolVector<int>::Read read = array.read(); - - const int *src = read.ptr(); - - p_surface->max_bone = 0; - - if (p_surface->array[VS::ARRAY_BONES].datatype == GL_UNSIGNED_BYTE) { - - for (int i = 0; i < p_surface->array_len; i++) { - - GLubyte data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) { - data[j] = CLAMP(src[i * VS::ARRAY_WEIGHTS_SIZE + j], 0, 255); - p_surface->max_bone = MAX(data[j], p_surface->max_bone); - } - - copymem(&p_mem[a.ofs + i * stride], data, a.size); - } - - } else { - for (int i = 0; i < p_surface->array_len; i++) { - - GLushort data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) { - data[j] = src[i * VS::ARRAY_WEIGHTS_SIZE + j]; - p_surface->max_bone = MAX(data[j], p_surface->max_bone); - } - - copymem(&p_mem[a.ofs + i * stride], data, a.size); - } - } - - } break; - case VS::ARRAY_INDEX: { - - ERR_FAIL_COND_V(p_surface->index_array_len <= 0, ERR_INVALID_DATA); - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::INT_ARRAY, ERR_INVALID_PARAMETER); - - PoolVector<int> indices = p_arrays[ai]; - ERR_FAIL_COND_V(indices.size() == 0, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(indices.size() != p_surface->index_array_len, ERR_INVALID_PARAMETER); - - /* determine wether using 16 or 32 bits indices */ - - PoolVector<int>::Read read = indices.read(); - const int *src = read.ptr(); - - for (int i = 0; i < p_surface->index_array_len; i++) { - - if (a.size == 2) { - uint16_t v = src[i]; - - copymem(&p_index_mem[i * a.size], &v, a.size); - } else { - uint32_t v = src[i]; - - copymem(&p_index_mem[i * a.size], &v, a.size); - } - } - - } break; - - default: { ERR_FAIL_V(ERR_INVALID_PARAMETER); } - } - - p_surface->configured_format |= (1 << ai); - } - - if (p_surface->format & VS::ARRAY_FORMAT_BONES) { - //create AABBs for each detected bone - int total_bones = p_surface->max_bone + 1; - if (p_main) { - p_surface->skeleton_bone_aabb.resize(total_bones); - p_surface->skeleton_bone_used.resize(total_bones); - for (int i = 0; i < total_bones; i++) - p_surface->skeleton_bone_used[i] = false; - } - PoolVector<Vector3> vertices = p_arrays[VS::ARRAY_VERTEX]; - PoolVector<int> bones = p_arrays[VS::ARRAY_BONES]; - PoolVector<float> weights = p_arrays[VS::ARRAY_WEIGHTS]; - - bool any_valid = false; - - if (vertices.size() && bones.size() == vertices.size() * 4 && weights.size() == bones.size()) { - //print_line("MAKING SKELETHONG"); - int vs = vertices.size(); - PoolVector<Vector3>::Read rv = vertices.read(); - PoolVector<int>::Read rb = bones.read(); - PoolVector<float>::Read rw = weights.read(); - - Vector<bool> first; - first.resize(total_bones); - for (int i = 0; i < total_bones; i++) { - first[i] = p_main; - } - AABB *bptr = p_surface->skeleton_bone_aabb.ptr(); - bool *fptr = first.ptr(); - bool *usedptr = p_surface->skeleton_bone_used.ptr(); - - for (int i = 0; i < vs; i++) { - - Vector3 v = rv[i]; - for (int j = 0; j < 4; j++) { - - int idx = rb[i * 4 + j]; - float w = rw[i * 4 + j]; - if (w == 0) - continue; //break; - ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA); - - if (fptr[idx]) { - bptr[idx].pos = v; - fptr[idx] = false; - any_valid = true; - } else { - bptr[idx].expand_to(v); - } - usedptr[idx] = true; - } - } - } - - if (p_main && !any_valid) { - - p_surface->skeleton_bone_aabb.clear(); - p_surface->skeleton_bone_used.clear(); - } - } - - return OK; -} - -void RasterizerGLES2::mesh_add_custom_surface(RID p_mesh, const Variant &p_dat) { - - ERR_EXPLAIN("OpenGL Rasterizer does not support custom surfaces. Running on wrong platform?"); - ERR_FAIL(); -} - -Array RasterizerGLES2::mesh_get_surface_arrays(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array()); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(!surface, Array()); - - return surface->data; -} -Array RasterizerGLES2::mesh_get_surface_morph_arrays(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array()); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(!surface, Array()); - - return surface->morph_data; -} - -void RasterizerGLES2::mesh_set_morph_target_count(RID p_mesh, int p_amount) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_COND(mesh->surfaces.size() != 0); - - mesh->morph_target_count = p_amount; -} - -int RasterizerGLES2::mesh_get_morph_target_count(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); - - return mesh->morph_target_count; -} - -void RasterizerGLES2::mesh_set_morph_target_mode(RID p_mesh, VS::MorphTargetMode p_mode) { - - ERR_FAIL_INDEX(p_mode, 2); - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - - mesh->morph_target_mode = p_mode; -} - -VS::MorphTargetMode RasterizerGLES2::mesh_get_morph_target_mode(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::MORPH_MODE_NORMALIZED); - - return mesh->morph_target_mode; -} - -void RasterizerGLES2::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material, bool p_owned) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size()); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND(!surface); - - if (surface->material_owned && surface->material.is_valid()) - free(surface->material); - - surface->material_owned = p_owned; - - surface->material = p_material; -} - -RID RasterizerGLES2::mesh_surface_get_material(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID()); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(!surface, RID()); - - return surface->material; -} - -int RasterizerGLES2::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(!surface, -1); - - return surface->array_len; -} -int RasterizerGLES2::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(!surface, -1); - - return surface->index_array_len; -} -uint32_t RasterizerGLES2::mesh_surface_get_format(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(!surface, 0); - - return surface->format; -} -VS::PrimitiveType RasterizerGLES2::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::PRIMITIVE_POINTS); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_POINTS); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(!surface, VS::PRIMITIVE_POINTS); - - return surface->primitive; -} - -void RasterizerGLES2::mesh_remove_surface(RID p_mesh, int p_index) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_index, mesh->surfaces.size()); - Surface *surface = mesh->surfaces[p_index]; - ERR_FAIL_COND(!surface); - - if (surface->vertex_id) - glDeleteBuffers(1, &surface->vertex_id); - if (surface->index_id) - glDeleteBuffers(1, &surface->index_id); - - if (mesh->morph_target_count) { - for (int i = 0; i < mesh->morph_target_count; i++) - memfree(surface->morph_targets_local[i].array); - memfree(surface->morph_targets_local); - } - - memdelete(mesh->surfaces[p_index]); - mesh->surfaces.remove(p_index); -} -int RasterizerGLES2::mesh_get_surface_count(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); - - return mesh->surfaces.size(); -} - -AABB RasterizerGLES2::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { - - Mesh *mesh = mesh_owner.get(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.get(p_skeleton); - - AABB aabb; - if (sk && sk->bones.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->bones.size(); - ERR_CONTINUE(bs > sbs); - Skeleton::Bone *skb = sk->bones.ptr(); - - bool first = true; - for (int j = 0; j < bs; j++) { - - if (!skused[j]) - continue; - AABB baabb = skb[j].transform_aabb(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 RasterizerGLES2::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - - mesh->custom_aabb = p_aabb; -} - -AABB RasterizerGLES2::mesh_get_custom_aabb(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - - return mesh->custom_aabb; -} -/* MULTIMESH API */ - -RID RasterizerGLES2::multimesh_create() { - - return multimesh_owner.make_rid(memnew(MultiMesh)); -} - -void RasterizerGLES2::multimesh_set_instance_count(RID p_multimesh, int p_count) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - //multimesh->elements.clear(); // make sure to delete everything, so it "fails" in all implementations - - if (use_texture_instancing) { - - if (nearest_power_of_2(p_count) != nearest_power_of_2(multimesh->elements.size())) { - if (multimesh->tex_id) { - glDeleteTextures(1, &multimesh->tex_id); - multimesh->tex_id = 0; - } - - if (p_count) { - - uint32_t po2 = nearest_power_of_2(p_count); - if (po2 & 0xAAAAAAAA) { - //half width - - multimesh->tw = Math::sqrt(po2 * 2); - multimesh->th = multimesh->tw / 2; - } else { - - multimesh->tw = Math::sqrt(po2); - multimesh->th = multimesh->tw; - } - multimesh->tw *= 4; - if (multimesh->th == 0) - multimesh->th = 1; - - glGenTextures(1, &multimesh->tex_id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, multimesh->tex_id); - -#ifdef GLEW_ENABLED - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, multimesh->tw, multimesh->th, 0, GL_RGBA, GL_FLOAT, NULL); -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, multimesh->tw, multimesh->th, 0, GL_RGBA, GL_FLOAT, NULL); -#endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); - //multimesh->pixel_size=1.0/ps; - - glBindTexture(GL_TEXTURE_2D, 0); - } - } - - if (!multimesh->dirty_list.in_list()) { - _multimesh_dirty_list.add(&multimesh->dirty_list); - } - } - - multimesh->elements.resize(p_count); -} -int RasterizerGLES2::multimesh_get_instance_count(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh, -1); - - return multimesh->elements.size(); -} - -void RasterizerGLES2::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->mesh = p_mesh; -} -void RasterizerGLES2::multimesh_set_aabb(RID p_multimesh, const AABB &p_aabb) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->aabb = p_aabb; -} -void RasterizerGLES2::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->elements.size()); - MultiMesh::Element &e = multimesh->elements[p_index]; - - e.matrix[0] = p_transform.basis.elements[0][0]; - e.matrix[1] = p_transform.basis.elements[1][0]; - e.matrix[2] = p_transform.basis.elements[2][0]; - e.matrix[3] = 0; - e.matrix[4] = p_transform.basis.elements[0][1]; - e.matrix[5] = p_transform.basis.elements[1][1]; - e.matrix[6] = p_transform.basis.elements[2][1]; - e.matrix[7] = 0; - e.matrix[8] = p_transform.basis.elements[0][2]; - e.matrix[9] = p_transform.basis.elements[1][2]; - e.matrix[10] = p_transform.basis.elements[2][2]; - e.matrix[11] = 0; - e.matrix[12] = p_transform.origin.x; - e.matrix[13] = p_transform.origin.y; - e.matrix[14] = p_transform.origin.z; - e.matrix[15] = 1; - - if (!multimesh->dirty_list.in_list()) { - _multimesh_dirty_list.add(&multimesh->dirty_list); - } -} -void RasterizerGLES2::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh) - ERR_FAIL_INDEX(p_index, multimesh->elements.size()); - MultiMesh::Element &e = multimesh->elements[p_index]; - e.color[0] = CLAMP(p_color.r * 255, 0, 255); - e.color[1] = CLAMP(p_color.g * 255, 0, 255); - e.color[2] = CLAMP(p_color.b * 255, 0, 255); - e.color[3] = CLAMP(p_color.a * 255, 0, 255); - - if (!multimesh->dirty_list.in_list()) { - _multimesh_dirty_list.add(&multimesh->dirty_list); - } -} - -RID RasterizerGLES2::multimesh_get_mesh(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh, RID()); - - return multimesh->mesh; -} -AABB RasterizerGLES2::multimesh_get_aabb(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh, AABB()); - - return multimesh->aabb; -} - -Transform RasterizerGLES2::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform()); - - ERR_FAIL_INDEX_V(p_index, multimesh->elements.size(), Transform()); - MultiMesh::Element &e = multimesh->elements[p_index]; - - Transform tr; - - tr.basis.elements[0][0] = e.matrix[0]; - tr.basis.elements[1][0] = e.matrix[1]; - tr.basis.elements[2][0] = e.matrix[2]; - tr.basis.elements[0][1] = e.matrix[4]; - tr.basis.elements[1][1] = e.matrix[5]; - tr.basis.elements[2][1] = e.matrix[6]; - tr.basis.elements[0][2] = e.matrix[8]; - tr.basis.elements[1][2] = e.matrix[9]; - tr.basis.elements[2][2] = e.matrix[10]; - tr.origin.x = e.matrix[12]; - tr.origin.y = e.matrix[13]; - tr.origin.z = e.matrix[14]; - - return tr; -} -Color RasterizerGLES2::multimesh_instance_get_color(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->elements.size(), Color()); - MultiMesh::Element &e = multimesh->elements[p_index]; - Color c; - c.r = e.color[0] / 255.0; - c.g = e.color[1] / 255.0; - c.b = e.color[2] / 255.0; - c.a = e.color[3] / 255.0; - - return c; -} - -void RasterizerGLES2::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->visible = p_visible; -} - -int RasterizerGLES2::multimesh_get_visible_instances(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh, -1); - return multimesh->visible; -} - -/* IMMEDIATE API */ - -RID RasterizerGLES2::immediate_create() { - - Immediate *im = memnew(Immediate); - return immediate_owner.make_rid(im); -} - -void RasterizerGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(im->building); - - Immediate::Chunk ic; - ic.texture = p_texture; - ic.primitive = p_rimitive; - im->chunks.push_back(ic); - im->mask = 0; - im->building = true; -} -void RasterizerGLES2::immediate_vertex(RID p_immediate, const Vector3 &p_vertex) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - Immediate::Chunk *c = &im->chunks.back()->get(); - - if (c->vertices.empty() && im->chunks.size() == 1) { - - im->aabb.pos = p_vertex; - im->aabb.size = Vector3(); - } else { - im->aabb.expand_to(p_vertex); - } - - if (im->mask & VS::ARRAY_FORMAT_NORMAL) - c->normals.push_back(chunk_normal); - if (im->mask & VS::ARRAY_FORMAT_TANGENT) - c->tangents.push_back(chunk_tangent); - if (im->mask & VS::ARRAY_FORMAT_COLOR) - c->colors.push_back(chunk_color); - if (im->mask & VS::ARRAY_FORMAT_TEX_UV) - c->uvs.push_back(chunk_uv); - if (im->mask & VS::ARRAY_FORMAT_TEX_UV2) - c->uvs2.push_back(chunk_uv2); - im->mask |= VS::ARRAY_FORMAT_VERTEX; - c->vertices.push_back(p_vertex); -} - -void RasterizerGLES2::immediate_normal(RID p_immediate, const Vector3 &p_normal) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_NORMAL; - chunk_normal = p_normal; -} -void RasterizerGLES2::immediate_tangent(RID p_immediate, const Plane &p_tangent) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_TANGENT; - chunk_tangent = p_tangent; -} -void RasterizerGLES2::immediate_color(RID p_immediate, const Color &p_color) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_COLOR; - chunk_color = p_color; -} -void RasterizerGLES2::immediate_uv(RID p_immediate, const Vector2 &tex_uv) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_TEX_UV; - chunk_uv = tex_uv; -} -void RasterizerGLES2::immediate_uv2(RID p_immediate, const Vector2 &tex_uv) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->mask |= VS::ARRAY_FORMAT_TEX_UV2; - chunk_uv2 = tex_uv; -} - -void RasterizerGLES2::immediate_end(RID p_immediate) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(!im->building); - - im->building = false; -} -void RasterizerGLES2::immediate_clear(RID p_immediate) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - ERR_FAIL_COND(im->building); - - im->chunks.clear(); -} - -AABB RasterizerGLES2::immediate_get_aabb(RID p_immediate) const { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND_V(!im, AABB()); - return im->aabb; -} - -void RasterizerGLES2::immediate_set_material(RID p_immediate, RID p_material) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - im->material = p_material; -} - -RID RasterizerGLES2::immediate_get_material(RID p_immediate) const { - - const Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND_V(!im, RID()); - return im->material; -} - -/* PARTICLES API */ - -RID RasterizerGLES2::particles_create() { - - Particles *particles = memnew(Particles); - ERR_FAIL_COND_V(!particles, RID()); - return particles_owner.make_rid(particles); -} - -void RasterizerGLES2::particles_set_amount(RID p_particles, int p_amount) { - - ERR_FAIL_COND(p_amount < 1); - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.amount = p_amount; -} - -int RasterizerGLES2::particles_get_amount(RID p_particles) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, -1); - return particles->data.amount; -} - -void RasterizerGLES2::particles_set_emitting(RID p_particles, bool p_emitting) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.emitting = p_emitting; -} -bool RasterizerGLES2::particles_is_emitting(RID p_particles) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, false); - return particles->data.emitting; -} - -void RasterizerGLES2::particles_set_visibility_aabb(RID p_particles, const AABB &p_visibility) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.visibility_aabb = p_visibility; -} - -void RasterizerGLES2::particles_set_emission_half_extents(RID p_particles, const Vector3 &p_half_extents) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - - particles->data.emission_half_extents = p_half_extents; -} -Vector3 RasterizerGLES2::particles_get_emission_half_extents(RID p_particles) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, Vector3()); - - return particles->data.emission_half_extents; -} - -void RasterizerGLES2::particles_set_emission_base_velocity(RID p_particles, const Vector3 &p_base_velocity) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - - particles->data.emission_base_velocity = p_base_velocity; -} - -Vector3 RasterizerGLES2::particles_get_emission_base_velocity(RID p_particles) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, Vector3()); - - return particles->data.emission_base_velocity; -} - -void RasterizerGLES2::particles_set_emission_points(RID p_particles, const PoolVector<Vector3> &p_points) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - - particles->data.emission_points = p_points; -} - -PoolVector<Vector3> RasterizerGLES2::particles_get_emission_points(RID p_particles) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, PoolVector<Vector3>()); - - return particles->data.emission_points; -} - -void RasterizerGLES2::particles_set_gravity_normal(RID p_particles, const Vector3 &p_normal) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - - particles->data.gravity_normal = p_normal; -} -Vector3 RasterizerGLES2::particles_get_gravity_normal(RID p_particles) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, Vector3()); - - return particles->data.gravity_normal; -} - -AABB RasterizerGLES2::particles_get_visibility_aabb(RID p_particles) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, AABB()); - return particles->data.visibility_aabb; -} - -void RasterizerGLES2::particles_set_variable(RID p_particles, VS::ParticleVariable p_variable, float p_value) { - - ERR_FAIL_INDEX(p_variable, VS::PARTICLE_VAR_MAX); - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.particle_vars[p_variable] = p_value; -} -float RasterizerGLES2::particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, -1); - return particles->data.particle_vars[p_variable]; -} - -void RasterizerGLES2::particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable, float p_randomness) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.particle_randomness[p_variable] = p_randomness; -} -float RasterizerGLES2::particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, -1); - return particles->data.particle_randomness[p_variable]; -} - -void RasterizerGLES2::particles_set_color_phases(RID p_particles, int p_phases) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND(p_phases < 0 || p_phases > VS::MAX_PARTICLE_COLOR_PHASES); - particles->data.color_phase_count = p_phases; -} -int RasterizerGLES2::particles_get_color_phases(RID p_particles) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, -1); - return particles->data.color_phase_count; -} - -void RasterizerGLES2::particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - if (p_pos < 0.0) - p_pos = 0.0; - if (p_pos > 1.0) - p_pos = 1.0; - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].pos = p_pos; -} -float RasterizerGLES2::particles_get_color_phase_pos(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, -1.0); - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, -1); - return particles->data.color_phases[p_phase].pos; -} - -void RasterizerGLES2::particles_set_color_phase_color(RID p_particles, int p_phase, const Color &p_color) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].color = p_color; - - //update alpha - particles->has_alpha = false; - for (int i = 0; i < VS::MAX_PARTICLE_COLOR_PHASES; i++) { - if (particles->data.color_phases[i].color.a < 0.99) - particles->has_alpha = true; - } -} - -Color RasterizerGLES2::particles_get_color_phase_color(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, Color()); - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, Color()); - return particles->data.color_phases[p_phase].color; -} - -void RasterizerGLES2::particles_set_attractors(RID p_particles, int p_attractors) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND(p_attractors < 0 || p_attractors > VisualServer::MAX_PARTICLE_ATTRACTORS); - particles->data.attractor_count = p_attractors; -} -int RasterizerGLES2::particles_get_attractors(RID p_particles) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, -1); - return particles->data.attractor_count; -} - -void RasterizerGLES2::particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3 &p_pos) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor, particles->data.attractor_count); - particles->data.attractors[p_attractor].pos = p_pos; -} -Vector3 RasterizerGLES2::particles_get_attractor_pos(RID p_particles, int p_attractor) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, Vector3()); - ERR_FAIL_INDEX_V(p_attractor, particles->data.attractor_count, Vector3()); - return particles->data.attractors[p_attractor].pos; -} - -void RasterizerGLES2::particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor, particles->data.attractor_count); - particles->data.attractors[p_attractor].force = p_force; -} - -float RasterizerGLES2::particles_get_attractor_strength(RID p_particles, int p_attractor) const { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, 0); - ERR_FAIL_INDEX_V(p_attractor, particles->data.attractor_count, 0); - return particles->data.attractors[p_attractor].force; -} - -void RasterizerGLES2::particles_set_material(RID p_particles, RID p_material, bool p_owned) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - if (particles->material_owned && particles->material.is_valid()) - free(particles->material); - - particles->material_owned = p_owned; - - particles->material = p_material; -} -RID RasterizerGLES2::particles_get_material(RID p_particles) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, RID()); - return particles->material; -} - -void RasterizerGLES2::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.local_coordinates = p_enable; -} - -bool RasterizerGLES2::particles_is_using_local_coordinates(RID p_particles) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, false); - return particles->data.local_coordinates; -} -bool RasterizerGLES2::particles_has_height_from_velocity(RID p_particles) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, false); - return particles->data.height_from_velocity; -} - -void RasterizerGLES2::particles_set_height_from_velocity(RID p_particles, bool p_enable) { - - Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND(!particles); - particles->data.height_from_velocity = p_enable; -} - -AABB RasterizerGLES2::particles_get_aabb(RID p_particles) const { - - const Particles *particles = particles_owner.get(p_particles); - ERR_FAIL_COND_V(!particles, AABB()); - return particles->data.visibility_aabb; -} - -/* SKELETON API */ - -RID RasterizerGLES2::skeleton_create() { - - Skeleton *skeleton = memnew(Skeleton); - ERR_FAIL_COND_V(!skeleton, RID()); - return skeleton_owner.make_rid(skeleton); -} -void RasterizerGLES2::skeleton_resize(RID p_skeleton, int p_bones) { - - Skeleton *skeleton = skeleton_owner.get(p_skeleton); - ERR_FAIL_COND(!skeleton); - if (p_bones == skeleton->bones.size()) { - return; - }; - if (use_hw_skeleton_xform) { - - if (nearest_power_of_2(p_bones) != nearest_power_of_2(skeleton->bones.size())) { - if (skeleton->tex_id) { - glDeleteTextures(1, &skeleton->tex_id); - skeleton->tex_id = 0; - } - - if (p_bones) { - - glGenTextures(1, &skeleton->tex_id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); - int ps = nearest_power_of_2(p_bones * 3); -#ifdef GLEW_ENABLED - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, ps, 1, 0, GL_RGBA, GL_FLOAT, skel_default.ptr()); -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ps, 1, 0, GL_RGBA, GL_FLOAT, skel_default.ptr()); -#endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); - skeleton->pixel_size = 1.0 / ps; - - glBindTexture(GL_TEXTURE_2D, 0); - } - } - - if (!skeleton->dirty_list.in_list()) { - _skeleton_dirty_list.add(&skeleton->dirty_list); - } - } - skeleton->bones.resize(p_bones); -} -int RasterizerGLES2::skeleton_get_bone_count(RID p_skeleton) const { - - Skeleton *skeleton = skeleton_owner.get(p_skeleton); - ERR_FAIL_COND_V(!skeleton, -1); - return skeleton->bones.size(); -} -void RasterizerGLES2::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) { - - Skeleton *skeleton = skeleton_owner.get(p_skeleton); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->bones.size()); - - Skeleton::Bone &b = skeleton->bones[p_bone]; - - b.mtx[0][0] = p_transform.basis[0][0]; - b.mtx[0][1] = p_transform.basis[1][0]; - b.mtx[0][2] = p_transform.basis[2][0]; - b.mtx[1][0] = p_transform.basis[0][1]; - b.mtx[1][1] = p_transform.basis[1][1]; - b.mtx[1][2] = p_transform.basis[2][1]; - b.mtx[2][0] = p_transform.basis[0][2]; - b.mtx[2][1] = p_transform.basis[1][2]; - b.mtx[2][2] = p_transform.basis[2][2]; - b.mtx[3][0] = p_transform.origin[0]; - b.mtx[3][1] = p_transform.origin[1]; - b.mtx[3][2] = p_transform.origin[2]; - - if (skeleton->tex_id) { - if (!skeleton->dirty_list.in_list()) { - _skeleton_dirty_list.add(&skeleton->dirty_list); - } - } -} - -Transform RasterizerGLES2::skeleton_bone_get_transform(RID p_skeleton, int p_bone) { - - Skeleton *skeleton = skeleton_owner.get(p_skeleton); - ERR_FAIL_COND_V(!skeleton, Transform()); - ERR_FAIL_INDEX_V(p_bone, skeleton->bones.size(), Transform()); - - const Skeleton::Bone &b = skeleton->bones[p_bone]; - - Transform t; - t.basis[0][0] = b.mtx[0][0]; - t.basis[1][0] = b.mtx[0][1]; - t.basis[2][0] = b.mtx[0][2]; - t.basis[0][1] = b.mtx[1][0]; - t.basis[1][1] = b.mtx[1][1]; - t.basis[2][1] = b.mtx[1][2]; - t.basis[0][2] = b.mtx[2][0]; - t.basis[1][2] = b.mtx[2][1]; - t.basis[2][2] = b.mtx[2][2]; - t.origin[0] = b.mtx[3][0]; - t.origin[1] = b.mtx[3][1]; - t.origin[2] = b.mtx[3][2]; - - return t; -} - -/* LIGHT API */ - -RID RasterizerGLES2::light_create(VS::LightType p_type) { - - Light *light = memnew(Light); - light->type = p_type; - return light_owner.make_rid(light); -} - -VS::LightType RasterizerGLES2::light_get_type(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI); - return light->type; -} - -void RasterizerGLES2::light_set_color(RID p_light, VS::LightColor p_type, const Color &p_color) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX(p_type, 3); - light->colors[p_type] = p_color; -} -Color RasterizerGLES2::light_get_color(RID p_light, VS::LightColor p_type) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, Color()); - ERR_FAIL_INDEX_V(p_type, 3, Color()); - return light->colors[p_type]; -} - -void RasterizerGLES2::light_set_shadow(RID p_light, bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->shadow_enabled = p_enabled; -} - -bool RasterizerGLES2::light_has_shadow(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, false); - return light->shadow_enabled; -} - -void RasterizerGLES2::light_set_volumetric(RID p_light, bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->volumetric_enabled = p_enabled; -} -bool RasterizerGLES2::light_is_volumetric(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, false); - return light->volumetric_enabled; -} - -void RasterizerGLES2::light_set_projector(RID p_light, RID p_texture) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->projector = p_texture; -} -RID RasterizerGLES2::light_get_projector(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, RID()); - return light->projector; -} - -void RasterizerGLES2::light_set_var(RID p_light, VS::LightParam p_var, float p_value) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX(p_var, VS::LIGHT_PARAM_MAX); - - light->vars[p_var] = p_value; -} -float RasterizerGLES2::light_get_var(RID p_light, VS::LightParam p_var) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, 0); - - ERR_FAIL_INDEX_V(p_var, VS::LIGHT_PARAM_MAX, 0); - - return light->vars[p_var]; -} - -void RasterizerGLES2::light_set_operator(RID p_light, VS::LightOp p_op){ - -}; - -VS::LightOp RasterizerGLES2::light_get_operator(RID p_light) const { - - return VS::LightOp(); -}; - -void RasterizerGLES2::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - - light->omni_shadow_mode = p_mode; -} -VS::LightOmniShadowMode RasterizerGLES2::light_omni_get_shadow_mode(RID p_light) const { - - const Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_DEFAULT); - - return light->omni_shadow_mode; -} - -void RasterizerGLES2::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - - light->directional_shadow_mode = p_mode; -} - -VS::LightDirectionalShadowMode RasterizerGLES2::light_directional_get_shadow_mode(RID p_light) const { - - const Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); - - return light->directional_shadow_mode; -} - -void RasterizerGLES2::light_directional_set_shadow_param(RID p_light, VS::LightDirectionalShadowParam p_param, float p_value) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - - light->directional_shadow_param[p_param] = p_value; -} - -float RasterizerGLES2::light_directional_get_shadow_param(RID p_light, VS::LightDirectionalShadowParam p_param) const { - - const Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, 0); - return light->directional_shadow_param[p_param]; -} - -AABB RasterizerGLES2::light_get_aabb(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, AABB()); - - switch (light->type) { - - case VS::LIGHT_SPOT: { - - float len = light->vars[VS::LIGHT_PARAM_RADIUS]; - float size = Math::tan(Math::deg2rad(light->vars[VS::LIGHT_PARAM_SPOT_ANGLE])) * len; - return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); - } break; - case VS::LIGHT_OMNI: { - - float r = light->vars[VS::LIGHT_PARAM_RADIUS]; - return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2); - } break; - case VS::LIGHT_DIRECTIONAL: { - - return AABB(); - } break; - default: {} - } - - ERR_FAIL_V(AABB()); -} - -RID RasterizerGLES2::light_instance_create(RID p_light) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, RID()); - - LightInstance *light_instance = memnew(LightInstance); - - light_instance->light = p_light; - light_instance->base = light; - light_instance->last_pass = 0; - - return light_instance_owner.make_rid(light_instance); -} -void RasterizerGLES2::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) { - - LightInstance *lighti = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND(!lighti); - lighti->transform = p_transform; -} - -Rasterizer::ShadowType RasterizerGLES2::light_instance_get_shadow_type(RID p_light_instance, bool p_far) const { - - LightInstance *lighti = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND_V(!lighti, Rasterizer::SHADOW_NONE); - - switch (lighti->base->type) { - - case VS::LIGHT_DIRECTIONAL: { - switch (lighti->base->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { - return SHADOW_ORTHOGONAL; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PERSPECTIVE: { - return SHADOW_PSM; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { - return SHADOW_PSSM; - } break; - } - - } break; - case VS::LIGHT_OMNI: return SHADOW_DUAL_PARABOLOID; break; - case VS::LIGHT_SPOT: return SHADOW_SIMPLE; break; - } - - return Rasterizer::SHADOW_NONE; -} - -int RasterizerGLES2::light_instance_get_shadow_passes(RID p_light_instance) const { - - LightInstance *lighti = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND_V(!lighti, 0); - - if (lighti->base->type == VS::LIGHT_DIRECTIONAL && lighti->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - - return 4; // dp4 - } else if (lighti->base->type == VS::LIGHT_OMNI || (lighti->base->type == VS::LIGHT_DIRECTIONAL && lighti->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS)) { - return 2; // dp - } else - return 1; -} - -bool RasterizerGLES2::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { - - return shadow_filter >= SHADOW_FILTER_ESM; -} - -void RasterizerGLES2::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix &p_camera, const Transform &p_transform, float p_split_near, float p_split_far) { - - LightInstance *lighti = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND(!lighti); - - ERR_FAIL_COND(lighti->base->type != VS::LIGHT_DIRECTIONAL); - //ERR_FAIL_INDEX(p_index,1); - - lighti->custom_projection[p_index] = p_camera; - lighti->custom_transform[p_index] = p_transform; - lighti->shadow_split[p_index] = 1.0 / p_split_far; -#if 0 - if (p_index==0) { - lighti->custom_projection=p_camera; - lighti->custom_transform=p_transform; - //Plane p(0,0,-p_split_far,1); - //p=camera_projection.xform4(p); - //lighti->shadow_split=p.normal.z/p.d; - lighti->shadow_split=1.0/p_split_far; - - //lighti->shadow_split=-p_split_far; - } else { - - lighti->custom_projection2=p_camera; - lighti->custom_transform2=p_transform; - lighti->shadow_split2=p_split_far; - - } -#endif -} - -int RasterizerGLES2::light_instance_get_shadow_size(RID p_light_instance, int p_index) const { - - LightInstance *lighti = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND_V(!lighti, 1); - ERR_FAIL_COND_V(!lighti->near_shadow_buffer, 256); - return lighti->near_shadow_buffer->size / 2; -} - -void RasterizerGLES2::shadow_clear_near() { - - for (int i = 0; i < near_shadow_buffers.size(); i++) { - - if (near_shadow_buffers[i].owner) - near_shadow_buffers[i].owner->clear_near_shadow_buffers(); - } -} - -bool RasterizerGLES2::shadow_allocate_near(RID p_light) { - - if (!use_shadow_mapping || !use_framebuffers) - return false; - - LightInstance *li = light_instance_owner.get(p_light); - ERR_FAIL_COND_V(!li, false); - ERR_FAIL_COND_V(li->near_shadow_buffer, false); - - int skip = 0; - if (framebuffer.active) { - - int sc = framebuffer.scale; - while (sc > 1) { - sc /= 2; - skip++; - } - } - - for (int i = 0; i < near_shadow_buffers.size(); i++) { - - if (skip > 0) { - skip--; - continue; - } - - if (near_shadow_buffers[i].owner != NULL) - continue; - - near_shadow_buffers[i].owner = li; - li->near_shadow_buffer = &near_shadow_buffers[i]; - return true; - } - - return false; -} - -bool RasterizerGLES2::shadow_allocate_far(RID p_light) { - - return false; -} - -/* PARTICLES INSTANCE */ - -RID RasterizerGLES2::particles_instance_create(RID p_particles) { - - ERR_FAIL_COND_V(!particles_owner.owns(p_particles), RID()); - ParticlesInstance *particles_instance = memnew(ParticlesInstance); - ERR_FAIL_COND_V(!particles_instance, RID()); - particles_instance->particles = p_particles; - return particles_instance_owner.make_rid(particles_instance); -} - -void RasterizerGLES2::particles_instance_set_transform(RID p_particles_instance, const Transform &p_transform) { - - ParticlesInstance *particles_instance = particles_instance_owner.get(p_particles_instance); - ERR_FAIL_COND(!particles_instance); - particles_instance->transform = p_transform; -} - -RID RasterizerGLES2::viewport_data_create() { - - ViewportData *vd = memnew(ViewportData); - - glActiveTexture(GL_TEXTURE0); - glGenFramebuffers(1, &vd->lum_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, vd->lum_fbo); - - GLuint format_luminance = use_fp16_fb ? _GL_RG_EXT : GL_RGBA; - GLuint format_luminance_type = use_fp16_fb ? (full_float_fb_supported ? GL_FLOAT : _GL_HALF_FLOAT_OES) : GL_UNSIGNED_BYTE; - GLuint format_luminance_components = use_fp16_fb ? _GL_RG_EXT : GL_RGBA; - - glGenTextures(1, &vd->lum_color); - glBindTexture(GL_TEXTURE_2D, vd->lum_color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); - /* - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - */ - glTexImage2D(GL_TEXTURE_2D, 0, format_luminance, 1, 1, 0, - format_luminance_components, format_luminance_type, NULL); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, vd->lum_color, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); - DEBUG_TEST_ERROR("Viewport Data Init"); - if (status != GL_FRAMEBUFFER_COMPLETE) { - WARN_PRINT("Can't create framebuffer for vd"); - } - - return viewport_data_owner.make_rid(vd); -} - -RID RasterizerGLES2::render_target_create() { - - RenderTarget *rt = memnew(RenderTarget); - rt->fbo = 0; - rt->width = 0; - rt->height = 0; - rt->last_pass = 0; - - Texture *texture = memnew(Texture); - texture->active = false; - texture->total_data_size = 0; - texture->render_target = rt; - texture->ignore_mipmaps = true; - rt->texture_ptr = texture; - rt->texture = texture_owner.make_rid(texture); - rt->texture_ptr->active = false; - return render_target_owner.make_rid(rt); -} -void RasterizerGLES2::render_target_set_size(RID p_render_target, int p_width, int p_height) { - - RenderTarget *rt = render_target_owner.get(p_render_target); - - if (p_width == rt->width && p_height == rt->height) - return; - - if (rt->width != 0 && rt->height != 0) { - - glDeleteFramebuffers(1, &rt->fbo); - glDeleteRenderbuffers(1, &rt->depth); - glDeleteTextures(1, &rt->color); - - rt->fbo = 0; - rt->depth = 0; - rt->color = 0; - rt->width = 0; - rt->height = 0; - rt->texture_ptr->tex_id = 0; - rt->texture_ptr->active = false; - } - - if (p_width == 0 || p_height == 0) - return; - - rt->width = p_width; - rt->height = p_height; - - //fbo - glGenFramebuffers(1, &rt->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); - - //depth - if (!low_memory_2d) { - glGenRenderbuffers(1, &rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); - - glRenderbufferStorage(GL_RENDERBUFFER, use_depth24 ? _DEPTH_COMPONENT24_OES : GL_DEPTH_COMPONENT16, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - } - - //color - glGenTextures(1, &rt->color); - glBindTexture(GL_TEXTURE_2D, rt->color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - if (rt->texture_ptr->flags & VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - 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); - - rt->texture_ptr->tex_id = rt->color; - rt->texture_ptr->active = true; - rt->texture_ptr->width = p_width; - rt->texture_ptr->height = p_height; - -# - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - - glDeleteRenderbuffers(1, &rt->fbo); - glDeleteTextures(1, &rt->depth); - glDeleteTextures(1, &rt->color); - rt->fbo = 0; - rt->width = 0; - rt->height = 0; - rt->color = 0; - rt->depth = 0; - rt->texture_ptr->tex_id = 0; - rt->texture_ptr->active = false; - WARN_PRINT("Could not create framebuffer!!"); - } - - glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); -} - -RID RasterizerGLES2::render_target_get_texture(RID p_render_target) const { - - const RenderTarget *rt = render_target_owner.get(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); - return rt->texture; -} -bool RasterizerGLES2::render_target_renedered_in_frame(RID p_render_target) { - - RenderTarget *rt = render_target_owner.get(p_render_target); - ERR_FAIL_COND_V(!rt, false); - return rt->last_pass == frame; -} - -/* RENDER API */ -/* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - -void RasterizerGLES2::begin_frame() { - - _update_framebuffer(); - - glDepthFunc(GL_LEQUAL); - glFrontFace(GL_CW); - -//fragment_lighting=Globals::get_singleton()->get("rasterizer/use_fragment_lighting"); -#ifdef TOOLS_ENABLED - canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/use_2d_pixel_snap", false)); - shadow_filter = ShadowFilterTechnique(int(ProjectSettings::get_singleton()->get("rasterizer/shadow_filter"))); -#endif - - canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF5, shadow_filter == SHADOW_FILTER_PCF5); - canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF13, shadow_filter == SHADOW_FILTER_PCF13); - canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_ESM, shadow_filter == SHADOW_FILTER_ESM); - - window_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height); - - double time = (OS::get_singleton()->get_ticks_usec() / 1000); // get msec - time /= 1000.0; // make secs - time_delta = time - last_time; - last_time = time; - frame++; - - _rinfo.vertex_count = 0; - _rinfo.object_count = 0; - _rinfo.mat_change_count = 0; - _rinfo.shader_change_count = 0; - _rinfo.ci_draw_commands = 0; - _rinfo.surface_count = 0; - _rinfo.draw_calls = 0; - - _update_fixed_materials(); - while (_shader_dirty_list.first()) { - - _update_shader(_shader_dirty_list.first()->self()); - } - - while (_skeleton_dirty_list.first()) { - - Skeleton *s = _skeleton_dirty_list.first()->self(); - - float *sk_float = (float *)skinned_buffer; - for (int i = 0; i < s->bones.size(); i++) { - - float *m = &sk_float[i * 12]; - const Skeleton::Bone &b = s->bones[i]; - m[0] = b.mtx[0][0]; - m[1] = b.mtx[1][0]; - m[2] = b.mtx[2][0]; - m[3] = b.mtx[3][0]; - - m[4] = b.mtx[0][1]; - m[5] = b.mtx[1][1]; - m[6] = b.mtx[2][1]; - m[7] = b.mtx[3][1]; - - m[8] = b.mtx[0][2]; - m[9] = b.mtx[1][2]; - m[10] = b.mtx[2][2]; - m[11] = b.mtx[3][2]; - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, s->tex_id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nearest_power_of_2(s->bones.size() * 3), 1, GL_RGBA, GL_FLOAT, sk_float); - _skeleton_dirty_list.remove(_skeleton_dirty_list.first()); - } - - while (_multimesh_dirty_list.first()) { - - MultiMesh *s = _multimesh_dirty_list.first()->self(); - - float *sk_float = (float *)skinned_buffer; - for (int i = 0; i < s->elements.size(); i++) { - - float *m = &sk_float[i * 16]; - const float *im = s->elements[i].matrix; - for (int j = 0; j < 16; j++) { - m[j] = im[j]; - } - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, s->tex_id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, s->tw, s->th, GL_RGBA, GL_FLOAT, sk_float); - _multimesh_dirty_list.remove(_multimesh_dirty_list.first()); - } - - draw_next_frame = false; - //material_shader.set_uniform_default(MaterialShaderGLES2::SCREENZ_SCALE, Math::fmod(time, 3600.0)); - /* nehe ?*/ - - //glClearColor(0,0,1,1); - //glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared.. -} - -void RasterizerGLES2::capture_viewport(Image *r_capture) { -#if 0 - PoolVector<uint8_t> pixels; - pixels.resize(viewport.width*viewport.height*3); - PoolVector<uint8_t>::Write w = pixels.write(); -#ifdef GLEW_ENABLED - glReadBuffer(GL_COLOR_ATTACHMENT0); -#endif - glPixelStorei(GL_PACK_ALIGNMENT, 1); - if (current_rt) - glReadPixels( 0, 0, viewport.width, viewport.height,GL_RGB,GL_UNSIGNED_BYTE,w.ptr() ); - else - glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGB,GL_UNSIGNED_BYTE,w.ptr()); - - glPixelStorei(GL_PACK_ALIGNMENT, 4); - - w=PoolVector<uint8_t>::Write(); - - r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGB8,pixels); -#else - - PoolVector<uint8_t> pixels; - pixels.resize(viewport.width * viewport.height * 4); - PoolVector<uint8_t>::Write w = pixels.write(); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - - //uint64_t time = OS::get_singleton()->get_ticks_usec(); - - if (current_rt) { -#ifdef GLEW_ENABLED - glReadBuffer(GL_COLOR_ATTACHMENT0); -#endif - glReadPixels(0, 0, viewport.width, viewport.height, GL_RGBA, GL_UNSIGNED_BYTE, w.ptr()); - } else { - // back? - glReadPixels(viewport.x, window_size.height - (viewport.height + viewport.y), viewport.width, viewport.height, GL_RGBA, GL_UNSIGNED_BYTE, w.ptr()); - } - - bool flip = current_rt == NULL; - - if (flip) { - uint32_t *imgptr = (uint32_t *)w.ptr(); - for (int y = 0; y < (viewport.height / 2); y++) { - - uint32_t *ptr1 = &imgptr[y * viewport.width]; - uint32_t *ptr2 = &imgptr[(viewport.height - y - 1) * viewport.width]; - - for (int x = 0; x < viewport.width; x++) { - - uint32_t tmp = ptr1[x]; - ptr1[x] = ptr2[x]; - ptr2[x] = tmp; - } - } - } - - w = PoolVector<uint8_t>::Write(); - r_capture->create(viewport.width, viewport.height, 0, Image::FORMAT_RGBA8, pixels); -//r_capture->flip_y(); - -#endif -} - -void RasterizerGLES2::clear_viewport(const Color &p_color) { - - if (current_rt || using_canvas_bg) { - - glScissor(0, 0, viewport.width, viewport.height); - } else { - glScissor(viewport.x, window_size.height - (viewport.height + viewport.y), viewport.width, viewport.height); - } - - glEnable(GL_SCISSOR_TEST); - glClearColor(p_color.r, p_color.g, p_color.b, p_color.a); - glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared.. - glDisable(GL_SCISSOR_TEST); -}; - -void RasterizerGLES2::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) { - - if (!p_render_target.is_valid()) { - glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); - current_rt = NULL; - current_rt_vflip = false; - - } else { - RenderTarget *rt = render_target_owner.get(p_render_target); - ERR_FAIL_COND(!rt); - ERR_FAIL_COND(rt->fbo == 0); - glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); - current_rt = rt; - current_rt_transparent = p_transparent_bg; - current_rt_vflip = !p_vflip; - } -} - -void RasterizerGLES2::set_viewport(const VS::ViewportRect &p_viewport) { - - viewport = p_viewport; - //viewport.width/=2; - //viewport.height/=2; - //print_line("viewport: "+itos(p_viewport.x)+","+itos(p_viewport.y)+","+itos(p_viewport.width)+","+itos(p_viewport.height)); - - if (current_rt) { - - glViewport(0, 0, viewport.width, viewport.height); - } else { - glViewport(viewport.x, window_size.height - (viewport.height + viewport.y), viewport.width, viewport.height); - } -} - -void RasterizerGLES2::begin_scene(RID p_viewport_data, RID p_env, VS::ScenarioDebugMode p_debug) { - - current_debug = p_debug; - opaque_render_list.clear(); - alpha_render_list.clear(); - light_instance_count = 0; - current_env = p_env.is_valid() ? environment_owner.get(p_env) : NULL; - scene_pass++; - last_light_id = 0; - directional_light_count = 0; - lights_use_shadow = false; - texscreen_used = false; - current_vd = viewport_data_owner.get(p_viewport_data); - if (current_debug == VS::SCENARIO_DEBUG_WIREFRAME) { -#ifdef GLEW_ENABLED - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -#endif - } - - //set state - - glCullFace(GL_FRONT); - cull_front = true; -}; - -void RasterizerGLES2::begin_shadow_map(RID p_light_instance, int p_shadow_pass) { - - ERR_FAIL_COND(shadow); - shadow = light_instance_owner.get(p_light_instance); - shadow_pass = p_shadow_pass; - ERR_FAIL_COND(!shadow); - - opaque_render_list.clear(); - alpha_render_list.clear(); - //pre_zpass_render_list.clear(); - light_instance_count = 0; - - glCullFace(GL_FRONT); - cull_front = true; -} - -void RasterizerGLES2::set_camera(const Transform &p_world, const CameraMatrix &p_projection, bool p_ortho_hint) { - - camera_transform = p_world; - if (current_rt && current_rt_vflip) { - camera_transform.basis.set_axis(1, -camera_transform.basis.get_axis(1)); - } - camera_transform_inverse = camera_transform.inverse(); - camera_projection = p_projection; - camera_plane = Plane(camera_transform.origin, -camera_transform.basis.get_axis(2)); - camera_z_near = camera_projection.get_z_near(); - camera_z_far = camera_projection.get_z_far(); - camera_projection.get_viewport_size(camera_vp_size.x, camera_vp_size.y); - camera_ortho = p_ortho_hint; -} - -void RasterizerGLES2::add_light(RID p_light_instance) { - -#define LIGHT_FADE_THRESHOLD 0.05 - - ERR_FAIL_COND(light_instance_count >= MAX_SCENE_LIGHTS); - - LightInstance *li = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND(!li); - - switch (li->base->type) { - - case VS::LIGHT_DIRECTIONAL: { - - ERR_FAIL_COND(directional_light_count >= RenderList::MAX_LIGHTS); - directional_lights[directional_light_count++] = li; - - if (li->base->shadow_enabled) { - CameraMatrix bias; - bias.set_light_bias(); - - int passes = light_instance_get_shadow_passes(p_light_instance); - - for (int i = 0; i < passes; i++) { - Transform modelview = Transform(camera_transform_inverse * li->custom_transform[i]).inverse(); - li->shadow_projection[i] = bias * li->custom_projection[i] * modelview; - } - - lights_use_shadow = true; - } - } break; - case VS::LIGHT_OMNI: { - - if (li->base->shadow_enabled) { - li->shadow_projection[0] = Transform(camera_transform_inverse * li->transform).inverse(); - lights_use_shadow = true; - } - } break; - case VS::LIGHT_SPOT: { - - if (li->base->shadow_enabled) { - CameraMatrix bias; - bias.set_light_bias(); - Transform modelview = Transform(camera_transform_inverse * li->transform).inverse(); - li->shadow_projection[0] = bias * li->projection * modelview; - lights_use_shadow = true; - } - } break; - } - - /* make light hash */ - - // actually, not really a hash, but helps to sort the lights - // and avoid recompiling redudant shader versions - - li->last_pass = scene_pass; - li->sort_key = light_instance_count; - - light_instances[light_instance_count++] = li; -} - -void RasterizerGLES2::_update_shader(Shader *p_shader) const { - - _shader_dirty_list.remove(&p_shader->dirty_list); - - p_shader->valid = false; - - p_shader->uniforms.clear(); - Vector<StringName> uniform_names; - - String vertex_code; - String vertex_globals; - ShaderCompilerGLES2::Flags vertex_flags; - ShaderCompilerGLES2::Flags fragment_flags; - ShaderCompilerGLES2::Flags light_flags; - - if (p_shader->mode == VS::SHADER_MATERIAL) { - Error err = shader_precompiler.compile(p_shader->vertex_code, ShaderLanguage::SHADER_MATERIAL_VERTEX, vertex_code, vertex_globals, vertex_flags, &p_shader->uniforms); - if (err) { - return; //invalid - } - } else if (p_shader->mode == VS::SHADER_CANVAS_ITEM) { - - Error err = shader_precompiler.compile(p_shader->vertex_code, ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX, vertex_code, vertex_globals, vertex_flags, &p_shader->uniforms); - if (err) { - return; //invalid - } - } - - //print_line("compiled vertex: "+vertex_code); - //print_line("compiled vertex globals: "+vertex_globals); - - //print_line("UCV: "+itos(p_shader->uniforms.size())); - String fragment_code; - String fragment_globals; - - if (p_shader->mode == VS::SHADER_MATERIAL) { - Error err = shader_precompiler.compile(p_shader->fragment_code, ShaderLanguage::SHADER_MATERIAL_FRAGMENT, fragment_code, fragment_globals, fragment_flags, &p_shader->uniforms); - if (err) { - return; //invalid - } - } else if (p_shader->mode == VS::SHADER_CANVAS_ITEM) { - Error err = shader_precompiler.compile(p_shader->fragment_code, ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT, fragment_code, fragment_globals, fragment_flags, &p_shader->uniforms); - if (err) { - return; //invalid - } - } - - String light_code; - String light_globals; - - if (p_shader->mode == VS::SHADER_MATERIAL) { - - Error err = shader_precompiler.compile(p_shader->light_code, (ShaderLanguage::SHADER_MATERIAL_LIGHT), light_code, light_globals, light_flags, &p_shader->uniforms); - if (err) { - return; //invalid - } - } else if (p_shader->mode == VS::SHADER_CANVAS_ITEM) { - Error err = shader_precompiler.compile(p_shader->light_code, (ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT), light_code, light_globals, light_flags, &p_shader->uniforms); - if (err) { - return; //invalid - } - } - - fragment_globals += light_globals; //both fragment anyway - - //print_line("compiled fragment: "+fragment_code); - //("compiled fragment globals: "+fragment_globals); - - //print_line("UCF: "+itos(p_shader->uniforms.size())); - - int first_tex_index = 0xFFFFF; - p_shader->first_texture = StringName(); - - for (Map<StringName, ShaderLanguage::Uniform>::Element *E = p_shader->uniforms.front(); E; E = E->next()) { - - uniform_names.push_back("_" + String(E->key())); - if (E->get().type == ShaderLanguage::TYPE_TEXTURE && E->get().order < first_tex_index) { - p_shader->first_texture = E->key(); - first_tex_index = E->get().order; - } - } - - bool uses_time = false; - - if (p_shader->mode == VS::SHADER_MATERIAL) { - //print_line("setting code to id.. "+itos(p_shader->custom_code_id)); - Vector<const char *> enablers; - if (fragment_flags.use_color_interp || vertex_flags.use_color_interp) - enablers.push_back("#define ENABLE_COLOR_INTERP\n"); - if (fragment_flags.use_uv_interp || vertex_flags.use_uv_interp) - enablers.push_back("#define ENABLE_UV_INTERP\n"); - if (fragment_flags.use_uv2_interp || vertex_flags.use_uv2_interp) - enablers.push_back("#define ENABLE_UV2_INTERP\n"); - if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp || fragment_flags.uses_normalmap) - enablers.push_back("#define ENABLE_TANGENT_INTERP\n"); - if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) - enablers.push_back("#define ENABLE_VAR1_INTERP\n"); - if (fragment_flags.use_var2_interp || vertex_flags.use_var2_interp) - enablers.push_back("#define ENABLE_VAR2_INTERP\n"); - if (fragment_flags.uses_texscreen) { - enablers.push_back("#define ENABLE_TEXSCREEN\n"); - } - if (fragment_flags.uses_screen_uv) { - enablers.push_back("#define ENABLE_SCREEN_UV\n"); - } - if (fragment_flags.uses_discard) { - enablers.push_back("#define ENABLE_DISCARD\n"); - } - if (fragment_flags.uses_normalmap) { - enablers.push_back("#define ENABLE_NORMALMAP\n"); - } - if (light_flags.uses_light) { - enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); - } - if (light_flags.uses_shadow_color) { - enablers.push_back("#define USE_OUTPUT_SHADOW_COLOR\n"); - } - if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { - enablers.push_back("#define USE_TIME\n"); - uses_time = true; - } - if (vertex_flags.vertex_code_writes_position) { - enablers.push_back("#define VERTEX_SHADER_WRITE_POSITION\n"); - } - - material_shader.set_custom_shader_code(p_shader->custom_code_id, vertex_code, vertex_globals, fragment_code, light_code, fragment_globals, uniform_names, enablers); - } else if (p_shader->mode == VS::SHADER_CANVAS_ITEM) { - - Vector<const char *> enablers; - - if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { - enablers.push_back("#define USE_TIME\n"); - uses_time = true; - } - if (fragment_flags.uses_normal) { - enablers.push_back("#define NORMAL_USED\n"); - } - if (fragment_flags.uses_normalmap) { - enablers.push_back("#define USE_NORMALMAP\n"); - } - - if (light_flags.uses_light) { - enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); - } - if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) - enablers.push_back("#define ENABLE_VAR1_INTERP\n"); - if (fragment_flags.use_var2_interp || vertex_flags.use_var2_interp) - enablers.push_back("#define ENABLE_VAR2_INTERP\n"); - if (fragment_flags.uses_texscreen) { - enablers.push_back("#define ENABLE_TEXSCREEN\n"); - } - if (fragment_flags.uses_screen_uv) { - enablers.push_back("#define ENABLE_SCREEN_UV\n"); - } - if (fragment_flags.uses_texpixel_size) { - enablers.push_back("#define USE_TEXPIXEL_SIZE\n"); - } - if (light_flags.uses_shadow_color) { - enablers.push_back("#define USE_OUTPUT_SHADOW_COLOR\n"); - } - - if (vertex_flags.uses_worldvec) { - enablers.push_back("#define USE_WORLD_VEC\n"); - } - canvas_shader.set_custom_shader_code(p_shader->custom_code_id, vertex_code, vertex_globals, fragment_code, light_code, fragment_globals, uniform_names, enablers); - - //postprocess_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names); - } - - p_shader->valid = true; - p_shader->has_alpha = fragment_flags.uses_alpha || fragment_flags.uses_texscreen; - p_shader->writes_vertex = vertex_flags.vertex_code_writes_vertex; - p_shader->uses_discard = fragment_flags.uses_discard; - p_shader->has_texscreen = fragment_flags.uses_texscreen; - p_shader->has_screen_uv = fragment_flags.uses_screen_uv; - p_shader->can_zpass = !fragment_flags.uses_discard && !vertex_flags.vertex_code_writes_vertex; - p_shader->uses_normal = fragment_flags.uses_normal || light_flags.uses_normal; - p_shader->uses_time = uses_time; - p_shader->uses_texpixel_size = fragment_flags.uses_texpixel_size; - p_shader->version++; -} - -void RasterizerGLES2::_add_geometry(const Geometry *p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner, int p_material) { - - 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); - -#ifdef DEBUG_ENABLED - if (current_debug == VS::SCENARIO_DEBUG_OVERDRAW) { - m_src = overdraw_material; - } - -#endif - - if (m_src) - m = material_owner.get(m_src); - - if (!m) { - m = material_owner.get(default_material); - } - - ERR_FAIL_COND(!m); - - if (m->last_pass != frame) { - - if (m->shader.is_valid()) { - - m->shader_cache = shader_owner.get(m->shader); - if (m->shader_cache) { - - if (!m->shader_cache->valid) { - m->shader_cache = NULL; - } else { - if (m->shader_cache->has_texscreen) - texscreen_used = true; - } - } else { - m->shader = RID(); - } - - } else { - m->shader_cache = NULL; - } - - m->last_pass = frame; - } - - RenderList *render_list = NULL; - - bool has_base_alpha = (m->shader_cache && m->shader_cache->has_alpha); - bool has_blend_alpha = m->blend_mode != VS::MATERIAL_BLEND_MODE_MIX || m->flags[VS::MATERIAL_FLAG_ONTOP]; - bool has_alpha = has_base_alpha || has_blend_alpha; - - if (shadow) { - - if (has_blend_alpha || (has_base_alpha && m->depth_draw_mode != VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) - return; //bye - - if (!m->shader_cache || (!m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && m->depth_draw_mode != VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) { - //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) - m = shadow_mat_double_sided_ptr; - else - m = shadow_mat_ptr; - if (m->last_pass != frame) { - - if (m->shader.is_valid()) { - - m->shader_cache = shader_owner.get(m->shader); - if (m->shader_cache) { - - if (!m->shader_cache->valid) - m->shader_cache = NULL; - } else { - m->shader = RID(); - } - - } else { - m->shader_cache = NULL; - } - - m->last_pass = frame; - } - } - - render_list = &opaque_render_list; - /* notyet - if (!m->shader_cache || m->shader_cache->can_zpass) - render_list = &alpha_render_list; - } else { - render_list = &opaque_render_list; - }*/ - - } else { - if (has_alpha) { - render_list = &alpha_render_list; - } else { - render_list = &opaque_render_list; - } - } - - RenderList::Element *e = render_list->add_element(); - - if (!e) - return; - - e->geometry = p_geometry; - e->geometry_cmp = p_geometry_cmp; - e->material = m; - e->instance = p_instance; - if (camera_ortho) { - e->depth = camera_plane.distance_to(p_instance->transform.origin); - } else { - e->depth = camera_transform.origin.distance_to(p_instance->transform.origin); - } - e->owner = p_owner; - e->light_type = 0; - e->additive = false; - e->additive_ptr = &e->additive; - e->sort_flags = 0; - - if (p_instance->skeleton.is_valid()) { - e->skeleton = skeleton_owner.get(p_instance->skeleton); - if (!e->skeleton) - const_cast<InstanceData *>(p_instance)->skeleton = RID(); - else - e->sort_flags |= RenderList::SORT_FLAG_SKELETON; - } else { - e->skeleton = NULL; - } - - if (e->geometry->type == Geometry::GEOMETRY_MULTISURFACE) - e->sort_flags |= RenderList::SORT_FLAG_INSTANCING; - - e->mirror = p_instance->mirror; - if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES]) - e->mirror = !e->mirror; - - //e->light_type=0xFF; // no lights! - e->light_type = 3; //light type 3 is no light? - e->light = 0xFFFF; - - if (!shadow && !has_blend_alpha && has_alpha && m->depth_draw_mode == VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA) { - - //if nothing exists, add this element as opaque too - RenderList::Element *oe = opaque_render_list.add_element(); - - if (!oe) - return; - - memcpy(oe, e, sizeof(RenderList::Element)); - oe->additive_ptr = &oe->additive; - } - - if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED] || current_debug == VS::SCENARIO_DEBUG_SHADELESS) { - - e->light_type = 0x7F; //unshaded is zero - } else { - - bool duplicate = false; - - for (int i = 0; i < directional_light_count; i++) { - uint16_t sort_key = directional_lights[i]->sort_key; - uint8_t light_type = VS::LIGHT_DIRECTIONAL; - if (directional_lights[i]->base->shadow_enabled) { - light_type |= 0x8; - if (directional_lights[i]->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) - light_type |= 0x10; - else if (directional_lights[i]->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) - light_type |= 0x30; - } - - RenderList::Element *ec; - if (duplicate) { - - ec = render_list->add_element(); - memcpy(ec, e, sizeof(RenderList::Element)); - } else { - - ec = e; - duplicate = true; - } - - ec->light_type = light_type; - ec->light = sort_key; - ec->additive_ptr = &e->additive; - } - - const RID *liptr = p_instance->light_instances.ptr(); - int ilc = p_instance->light_instances.size(); - - for (int i = 0; i < ilc; i++) { - - LightInstance *li = light_instance_owner.get(liptr[i]); - if (!li || li->last_pass != scene_pass) //lit by light not in visible scene - continue; - uint8_t light_type = li->base->type | 0x40; //penalty to ensure directionals always go first - if (li->base->shadow_enabled) { - light_type |= 0x8; - } - uint16_t sort_key = li->sort_key; - - RenderList::Element *ec; - if (duplicate) { - - ec = render_list->add_element(); - memcpy(ec, e, sizeof(RenderList::Element)); - } else { - - duplicate = true; - ec = e; - } - - ec->light_type = light_type; - ec->light = sort_key; - ec->additive_ptr = &e->additive; - } - } - - DEBUG_TEST_ERROR("Add Geometry"); -} - -void RasterizerGLES2::add_mesh(const RID &p_mesh, const InstanceData *p_data) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - - int ssize = mesh->surfaces.size(); - - for (int i = 0; i < ssize; i++) { - - int mat_idx = p_data->materials[i].is_valid() ? i : -1; - Surface *s = mesh->surfaces[i]; - _add_geometry(s, p_data, s, NULL, mat_idx); - } - - mesh->last_pass = frame; -} - -void RasterizerGLES2::add_multimesh(const RID &p_multimesh, const InstanceData *p_data) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (!multimesh->mesh.is_valid()) - return; - if (multimesh->elements.empty()) - return; - - Mesh *mesh = mesh_owner.get(multimesh->mesh); - ERR_FAIL_COND(!mesh); - - int surf_count = mesh->surfaces.size(); - if (multimesh->last_pass != scene_pass) { - - multimesh->cache_surfaces.resize(surf_count); - for (int i = 0; i < surf_count; i++) { - - multimesh->cache_surfaces[i].material = mesh->surfaces[i]->material; - multimesh->cache_surfaces[i].has_alpha = mesh->surfaces[i]->has_alpha; - multimesh->cache_surfaces[i].surface = mesh->surfaces[i]; - } - - multimesh->last_pass = scene_pass; - } - - for (int i = 0; i < surf_count; i++) { - - _add_geometry(&multimesh->cache_surfaces[i], p_data, multimesh->cache_surfaces[i].surface, multimesh); - } -} - -void RasterizerGLES2::add_immediate(const RID &p_immediate, const InstanceData *p_data) { - - Immediate *immediate = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!immediate); - - _add_geometry(immediate, p_data, immediate, NULL); -} - -void RasterizerGLES2::add_particles(const RID &p_particle_instance, const InstanceData *p_data) { - - //print_line("adding particles"); - ParticlesInstance *particles_instance = particles_instance_owner.get(p_particle_instance); - ERR_FAIL_COND(!particles_instance); - Particles *p = particles_owner.get(particles_instance->particles); - ERR_FAIL_COND(!p); - - _add_geometry(p, p_data, p, particles_instance); - draw_next_frame = true; -} - -Color RasterizerGLES2::_convert_color(const Color &p_color) { - - if (current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]) - return p_color.to_linear(); - else - return p_color; -} - -void RasterizerGLES2::_set_cull(bool p_front, bool p_reverse_cull) { - - bool front = p_front; - if (p_reverse_cull) - front = !front; - - if (front != cull_front) { - - glCullFace(front ? GL_FRONT : GL_BACK); - cull_front = front; - } -} - -_FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_material) const { - - Map<StringName, Material::UniformData> old_mparams = p_material->shader_params; - Map<StringName, Material::UniformData> &mparams = p_material->shader_params; - mparams.clear(); - int idx = 0; - for (Map<StringName, ShaderLanguage::Uniform>::Element *E = p_material->shader_cache->uniforms.front(); E; E = E->next()) { - - Material::UniformData ud; - - bool keep = true; //keep material value - - Map<StringName, Material::UniformData>::Element *OLD = old_mparams.find(E->key()); - bool has_old = OLD; - bool old_inuse = has_old && old_mparams[E->key()].inuse; - - ud.istexture = (E->get().type == ShaderLanguage::TYPE_TEXTURE || E->get().type == ShaderLanguage::TYPE_CUBEMAP); - - if (!has_old || !old_inuse) { - keep = false; - } else if (OLD->get().value.get_type() != E->value().default_value.get_type()) { - - if (OLD->get().value.get_type() == Variant::INT && E->get().type == ShaderLanguage::TYPE_FLOAT) { - //handle common mistake using shaders (feeding ints instead of float) - OLD->get().value = float(OLD->get().value); - keep = true; - } else if (!ud.istexture && E->value().default_value.get_type() != Variant::NIL) { - - keep = false; - } - //type changed between old and new - /* if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { - if (E->value().default_value.get_type()!=Variant::_RID) //hackfor textures - keep=false; - } else if (!old_mparams[E->key()].value.is_num() || !E->value().default_value.get_type()) - keep=false;*/ - - //value is invalid because type differs and default is not null - ; - } - - if (keep) { - ud.value = old_mparams[E->key()].value; - - //print_line("KEEP: "+String(E->key())); - } else { - if (ud.istexture && p_material->shader_cache->default_textures.has(E->key())) - ud.value = p_material->shader_cache->default_textures[E->key()]; - else - ud.value = E->value().default_value; - old_inuse = false; //if reverted to default, obviously did not work - - /* - print_line("NEW: "+String(E->key())+" because: hasold-"+itos(old_mparams.has(E->key()))); - if (old_mparams.has(E->key())) - print_line(" told "+Variant::get_type_name(old_mparams[E->key()].value.get_type())+" tnew "+Variant::get_type_name(E->value().default_value.get_type())); - */ - } - - ud.index = idx++; - ud.inuse = old_inuse; - mparams[E->key()] = ud; - } - - p_material->shader_version = p_material->shader_cache->version; -} - -bool RasterizerGLES2::_setup_material(const Geometry *p_geometry, const Material *p_material, bool p_no_const_light, bool p_opaque_pass) { - - if (p_material->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED]) { - glDisable(GL_CULL_FACE); - } else { - glEnable(GL_CULL_FACE); - } - - //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - - /* - if (p_material->flags[VS::MATERIAL_FLAG_WIREFRAME]) - glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - else - glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); - */ - - if (p_material->line_width) - glLineWidth(p_material->line_width); - - //all goes to false by default - material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PASS, shadow != NULL); - material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF, shadow_filter == SHADOW_FILTER_PCF5 || shadow_filter == SHADOW_FILTER_PCF13); - material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ, shadow_filter == SHADOW_FILTER_PCF13); - material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM, shadow_filter == SHADOW_FILTER_ESM); - material_shader.set_conditional(MaterialShaderGLES2::USE_LIGHTMAP_ON_UV2, p_material->flags[VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2]); - material_shader.set_conditional(MaterialShaderGLES2::USE_COLOR_ATTRIB_SRGB_TO_LINEAR, p_material->flags[VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB] && current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); - - if (p_opaque_pass && p_material->depth_draw_mode == VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA && p_material->shader_cache && p_material->shader_cache->has_alpha) { - - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA, true); - } else { - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA, false); - } - - if (!shadow) { - - bool depth_test = !p_material->flags[VS::MATERIAL_FLAG_ONTOP]; - bool depth_write = p_material->depth_draw_mode != VS::MATERIAL_DEPTH_DRAW_NEVER && (p_opaque_pass || p_material->depth_draw_mode == VS::MATERIAL_DEPTH_DRAW_ALWAYS); - //bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW] && (p_opaque_pass || !p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]); - - if (current_depth_mask != depth_write) { - current_depth_mask = depth_write; - glDepthMask(depth_write); - } - - if (current_depth_test != depth_test) { - - current_depth_test = depth_test; - if (depth_test) - glEnable(GL_DEPTH_TEST); - else - glDisable(GL_DEPTH_TEST); - } - - material_shader.set_conditional(MaterialShaderGLES2::USE_FOG, current_env && current_env->fx_enabled[VS::ENV_FX_FOG]); - //glDepthMask( true ); - } - - DEBUG_TEST_ERROR("Pre Shader Bind"); - - bool rebind = false; - - if (p_material->shader_cache && p_material->shader_cache->valid) { - - /* - // reduce amount of conditional compilations - for(int i=0;i<_tex_version_count;i++) - material_shader.set_conditional((MaterialShaderGLES2::Conditionals)_tex_version[i],false); - */ - - //material_shader.set_custom_shader(p_material->shader_cache->custom_code_id); - - if (p_material->shader_version != p_material->shader_cache->version) { - //shader changed somehow, must update uniforms - - _update_material_shader_params((Material *)p_material); - } - material_shader.set_custom_shader(p_material->shader_cache->custom_code_id); - rebind = material_shader.bind(); - - DEBUG_TEST_ERROR("Shader Bind"); - - //set uniforms! - int texcoord = 0; - for (Map<StringName, Material::UniformData>::Element *E = p_material->shader_params.front(); E; E = E->next()) { - - if (E->get().index < 0) - continue; - //print_line(String(E->key())+": "+E->get().value); - if (E->get().istexture) { - //clearly a texture.. - RID rid = E->get().value; - int loc = material_shader.get_custom_uniform_location(E->get().index); //should be automatic.. - - Texture *t = NULL; - if (rid.is_valid()) { - - t = texture_owner.get(rid); - if (!t) { - E->get().value = RID(); //nullify, invalid texture - rid = RID(); - } - } - - glActiveTexture(GL_TEXTURE0 + texcoord); - glUniform1i(loc, texcoord); //TODO - this could happen automatically on compile... - if (t) { - if (t->render_target) - t->render_target->last_pass = frame; - if (E->key() == p_material->shader_cache->first_texture) { - tc0_idx = texcoord; - tc0_id_cache = t->tex_id; - } - glBindTexture(t->target, t->tex_id); - } else - glBindTexture(GL_TEXTURE_2D, white_tex); //no texture - texcoord++; - - } else if (E->get().value.get_type() == Variant::COLOR) { - Color c = E->get().value; - material_shader.set_custom_uniform(E->get().index, _convert_color(c)); - } else { - material_shader.set_custom_uniform(E->get().index, E->get().value); - } - } - - if (p_material->shader_cache->has_texscreen && framebuffer.active) { - material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_MULT, Vector2(float(viewport.width) / framebuffer.width, float(viewport.height) / framebuffer.height)); - material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_CLAMP, Color(0, 0, float(viewport.width) / framebuffer.width, float(viewport.height) / framebuffer.height)); - material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_TEX, texcoord); - glActiveTexture(GL_TEXTURE0 + texcoord); - glBindTexture(GL_TEXTURE_2D, framebuffer.sample_color); - } - if (p_material->shader_cache->has_screen_uv) { - material_shader.set_uniform(MaterialShaderGLES2::SCREEN_UV_MULT, Vector2(1.0 / viewport.width, 1.0 / viewport.height)); - } - DEBUG_TEST_ERROR("Material arameters"); - - if (p_material->shader_cache->uses_time) { - material_shader.set_uniform(MaterialShaderGLES2::TIME, Math::fmod(last_time, shader_time_rollback)); - draw_next_frame = true; - } - //if uses TIME - draw_next_frame=true - - } else { - - material_shader.set_custom_shader(0); - rebind = material_shader.bind(); - - DEBUG_TEST_ERROR("Shader bind2"); - } - - if (shadow) { - - float zofs = shadow->base->vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]; - float zslope = shadow->base->vars[VS::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE]; - if (shadow_pass >= 1 && shadow->base->type == VS::LIGHT_DIRECTIONAL) { - float m = Math::pow(shadow->base->directional_shadow_param[VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_ZOFFSET_SCALE], shadow_pass); - zofs *= m; - zslope *= m; - } - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_Z_OFFSET, zofs); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_Z_SLOPE_SCALE, zslope); - if (shadow->base->type == VS::LIGHT_OMNI) - material_shader.set_uniform(MaterialShaderGLES2::DUAL_PARABOLOID, shadow->dp); - DEBUG_TEST_ERROR("Shadow uniforms"); - } - - if (current_env && current_env->fx_enabled[VS::ENV_FX_FOG]) { - - Color col_begin = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]; - Color col_end = current_env->fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]; - col_begin = _convert_color(col_begin); - col_end = _convert_color(col_end); - float from = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]; - float zf = camera_z_far; - float curve = current_env->fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]; - material_shader.set_uniform(MaterialShaderGLES2::FOG_PARAMS, Vector3(from, zf, curve)); - material_shader.set_uniform(MaterialShaderGLES2::FOG_COLOR_BEGIN, Vector3(col_begin.r, col_begin.g, col_begin.b)); - material_shader.set_uniform(MaterialShaderGLES2::FOG_COLOR_END, Vector3(col_end.r, col_end.g, col_end.b)); - } - - //material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,300.0)); - //if uses TIME - draw_next_frame=true - - return rebind; -} - -void RasterizerGLES2::_setup_light(uint16_t p_light) { - - if (shadow) - return; - - if (p_light == 0xFFFF) - return; - - enum { - VL_LIGHT_POS, - VL_LIGHT_DIR, - VL_LIGHT_ATTENUATION, - VL_LIGHT_SPOT_ATTENUATION, - VL_LIGHT_DIFFUSE, - VL_LIGHT_SPECULAR, - VL_LIGHT_MAX - }; - - static const MaterialShaderGLES2::Uniforms light_uniforms[VL_LIGHT_MAX] = { - MaterialShaderGLES2::LIGHT_POS, - MaterialShaderGLES2::LIGHT_DIRECTION, - MaterialShaderGLES2::LIGHT_ATTENUATION, - MaterialShaderGLES2::LIGHT_SPOT_ATTENUATION, - MaterialShaderGLES2::LIGHT_DIFFUSE, - MaterialShaderGLES2::LIGHT_SPECULAR, - }; - - GLfloat light_data[VL_LIGHT_MAX][3]; - memset(light_data, 0, (VL_LIGHT_MAX)*3 * sizeof(GLfloat)); - - LightInstance *li = light_instances[p_light]; - Light *l = li->base; - - Color col_diffuse = _convert_color(l->colors[VS::LIGHT_COLOR_DIFFUSE]); - Color col_specular = _convert_color(l->colors[VS::LIGHT_COLOR_SPECULAR]); - - for (int j = 0; j < 3; j++) { - light_data[VL_LIGHT_DIFFUSE][j] = col_diffuse[j]; - light_data[VL_LIGHT_SPECULAR][j] = col_specular[j]; - } - - if (l->type != VS::LIGHT_OMNI) { - - Vector3 dir = -li->transform.get_basis().get_axis(2); - dir = camera_transform_inverse.basis.xform(dir).normalized(); - for (int j = 0; j < 3; j++) - light_data[VL_LIGHT_DIR][j] = dir[j]; - } - - if (l->type != VS::LIGHT_DIRECTIONAL) { - - Vector3 pos = li->transform.get_origin(); - pos = camera_transform_inverse.xform(pos); - for (int j = 0; j < 3; j++) - light_data[VL_LIGHT_POS][j] = pos[j]; - } - - if (li->near_shadow_buffer) { - - glActiveTexture(GL_TEXTURE0 + max_texture_units - 1); - glBindTexture(GL_TEXTURE_2D, li->near_shadow_buffer->depth); - - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX, li->shadow_projection[0]); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE, Vector2(1.0, 1.0) / li->near_shadow_buffer->size); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE, max_texture_units - 1); - if (shadow_filter == SHADOW_FILTER_ESM) - material_shader.set_uniform(MaterialShaderGLES2::ESM_MULTIPLIER, float(li->base->vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER])); - - if (li->base->type == VS::LIGHT_DIRECTIONAL) { - - if (li->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX2, li->shadow_projection[1]); - material_shader.set_uniform(MaterialShaderGLES2::LIGHT_PSSM_SPLIT, Vector3(li->shadow_split[0], li->shadow_split[1], li->shadow_split[2])); - } else if (li->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX2, li->shadow_projection[1]); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX3, li->shadow_projection[2]); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX4, li->shadow_projection[3]); - material_shader.set_uniform(MaterialShaderGLES2::LIGHT_PSSM_SPLIT, Vector3(li->shadow_split[0], li->shadow_split[1], li->shadow_split[2])); - } - //print_line("shadow split: "+rtos(li->shadow_split)); - } - - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_DARKENING, li->base->vars[VS::LIGHT_PARAM_SHADOW_DARKENING]); - //matrix - } - - light_data[VL_LIGHT_ATTENUATION][0] = l->vars[VS::LIGHT_PARAM_ENERGY]; - - if (l->type == VS::LIGHT_DIRECTIONAL) { - light_data[VL_LIGHT_ATTENUATION][1] = l->directional_shadow_param[VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE]; - } else { - light_data[VL_LIGHT_ATTENUATION][1] = l->vars[VS::LIGHT_PARAM_RADIUS]; - } - - light_data[VL_LIGHT_ATTENUATION][2] = l->vars[VS::LIGHT_PARAM_ATTENUATION]; - - light_data[VL_LIGHT_SPOT_ATTENUATION][0] = Math::cos(Math::deg2rad(l->vars[VS::LIGHT_PARAM_SPOT_ANGLE])); - light_data[VL_LIGHT_SPOT_ATTENUATION][1] = l->vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]; - - //int uf = material_shader.get_uniform(MaterialShaderGLES2::LIGHT_PARAMS); - for (int i = 0; i < VL_LIGHT_MAX; i++) { - glUniform3f(material_shader.get_uniform(light_uniforms[i]), light_data[i][0], light_data[i][1], light_data[i][2]); - } -} - -template <bool USE_NORMAL, bool USE_TANGENT, bool INPLACE> -void RasterizerGLES2::_skeleton_xform(const uint8_t *p_src_array, int p_src_stride, uint8_t *p_dst_array, int p_dst_stride, int p_elements, const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms) { - - uint32_t basesize = 3; - if (USE_NORMAL) - basesize += 3; - if (USE_TANGENT) - basesize += 4; - - uint32_t extra = (p_dst_stride - basesize * 4); - const int dstvec_size = 3 + (USE_NORMAL ? 3 : 0) + (USE_TANGENT ? 4 : 0); - float dstcopy[dstvec_size]; - - for (int i = 0; i < p_elements; i++) { - - uint32_t ss = p_src_stride * i; - uint32_t ds = p_dst_stride * i; - const uint16_t *bi = (const uint16_t *)&p_src_bones[ss]; - const float *bw = (const float *)&p_src_weights[ss]; - const float *src_vec = (const float *)&p_src_array[ss]; - float *dst_vec; - if (INPLACE) - dst_vec = dstcopy; - else - dst_vec = (float *)&p_dst_array[ds]; - - dst_vec[0] = 0.0; - dst_vec[1] = 0.0; - dst_vec[2] = 0.0; - //conditionals simply removed by optimizer - if (USE_NORMAL) { - - dst_vec[3] = 0.0; - dst_vec[4] = 0.0; - dst_vec[5] = 0.0; - - if (USE_TANGENT) { - - dst_vec[6] = 0.0; - dst_vec[7] = 0.0; - dst_vec[8] = 0.0; - dst_vec[9] = src_vec[9]; - } - } else { - - if (USE_TANGENT) { - - dst_vec[3] = 0.0; - dst_vec[4] = 0.0; - dst_vec[5] = 0.0; - dst_vec[6] = src_vec[6]; - } - } - -#define _XFORM_BONE(m_idx) \ - if (bw[m_idx] == 0) \ - goto end; \ - p_bone_xforms[bi[m_idx]].transform_add_mul3(&src_vec[0], &dst_vec[0], bw[m_idx]); \ - if (USE_NORMAL) { \ - p_bone_xforms[bi[m_idx]].transform3_add_mul3(&src_vec[3], &dst_vec[3], bw[m_idx]); \ - if (USE_TANGENT) { \ - p_bone_xforms[bi[m_idx]].transform3_add_mul3(&src_vec[6], &dst_vec[6], bw[m_idx]); \ - } \ - } else { \ - if (USE_TANGENT) { \ - p_bone_xforms[bi[m_idx]].transform3_add_mul3(&src_vec[3], &dst_vec[3], bw[m_idx]); \ - } \ - } - - _XFORM_BONE(0); - _XFORM_BONE(1); - _XFORM_BONE(2); - _XFORM_BONE(3); - - end: - - if (INPLACE) { - - const uint8_t *esp = (const uint8_t *)dstcopy; - uint8_t *edp = (uint8_t *)&p_dst_array[ds]; - - for (uint32_t j = 0; j < dstvec_size * 4; j++) { - - edp[j] = esp[j]; - } - - } else { - //copy extra stuff - const uint8_t *esp = (const uint8_t *)&src_vec[basesize]; - uint8_t *edp = (uint8_t *)&dst_vec[basesize]; - - for (uint32_t j = 0; j < extra; j++) { - - edp[j] = esp[j]; - } - } - } -} - -Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Material *p_material, const Skeleton *p_skeleton, const float *p_morphs) { - - switch (p_geometry->type) { - - case Geometry::GEOMETRY_MULTISURFACE: - case Geometry::GEOMETRY_SURFACE: { - - const Surface *surf = NULL; - if (p_geometry->type == Geometry::GEOMETRY_SURFACE) - surf = static_cast<const Surface *>(p_geometry); - else if (p_geometry->type == Geometry::GEOMETRY_MULTISURFACE) - surf = static_cast<const MultiMeshSurface *>(p_geometry)->surface; - - if (surf->format != surf->configured_format) { - if (OS::get_singleton()->is_stdout_verbose()) { - - print_line("has format: " + itos(surf->format)); - print_line("configured format: " + itos(surf->configured_format)); - } - ERR_EXPLAIN("Missing arrays (not set) in surface"); - } - ERR_FAIL_COND_V(surf->format != surf->configured_format, ERR_UNCONFIGURED); - uint8_t *base = 0; - int stride = surf->stride; - bool use_VBO = (surf->array_local == 0); - _setup_geometry_vinfo = surf->array_len; - - bool skeleton_valid = p_skeleton && (surf->format & VS::ARRAY_FORMAT_BONES) && (surf->format & VS::ARRAY_FORMAT_WEIGHTS) && !p_skeleton->bones.empty() && p_skeleton->bones.size() > surf->max_bone; - /* - if (surf->packed) { - float scales[4]={surf->vertex_scale,surf->uv_scale,surf->uv2_scale,0.0}; - glVertexAttrib4fv( 7, scales ); - } else { - glVertexAttrib4f( 7, 1,1,1,1 ); - - }*/ - - if (!use_VBO) { - - DEBUG_TEST_ERROR("Draw NO VBO"); - - base = surf->array_local; - glBindBuffer(GL_ARRAY_BUFFER, 0); - bool can_copy_to_local = surf->local_stride * surf->array_len <= skinned_buffer_size; - if (p_morphs && surf->stride * surf->array_len > skinned_buffer_size) - can_copy_to_local = false; - - if (!can_copy_to_local) - skeleton_valid = false; - - /* compute morphs */ - - if (p_morphs && surf->morph_target_count && can_copy_to_local) { - - base = skinned_buffer; - stride = surf->local_stride; - - //copy all first - float coef = 1.0; - - for (int i = 0; i < surf->morph_target_count; i++) { - if (surf->mesh->morph_target_mode == VS::MORPH_MODE_NORMALIZED) - coef -= p_morphs[i]; - ERR_FAIL_COND_V(surf->morph_format != surf->morph_targets_local[i].configured_format, ERR_INVALID_DATA); - } - - int16_t coeffp = CLAMP(coef * 255, 0, 255); - - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - - const Surface::ArrayData &ad = surf->array[i]; - if (ad.size == 0) - continue; - - int ofs = ad.ofs; - int src_stride = surf->stride; - int dst_stride = skeleton_valid ? surf->stride : surf->local_stride; - int count = surf->array_len; - - if (!skeleton_valid && i >= VS::ARRAY_MAX - 3) - break; - - switch (i) { - - case VS::ARRAY_VERTEX: - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: { - - for (int k = 0; k < count; k++) { - - const float *src = (const float *)&surf->array_local[ofs + k * src_stride]; - float *dst = (float *)&base[ofs + k * dst_stride]; - - dst[0] = src[0] * coef; - dst[1] = src[1] * coef; - dst[2] = src[2] * coef; - }; - - } break; - case VS::ARRAY_COLOR: { - - for (int k = 0; k < count; k++) { - - const uint8_t *src = (const uint8_t *)&surf->array_local[ofs + k * src_stride]; - uint8_t *dst = (uint8_t *)&base[ofs + k * dst_stride]; - - dst[0] = (src[0] * coeffp) >> 8; - dst[1] = (src[1] * coeffp) >> 8; - dst[2] = (src[2] * coeffp) >> 8; - dst[3] = (src[3] * coeffp) >> 8; - } - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - for (int k = 0; k < count; k++) { - - const float *src = (const float *)&surf->array_local[ofs + k * src_stride]; - float *dst = (float *)&base[ofs + k * dst_stride]; - - dst[0] = src[0] * coef; - dst[1] = src[1] * coef; - } - - } break; - case VS::ARRAY_BONES: - case VS::ARRAY_WEIGHTS: { - - for (int k = 0; k < count; k++) { - - const float *src = (const float *)&surf->array_local[ofs + k * src_stride]; - float *dst = (float *)&base[ofs + k * dst_stride]; - - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst[3] = src[3]; - } - - } break; - } - } - - for (int j = 0; j < surf->morph_target_count; j++) { - - for (int i = 0; i < VS::ARRAY_MAX - 3; i++) { - - const Surface::ArrayData &ad = surf->array[i]; - if (ad.size == 0) - continue; - - int ofs = ad.ofs; - int src_stride = surf->local_stride; - int dst_stride = skeleton_valid ? surf->stride : surf->local_stride; - int count = surf->array_len; - const uint8_t *morph = surf->morph_targets_local[j].array; - float w = p_morphs[j]; - int16_t wfp = CLAMP(w * 255, 0, 255); - - switch (i) { - - case VS::ARRAY_VERTEX: - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: { - - for (int k = 0; k < count; k++) { - - const float *src_morph = (const float *)&morph[ofs + k * src_stride]; - float *dst = (float *)&base[ofs + k * dst_stride]; - - dst[0] += src_morph[0] * w; - dst[1] += src_morph[1] * w; - dst[2] += src_morph[2] * w; - } - - } break; - case VS::ARRAY_COLOR: { - for (int k = 0; k < count; k++) { - - const uint8_t *src = (const uint8_t *)&morph[ofs + k * src_stride]; - uint8_t *dst = (uint8_t *)&base[ofs + k * dst_stride]; - - dst[0] = (src[0] * wfp) >> 8; - dst[1] = (src[1] * wfp) >> 8; - dst[2] = (src[2] * wfp) >> 8; - dst[3] = (src[3] * wfp) >> 8; - } - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - for (int k = 0; k < count; k++) { - - const float *src_morph = (const float *)&morph[ofs + k * src_stride]; - float *dst = (float *)&base[ofs + k * dst_stride]; - - dst[0] += src_morph[0] * w; - dst[1] += src_morph[1] * w; - } - - } break; - } - } - } - - if (skeleton_valid) { - - const uint8_t *src_weights = &surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs]; - const uint8_t *src_bones = &surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; - const Skeleton::Bone *skeleton = &p_skeleton->bones[0]; - - if (surf->format & VS::ARRAY_FORMAT_NORMAL && surf->format & VS::ARRAY_FORMAT_TANGENT) - _skeleton_xform<true, true, true>(base, surf->stride, base, surf->stride, surf->array_len, src_bones, src_weights, skeleton); - else if (surf->format & (VS::ARRAY_FORMAT_NORMAL)) - _skeleton_xform<true, false, true>(base, surf->stride, base, surf->stride, surf->array_len, src_bones, src_weights, skeleton); - else if (surf->format & (VS::ARRAY_FORMAT_TANGENT)) - _skeleton_xform<false, true, true>(base, surf->stride, base, surf->stride, surf->array_len, src_bones, src_weights, skeleton); - else - _skeleton_xform<false, false, true>(base, surf->stride, base, surf->stride, surf->array_len, src_bones, src_weights, skeleton); - } - - stride = skeleton_valid ? surf->stride : surf->local_stride; - -#if 0 - { - //in-place skeleton tansformation, only used for morphs, slow. - //should uptimize some day.... - - const uint8_t *src_weights=&surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs]; - const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; - int src_stride = surf->stride; - int count = surf->array_len; - const Transform *skeleton = &p_skeleton->bones[0]; - - for(int i=0;i<VS::ARRAY_MAX-1;i++) { - - const Surface::ArrayData& ad=surf->array[i]; - if (ad.size==0) - continue; - - int ofs = ad.ofs; - - - switch(i) { - - case VS::ARRAY_VERTEX: { - for(int k=0;k<count;k++) { - - float *ptr= (float*)&base[ofs+k*stride]; - const GLfloat* weights = reinterpret_cast<const GLfloat*>(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast<const GLfloat*>(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - - float w = weights[j]; - if (w==0) - break; - - //print_line("accum "+itos(i)+" += "+rtos(Math::ftoi(bones[j]))+" * "+skeleton[ Math::ftoi(bones[j]) ]+" * "+rtos(w)); - int bidx = Math::fast_ftoi(bones[j]); - dst+=skeleton[ bidx ].xform(src) * w; - } - - ptr[0]=dst.x; - ptr[1]=dst.y; - ptr[2]=dst.z; - - } break; - - } break; - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: { - for(int k=0;k<count;k++) { - - float *ptr= (float*)&base[ofs+k*stride]; - const GLfloat* weights = reinterpret_cast<const GLfloat*>(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast<const GLfloat*>(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - - float w = weights[j]; - if (w==0) - break; - - //print_line("accum "+itos(i)+" += "+rtos(Math::ftoi(bones[j]))+" * "+skeleton[ Math::ftoi(bones[j]) ]+" * "+rtos(w)); - int bidx=Math::fast_ftoi(bones[j]); - dst+=skeleton[ bidx ].basis.xform(src) * w; - } - - ptr[0]=dst.x; - ptr[1]=dst.y; - ptr[2]=dst.z; - - } break; - - } break; - } - } - } -#endif - - } else if (skeleton_valid) { - - base = skinned_buffer; - //copy stuff and get it ready for the skeleton - - int dst_stride = surf->stride - (surf->array[VS::ARRAY_BONES].size + surf->array[VS::ARRAY_WEIGHTS].size); - const uint8_t *src_weights = &surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs]; - const uint8_t *src_bones = &surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; - const Skeleton::Bone *skeleton = &p_skeleton->bones[0]; - - if (surf->format & VS::ARRAY_FORMAT_NORMAL && surf->format & VS::ARRAY_FORMAT_TANGENT) - _skeleton_xform<true, true, false>(surf->array_local, surf->stride, base, dst_stride, surf->array_len, src_bones, src_weights, skeleton); - else if (surf->format & (VS::ARRAY_FORMAT_NORMAL)) - _skeleton_xform<true, false, false>(surf->array_local, surf->stride, base, dst_stride, surf->array_len, src_bones, src_weights, skeleton); - else if (surf->format & (VS::ARRAY_FORMAT_TANGENT)) - _skeleton_xform<false, true, false>(surf->array_local, surf->stride, base, dst_stride, surf->array_len, src_bones, src_weights, skeleton); - else - _skeleton_xform<false, false, false>(surf->array_local, surf->stride, base, dst_stride, surf->array_len, src_bones, src_weights, skeleton); - - stride = dst_stride; - } - - } else { - - glBindBuffer(GL_ARRAY_BUFFER, surf->vertex_id); - }; - - for (int i = 0; i < (VS::ARRAY_MAX - 1); i++) { - - const Surface::ArrayData &ad = surf->array[i]; - - /* - if (!gl_texcoord_shader[i]) - continue; - */ - - if (ad.size == 0 || !ad.bind) { - glDisableVertexAttribArray(i); - if (i == VS::ARRAY_COLOR) { - _set_color_attrib(Color(1, 1, 1, 1)); - }; - //print_line("disable: "+itos(i)); - continue; // this one is disabled. - } - - glEnableVertexAttribArray(i); - //print_line("set: "+itos(i)+" - count: "+itos(ad.count)+" datatype: "+itos(ad.datatype)+" ofs: "+itos(ad.ofs)+" stride: "+itos(stride)+" total len: "+itos(surf->array_len)); - glVertexAttribPointer(i, ad.count, ad.datatype, ad.normalize, stride, &base[ad.ofs]); - } -#ifdef GLEW_ENABLED - //"desktop" opengl needs this. - if (surf->primitive == VS::PRIMITIVE_POINTS) { - glEnable(GL_POINT_SPRITE); - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - - } else { - glDisable(GL_POINT_SPRITE); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); - } -#endif - } break; - - default: break; - }; - - return OK; -}; - -static const GLenum gl_primitive[] = { - GL_POINTS, - GL_LINES, - GL_LINE_STRIP, - GL_LINE_LOOP, - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN -}; - -void RasterizerGLES2::_render(const Geometry *p_geometry, const Material *p_material, const Skeleton *p_skeleton, const GeometryOwner *p_owner, const Transform &p_xform) { - - _rinfo.object_count++; - - switch (p_geometry->type) { - - case Geometry::GEOMETRY_SURFACE: { - - Surface *s = (Surface *)p_geometry; - - _rinfo.vertex_count += s->array_len; - - if (s->index_array_len > 0) { - - if (s->index_array_local) { - - //print_line("LOCAL F: "+itos(s->format)+" C: "+itos(s->index_array_len)+" VC: "+itos(s->array_len)); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len > (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, s->index_array_local); - - } else { - //print_line("indices: "+itos(s->index_array_local) ); - - //print_line("VBO F: "+itos(s->format)+" C: "+itos(s->index_array_len)+" VC: "+itos(s->array_len)); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); - 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); - }; - - _rinfo.draw_calls++; - } break; - - case Geometry::GEOMETRY_MULTISURFACE: { - - material_shader.bind_uniforms(); - Surface *s = static_cast<const MultiMeshSurface *>(p_geometry)->surface; - const MultiMesh *mm = static_cast<const MultiMesh *>(p_owner); - int element_count = mm->elements.size(); - - if (element_count == 0) - return; - - if (mm->visible >= 0) { - element_count = MIN(element_count, mm->visible); - } - - const MultiMesh::Element *elements = &mm->elements[0]; - - _rinfo.vertex_count += s->array_len * element_count; - - _rinfo.draw_calls += element_count; - - if (use_texture_instancing) { - //this is probably the fastest all around way if vertex texture fetch is supported - - float twd = (1.0 / mm->tw) * 4.0; - float thd = 1.0 / mm->th; - float parm[3] = { 0.0, 01.0, (1.0f / mm->tw) }; - glActiveTexture(GL_TEXTURE0 + max_texture_units - 2); - glDisableVertexAttribArray(6); - glBindTexture(GL_TEXTURE_2D, mm->tex_id); - material_shader.set_uniform(MaterialShaderGLES2::INSTANCE_MATRICES, GL_TEXTURE0 + max_texture_units - 2); - - if (s->index_array_len > 0) { - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); - for (int i = 0; i < element_count; i++) { - parm[0] = (i % (mm->tw >> 2)) * twd; - parm[1] = (i / (mm->tw >> 2)) * thd; - glVertexAttrib3fv(6, parm); - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len > (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - } - - } else { - - for (int i = 0; i < element_count; i++) { - //parm[0]=(i%(mm->tw>>2))*twd; - //parm[1]=(i/(mm->tw>>2))*thd; - glVertexAttrib3fv(6, parm); - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - } - }; - - } else if (use_attribute_instancing) { - //if not, using attributes instead of uniforms can be really fast in forward rendering architectures - if (s->index_array_len > 0) { - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); - for (int i = 0; i < element_count; i++) { - glVertexAttrib4fv(8, &elements[i].matrix[0]); - glVertexAttrib4fv(9, &elements[i].matrix[4]); - glVertexAttrib4fv(10, &elements[i].matrix[8]); - glVertexAttrib4fv(11, &elements[i].matrix[12]); - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len > (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - } - - } else { - - for (int i = 0; i < element_count; i++) { - glVertexAttrib4fv(8, &elements[i].matrix[0]); - glVertexAttrib4fv(9, &elements[i].matrix[4]); - glVertexAttrib4fv(10, &elements[i].matrix[8]); - glVertexAttrib4fv(11, &elements[i].matrix[12]); - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - } - }; - - } else { - - //nothing to do, slow path (hope no hardware has to use it... but you never know) - - if (s->index_array_len > 0) { - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); - for (int i = 0; i < element_count; i++) { - - glUniformMatrix4fv(material_shader.get_uniform_location(MaterialShaderGLES2::INSTANCE_TRANSFORM), 1, false, elements[i].matrix); - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len > (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - } - - } else { - - for (int i = 0; i < element_count; i++) { - glUniformMatrix4fv(material_shader.get_uniform_location(MaterialShaderGLES2::INSTANCE_TRANSFORM), 1, false, elements[i].matrix); - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - } - }; - } - } break; - case Geometry::GEOMETRY_IMMEDIATE: { - - bool restore_tex = false; - const Immediate *im = static_cast<const Immediate *>(p_geometry); - if (im->building) { - return; - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - for (const List<Immediate::Chunk>::Element *E = im->chunks.front(); E; E = E->next()) { - - const Immediate::Chunk &c = E->get(); - if (c.vertices.empty()) { - continue; - } - for (int i = 0; i < c.vertices.size(); i++) - - if (c.texture.is_valid() && texture_owner.owns(c.texture)) { - - const Texture *t = texture_owner.get(c.texture); - glActiveTexture(GL_TEXTURE0 + tc0_idx); - glBindTexture(t->target, t->tex_id); - restore_tex = true; - - } else if (restore_tex) { - - glActiveTexture(GL_TEXTURE0 + tc0_idx); - glBindTexture(GL_TEXTURE_2D, tc0_id_cache); - restore_tex = false; - } - - if (!c.normals.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_NORMAL); - glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false, sizeof(Vector3), c.normals.ptr()); - - } else { - - glDisableVertexAttribArray(VS::ARRAY_NORMAL); - } - - if (!c.tangents.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_TANGENT); - glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false, sizeof(Plane), c.tangents.ptr()); - - } else { - - glDisableVertexAttribArray(VS::ARRAY_TANGENT); - } - - if (!c.colors.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), c.colors.ptr()); - - } else { - - glDisableVertexAttribArray(VS::ARRAY_COLOR); - _set_color_attrib(Color(1, 1, 1, 1)); - } - - if (!c.uvs.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), c.uvs.ptr()); - - } else { - - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - if (!c.uvs2.empty()) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); - glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false, sizeof(Vector2), c.uvs2.ptr()); - - } else { - - glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); - } - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, sizeof(Vector3), c.vertices.ptr()); - glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size()); - } - - if (restore_tex) { - - glActiveTexture(GL_TEXTURE0 + tc0_idx); - glBindTexture(GL_TEXTURE_2D, tc0_id_cache); - restore_tex = false; - } - - } break; - case Geometry::GEOMETRY_PARTICLES: { - - //print_line("particulinas"); - const Particles *particles = static_cast<const Particles *>(p_geometry); - ERR_FAIL_COND(!p_owner); - ParticlesInstance *particles_instance = (ParticlesInstance *)p_owner; - - ParticleSystemProcessSW &pp = particles_instance->particles_process; - float td = time_delta; //MIN(time_delta,1.0/10.0); - pp.process(&particles->data, particles_instance->transform, td); - ERR_EXPLAIN("A parameter in the particle system is not correct."); - ERR_FAIL_COND(!pp.valid); - - Transform camera; - if (shadow) - camera = shadow->transform; - else - camera = camera_transform; - - particle_draw_info.prepare(&particles->data, &pp, particles_instance->transform, camera); - _rinfo.draw_calls += particles->data.amount; - - _rinfo.vertex_count += 4 * particles->data.amount; - - { - static const Vector3 points[4] = { - Vector3(-1.0, 1.0, 0), - Vector3(1.0, 1.0, 0), - Vector3(1.0, -1.0, 0), - Vector3(-1.0, -1.0, 0) - }; - static const Vector3 uvs[4] = { - Vector3(0.0, 0.0, 0.0), - Vector3(1.0, 0.0, 0.0), - Vector3(1.0, 1.0, 0.0), - Vector3(0, 1.0, 0.0) - }; - static const Vector3 normals[4] = { - Vector3(0, 0, 1), - Vector3(0, 0, 1), - Vector3(0, 0, 1), - Vector3(0, 0, 1) - }; - - static const Plane tangents[4] = { - Plane(Vector3(1, 0, 0), 0), - Plane(Vector3(1, 0, 0), 0), - Plane(Vector3(1, 0, 0), 0), - Plane(Vector3(1, 0, 0), 0) - }; - - for (int i = 0; i < particles->data.amount; i++) { - - ParticleSystemDrawInfoSW::ParticleDrawInfo &pinfo = *particle_draw_info.draw_info_order[i]; - if (!pinfo.data->active) - continue; - - material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, pinfo.transform); - _set_color_attrib(pinfo.color); - _draw_primitive(4, points, normals, NULL, uvs, tangents); - } - } - - } break; - default: break; - }; -}; - -void RasterizerGLES2::_setup_shader_params(const Material *p_material) { - -#if 0 - int idx=0; - int tex_idx=0; - for(Map<StringName,Variant>::Element *E=p_material->shader_cache->params.front();E;E=E->next(),idx++) { - - Variant v; // - v = E->get(); - const Map<StringName,Variant>::Element *F=p_material->shader_params.find(E->key()); - if (F) - v=F->get(); - - switch(v.get_type() ) { - case Variant::OBJECT: - case Variant::_RID: { - - RID tex=v; - if (!tex.is_valid()) - break; - - Texture *texture = texture_owner.get(tex); - if (!texture) - break; - glUniform1i( material_shader.get_custom_uniform_location(idx), tex_idx); - glActiveTexture(tex_idx); - glBindTexture(texture->target,texture->tex_id); - - } break; - case Variant::COLOR: { - - Color c=v; - material_shader.set_custom_uniform(idx,Vector3(c.r,c.g,c.b)); - } break; - default: { - - material_shader.set_custom_uniform(idx,v); - } break; - } - - } -#endif -} - -void RasterizerGLES2::_setup_skeleton(const Skeleton *p_skeleton) { - - material_shader.set_conditional(MaterialShaderGLES2::USE_SKELETON, p_skeleton != NULL); - if (p_skeleton && p_skeleton->tex_id) { - - glActiveTexture(GL_TEXTURE0 + max_texture_units - 2); - glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id); - } -} - -void RasterizerGLES2::_render_list_forward(RenderList *p_render_list, const Transform &p_view_transform, const Transform &p_view_transform_inverse, const CameraMatrix &p_projection, bool p_reverse_cull, bool p_fragment_light, bool p_alpha_pass) { - - if (current_rt && current_rt_vflip) { - //p_reverse_cull=!p_reverse_cull; - glFrontFace(GL_CCW); - } - - const Material *prev_material = NULL; - uint16_t prev_light = 0x777E; - const Geometry *prev_geometry_cmp = NULL; - uint8_t prev_light_type = 0xEF; - const Skeleton *prev_skeleton = NULL; - uint8_t prev_sort_flags = 0xFF; - const BakedLightData *prev_baked_light = NULL; - RID prev_baked_light_texture; - const float *prev_morph_values = NULL; - int prev_receive_shadows_state = -1; - - material_shader.set_conditional(MaterialShaderGLES2::USE_VERTEX_LIGHTING, !shadow && !p_fragment_light); - material_shader.set_conditional(MaterialShaderGLES2::USE_FRAGMENT_LIGHTING, !shadow && p_fragment_light); - material_shader.set_conditional(MaterialShaderGLES2::USE_SKELETON, false); - - if (shadow) { - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_DIRECTIONAL, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_OMNI, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4, false); - material_shader.set_conditional(MaterialShaderGLES2::SHADELESS, false); - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE, false); - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, false); - //material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_TEXTURE,false); - } - - bool stores_glow = !shadow && (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) && !p_alpha_pass; - float sampled_light_dp_multiplier = 1.0; - - bool prev_blend = false; - glDisable(GL_BLEND); - for (int i = 0; i < p_render_list->element_count; i++) { - - RenderList::Element *e = p_render_list->elements[i]; - const Material *material = e->material; - uint16_t light = e->light; - uint8_t light_type = e->light_type; - uint8_t sort_flags = e->sort_flags; - const Skeleton *skeleton = e->skeleton; - const Geometry *geometry_cmp = e->geometry_cmp; - const BakedLightData *baked_light = e->instance->baked_light; - const float *morph_values = e->instance->morph_values.ptr(); - int receive_shadows_state = e->instance->receive_shadows == true ? 1 : 0; - - bool rebind = false; - bool bind_baked_light_octree = false; - bool bind_baked_lightmap = false; - bool additive = false; - bool bind_dp_sampler = false; - - if (!shadow) { - - if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) { - texscreen_copied = true; - _copy_to_texscreen(); - - //force reset state - prev_material = NULL; - prev_light = 0x777E; - prev_geometry_cmp = NULL; - prev_light_type = 0xEF; - prev_skeleton = NULL; - prev_sort_flags = 0xFF; - prev_morph_values = NULL; - prev_receive_shadows_state = -1; - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - } - - if (light_type != prev_light_type || receive_shadows_state != prev_receive_shadows_state) { - - if (material->flags[VS::MATERIAL_FLAG_UNSHADED] || current_debug == VS::SCENARIO_DEBUG_SHADELESS) { - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_DIRECTIONAL, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_OMNI, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4, false); - material_shader.set_conditional(MaterialShaderGLES2::SHADELESS, true); - } else { - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_DIRECTIONAL, (light_type & 0x3) == VS::LIGHT_DIRECTIONAL); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_OMNI, (light_type & 0x3) == VS::LIGHT_OMNI); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT, (light_type & 0x3) == VS::LIGHT_SPOT); - if (receive_shadows_state == 1) { - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW, (light_type & 0x8)); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM, (light_type & 0x10)); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4, (light_type & 0x20)); - } else { - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM, false); - material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4, false); - } - material_shader.set_conditional(MaterialShaderGLES2::SHADELESS, false); - } - - rebind = true; - } - - if (!*e->additive_ptr) { - - additive = false; - *e->additive_ptr = true; - } else { - additive = true; - } - - if (stores_glow) - material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW, !additive); - - bool desired_blend = false; - VS::MaterialBlendMode desired_blend_mode = VS::MATERIAL_BLEND_MODE_MIX; - - if (additive) { - desired_blend = true; - desired_blend_mode = VS::MATERIAL_BLEND_MODE_ADD; - } else { - desired_blend = p_alpha_pass; - desired_blend_mode = material->blend_mode; - } - - if (prev_blend != desired_blend) { - - if (desired_blend) { - glEnable(GL_BLEND); - if (!current_rt || !current_rt_transparent) - glColorMask(1, 1, 1, 0); - } else { - glDisable(GL_BLEND); - glColorMask(1, 1, 1, 1); - } - - prev_blend = desired_blend; - } - - if (desired_blend && desired_blend_mode != current_blend_mode) { - - switch (desired_blend_mode) { - - case VS::MATERIAL_BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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 VS::MATERIAL_BLEND_MODE_ADD: { - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(p_alpha_pass ? GL_SRC_ALPHA : GL_ONE, GL_ONE); - - } break; - case VS::MATERIAL_BLEND_MODE_SUB: { - - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case VS::MATERIAL_BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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; - } - - current_blend_mode = desired_blend_mode; - } - - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE, false); - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, false); - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER, false); - - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_COLOR, false); - - if (material->flags[VS::MATERIAL_FLAG_UNSHADED] == false && current_debug != VS::SCENARIO_DEBUG_SHADELESS) { - - if (baked_light != NULL) { - if (baked_light->realtime_color_enabled) { - float realtime_energy = baked_light->realtime_energy; - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_COLOR, true); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_COLOR, Vector3(baked_light->realtime_color.r * realtime_energy, baked_light->realtime_color.g * realtime_energy, baked_light->realtime_color.b * realtime_energy)); - } - } - - if (e->instance->sampled_light.is_valid()) { - - SampledLight *sl = sampled_light_owner.get(e->instance->sampled_light); - if (sl) { - - baked_light = NULL; //can't mix - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER, true); - glActiveTexture(GL_TEXTURE0 + max_texture_units - 3); - glBindTexture(GL_TEXTURE_2D, sl->texture); //bind the texture - sampled_light_dp_multiplier = sl->multiplier; - bind_dp_sampler = true; - } - } - - if (!additive && baked_light) { - - if (baked_light->mode == VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) { - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE, true); - bind_baked_light_octree = true; - if (prev_baked_light != baked_light) { - Texture *tex = texture_owner.get(baked_light->octree_texture); - if (tex) { - - glActiveTexture(GL_TEXTURE0 + max_texture_units - 3); - glBindTexture(tex->target, tex->tex_id); //bind the texture - } - if (baked_light->light_texture.is_valid()) { - Texture *texl = texture_owner.get(baked_light->light_texture); - if (texl) { - glActiveTexture(GL_TEXTURE0 + max_texture_units - 4); - glBindTexture(texl->target, texl->tex_id); //bind the light texture - } - } - } - } else if (baked_light->mode == VS::BAKED_LIGHT_LIGHTMAPS) { - - int lightmap_idx = e->instance->baked_lightmap_id; - - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, false); - bind_baked_lightmap = false; - - if (baked_light->lightmaps.has(lightmap_idx)) { - - RID texid = baked_light->lightmaps[lightmap_idx]; - - if (prev_baked_light != baked_light || texid != prev_baked_light_texture) { - - Texture *tex = texture_owner.get(texid); - if (tex) { - - glActiveTexture(GL_TEXTURE0 + max_texture_units - 3); - glBindTexture(tex->target, tex->tex_id); //bind the texture - } - - prev_baked_light_texture = texid; - } - - if (texid.is_valid()) { - material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, true); - bind_baked_lightmap = true; - } - } - } - } - - if (int(prev_baked_light != NULL) ^ int(baked_light != NULL)) { - rebind = true; - } - } - } - - if (sort_flags != prev_sort_flags) { - - if (sort_flags & RenderList::SORT_FLAG_INSTANCING) { - material_shader.set_conditional(MaterialShaderGLES2::USE_UNIFORM_INSTANCING, !use_texture_instancing && !use_attribute_instancing); - material_shader.set_conditional(MaterialShaderGLES2::USE_ATTRIBUTE_INSTANCING, use_attribute_instancing); - material_shader.set_conditional(MaterialShaderGLES2::USE_TEXTURE_INSTANCING, use_texture_instancing); - } else { - material_shader.set_conditional(MaterialShaderGLES2::USE_UNIFORM_INSTANCING, false); - material_shader.set_conditional(MaterialShaderGLES2::USE_ATTRIBUTE_INSTANCING, false); - material_shader.set_conditional(MaterialShaderGLES2::USE_TEXTURE_INSTANCING, false); - } - rebind = true; - } - - if (use_hw_skeleton_xform && (skeleton != prev_skeleton || morph_values != prev_morph_values)) { - if (!prev_skeleton || !skeleton) - rebind = true; //went from skeleton <-> no skeleton, needs rebind - - if (morph_values == NULL) - _setup_skeleton(skeleton); - else - _setup_skeleton(NULL); - } - - if (material != prev_material || rebind) { - - rebind = _setup_material(e->geometry, material, additive, !p_alpha_pass); - - DEBUG_TEST_ERROR("Setup material"); - _rinfo.mat_change_count++; - //_setup_material_overrides(e->material,NULL,material_overrides); - //_setup_material_skeleton(material,skeleton); - } else { - - if (prev_skeleton != skeleton) { - //_setup_material_skeleton(material,skeleton); - }; - } - - if (geometry_cmp != prev_geometry_cmp || prev_skeleton != skeleton) { - - _setup_geometry(e->geometry, material, e->skeleton, e->instance->morph_values.ptr()); - _rinfo.surface_count++; - DEBUG_TEST_ERROR("Setup geometry"); - }; - - if (i == 0 || light != prev_light || rebind) { - if (e->light != 0xFFFF) { - _setup_light(e->light); - } - } - - if (bind_baked_light_octree && (baked_light != prev_baked_light || rebind)) { - - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_INVERSE_TRANSFORM, *e->instance->baked_light_octree_xform); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_SIZE, baked_light->octree_lattice_size); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_DIVIDE, baked_light->octree_lattice_divide); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_STEPS, baked_light->octree_steps); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX, max_texture_units - 3); - if (baked_light->light_texture.is_valid()) { - - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX, max_texture_units - 4); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE, baked_light->light_tex_pixel_size); - } else { - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX, max_texture_units - 3); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE, baked_light->octree_tex_pixel_size); - } - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_MULTIPLIER, baked_light->texture_multiplier); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_PIX_SIZE, baked_light->octree_tex_pixel_size); - } - - if (bind_baked_lightmap && (baked_light != prev_baked_light || rebind)) { - - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, max_texture_units - 3); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP_MULTIPLIER, baked_light->lightmap_multiplier); - } - - if (bind_dp_sampler) { - - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER_MULTIPLIER, sampled_light_dp_multiplier); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER, max_texture_units - 3); - } - - _set_cull(e->mirror, p_reverse_cull); - - if (i == 0 || rebind) { - material_shader.set_uniform(MaterialShaderGLES2::CAMERA_INVERSE_TRANSFORM, p_view_transform_inverse); - material_shader.set_uniform(MaterialShaderGLES2::PROJECTION_TRANSFORM, p_projection); - if (!shadow) { - - if (!additive && current_env && current_env->fx_enabled[VS::ENV_FX_AMBIENT_LIGHT]) { - Color ambcolor = _convert_color(current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR]); - float ambnrg = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY]; - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHT, Vector3(ambcolor.r * ambnrg, ambcolor.g * ambnrg, ambcolor.b * ambnrg)); - } else { - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHT, Vector3()); - } - } - - _rinfo.shader_change_count++; - } - - if (skeleton != prev_skeleton || rebind) { - if (skeleton && morph_values == NULL) { - material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES, max_texture_units - 2); - material_shader.set_uniform(MaterialShaderGLES2::SKELTEX_PIXEL_SIZE, skeleton->pixel_size); - } - } - - if (e->instance->billboard || e->instance->billboard_y || e->instance->depth_scale) { - - Transform xf = e->instance->transform; - if (e->instance->depth_scale) { - - if (p_projection.matrix[3][3]) { - //orthogonal matrix, try to do about the same - //with viewport size - //real_t w = Math::abs( 1.0/(2.0*(p_projection.matrix[0][0])) ); - real_t h = Math::abs(1.0 / (2.0 * p_projection.matrix[1][1])); - float sc = (h * 2.0); //consistent with Y-fov - xf.basis.scale(Vector3(sc, sc, sc)); - } else { - //just scale by depth - real_t sc = -camera_plane.distance_to(xf.origin); - xf.basis.scale(Vector3(sc, sc, sc)); - } - } - - if (e->instance->billboard) { - - Vector3 scale = xf.basis.get_scale(); - - if (current_rt && current_rt_vflip) { - xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), -p_view_transform.get_basis().get_axis(1)); - } else { - xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), p_view_transform.get_basis().get_axis(1)); - } - - xf.basis.scale(scale); - } - - if (e->instance->billboard_y) { - - Vector3 scale = xf.basis.get_scale(); - Vector3 look_at = p_view_transform.get_origin(); - look_at.y = 0.0; - Vector3 look_at_norm = look_at.normalized(); - - if (current_rt && current_rt_vflip) { - xf.set_look_at(xf.origin, xf.origin + look_at_norm, Vector3(0.0, -1.0, 0.0)); - } else { - xf.set_look_at(xf.origin, xf.origin + look_at_norm, Vector3(0.0, 1.0, 0.0)); - } - xf.basis.scale(scale); - } - material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, xf); - - } else { - material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, e->instance->transform); - } - - material_shader.set_uniform(MaterialShaderGLES2::NORMAL_MULT, e->mirror ? -1.0 : 1.0); - material_shader.set_uniform(MaterialShaderGLES2::CONST_LIGHT_MULT, additive ? 0.0 : 1.0); - - _render(e->geometry, material, skeleton, e->owner, e->instance->transform); - DEBUG_TEST_ERROR("Rendering"); - - prev_material = material; - prev_skeleton = skeleton; - prev_geometry_cmp = geometry_cmp; - prev_light = e->light; - prev_light_type = e->light_type; - prev_sort_flags = sort_flags; - prev_baked_light = baked_light; - prev_morph_values = morph_values; - prev_receive_shadows_state = receive_shadows_state; - } - - //print_line("shaderchanges: "+itos(p_alpha_pass)+": "+itos(_rinfo.shader_change_count)); - - if (current_rt && current_rt_vflip) { - glFrontFace(GL_CW); - } -}; - -void RasterizerGLES2::_copy_to_texscreen() { - - //what am i missing? - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); -#ifdef GLEW_ENABLED - glDisable(GL_POINT_SPRITE); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); -#endif - glDisable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - glDisableVertexAttribArray(i); - } - - glActiveTexture(GL_TEXTURE0); - - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.sample_fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, framebuffer.color); - copy_shader.bind(); - _copy_screen_quad(); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); -} - -void RasterizerGLES2::_copy_screen_quad() { - - Vector2 dst_pos[4] = { - Vector2(-1, 1), - Vector2(1, 1), - Vector2(1, -1), - Vector2(-1, -1) - }; - - Size2 uvscale( - (viewport.width / float(framebuffer.scale)) / framebuffer.width, - (viewport.height / float(framebuffer.scale)) / framebuffer.height); - - Vector2 src_uv[4] = { - Vector2(0, 1) * uvscale, - Vector2(1, 1) * uvscale, - Vector2(1, 0) * uvscale, - Vector2(0, 0) * uvscale - }; - - Vector2 full_uv[4] = { - Vector2(0, 1), - Vector2(1, 1), - Vector2(1, 0), - Vector2(0, 0) - }; - - _draw_gui_primitive2(4, dst_pos, NULL, src_uv, full_uv); -} - -void RasterizerGLES2::_process_glow_bloom() { - - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.blur[0].fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, framebuffer.color); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_COPY, true); - if (current_vd && current_env->fx_enabled[VS::ENV_FX_HDR]) { - - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR, true); - } - - copy_shader.bind(); - copy_shader.set_uniform(CopyShaderGLES2::BLOOM, float(current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM])); - copy_shader.set_uniform(CopyShaderGLES2::BLOOM_THRESHOLD, float(current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_THRESHOLD])); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - - if (current_vd && current_env->fx_enabled[VS::ENV_FX_HDR]) { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, current_vd->lum_color); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::HDR_SOURCE), 2); - copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_EXPOSURE, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE])); - copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_WHITE, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_WHITE])); - //copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_WHITE,1.0); - copy_shader.set_uniform(CopyShaderGLES2::HDR_GLOW_THRESHOLD, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_GLOW_THRESHOLD])); - copy_shader.set_uniform(CopyShaderGLES2::HDR_GLOW_SCALE, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_GLOW_SCALE])); - - glActiveTexture(GL_TEXTURE0); - } - - glViewport(0, 0, framebuffer.blur_size, framebuffer.blur_size); - _copy_screen_quad(); - - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_COPY, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR, false); - int passes = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]; - Vector2 psize(1.0 / framebuffer.blur_size, 1.0 / framebuffer.blur_size); - float pscale = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE]; - float pmag = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH]; - - for (int i = 0; i < passes; i++) { - - static const Vector2 src_uv[4] = { - Vector2(0, 1), - Vector2(1, 1), - Vector2(1, 0), - Vector2(0, 0) - }; - static const Vector2 dst_pos[4] = { - Vector2(-1, 1), - Vector2(1, 1), - Vector2(1, -1), - Vector2(-1, -1) - }; - - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.blur[1].fbo); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[0].color); - copy_shader.set_conditional(CopyShaderGLES2::BLUR_V_PASS, true); - copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS, false); - copy_shader.bind(); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE, psize); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE, pscale); - copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE, pmag); - - _draw_gui_primitive(4, dst_pos, NULL, src_uv); - - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.blur[0].fbo); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[1].color); - copy_shader.set_conditional(CopyShaderGLES2::BLUR_V_PASS, false); - copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS, true); - copy_shader.bind(); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE, psize); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE, pscale); - copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE, pmag); - - _draw_gui_primitive(4, dst_pos, NULL, src_uv); - } - - copy_shader.set_conditional(CopyShaderGLES2::BLUR_V_PASS, false); - copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR, false); - - //blur it -} - -void RasterizerGLES2::_process_hdr() { - - if (framebuffer.luminance.empty()) { - return; - } - - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.luminance[0].fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, framebuffer.color); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR_COPY, true); - copy_shader.bind(); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - glViewport(0, 0, framebuffer.luminance[0].size, framebuffer.luminance[0].size); - _copy_screen_quad(); - - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR_COPY, false); - //int passes = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]; - - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR_REDUCE, true); - copy_shader.bind(); - - for (int i = 1; i < framebuffer.luminance.size(); i++) { - - static const Vector2 src_uv[4] = { - Vector2(0, 1), - Vector2(1, 1), - Vector2(1, 0), - Vector2(0, 0) - }; - static const Vector2 dst_pos[4] = { - Vector2(-1, 1), - Vector2(1, 1), - Vector2(1, -1), - Vector2(-1, -1) - }; - - Vector2 psize(1.0 / framebuffer.luminance[i - 1].size, 1.0 / framebuffer.luminance[i - 1].size); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.luminance[i].fbo); - glBindTexture(GL_TEXTURE_2D, framebuffer.luminance[i - 1].color); - glViewport(0, 0, framebuffer.luminance[i].size, framebuffer.luminance[i].size); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - - if (framebuffer.luminance[i].size == 1) { - //last step - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR_STORE, true); - copy_shader.bind(); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, current_vd->lum_color); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE_VD_LUM), 1); - copy_shader.set_uniform(CopyShaderGLES2::HDR_TIME_DELTA, time_delta); - copy_shader.set_uniform(CopyShaderGLES2::HDR_EXP_ADJ_SPEED, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED])); - copy_shader.set_uniform(CopyShaderGLES2::MIN_LUMINANCE, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_MIN_LUMINANCE])); - copy_shader.set_uniform(CopyShaderGLES2::MAX_LUMINANCE, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_MAX_LUMINANCE])); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - - //swap them - SWAP(current_vd->lum_color, framebuffer.luminance[i].color); - SWAP(current_vd->lum_fbo, framebuffer.luminance[i].fbo); - } - - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE, psize); - - _draw_gui_primitive(4, dst_pos, NULL, src_uv); - } - - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR_REDUCE, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR_STORE, false); - - draw_next_frame = true; -} - -void RasterizerGLES2::_draw_tex_bg() { - - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glColorMask(1, 1, 1, 1); - - RID texture; - - if (current_env->bg_mode == VS::ENV_BG_TEXTURE) { - texture = current_env->bg_param[VS::ENV_BG_PARAM_TEXTURE]; - } else { - texture = current_env->bg_param[VS::ENV_BG_PARAM_CUBEMAP]; - } - - if (!texture_owner.owns(texture)) { - return; - } - - Texture *t = texture_owner.get(texture); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(t->target, t->tex_id); - - copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY, true); - - if (current_env->bg_mode == VS::ENV_BG_TEXTURE) { - copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false); - - } else { - copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP, true); - } - - copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, true); - - copy_shader.bind(); - - if (current_env->bg_mode == VS::ENV_BG_TEXTURE) { - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - } else { - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE_CUBE), 0); - } - - float nrg = float(current_env->bg_param[VS::ENV_BG_PARAM_ENERGY]); - if (current_env->fx_enabled[VS::ENV_FX_HDR] && !use_fp16_fb) - nrg *= 0.25; //go down a quarter for hdr - copy_shader.set_uniform(CopyShaderGLES2::ENERGY, nrg); - copy_shader.set_uniform(CopyShaderGLES2::CUSTOM_ALPHA, float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW])); - - float flip_sign = (current_env->bg_mode == VS::ENV_BG_TEXTURE && current_rt && current_rt_vflip) ? -1 : 1; - - Vector3 vertices[4] = { - Vector3(-1, -1 * flip_sign, 1), - Vector3(1, -1 * flip_sign, 1), - Vector3(1, 1 * flip_sign, 1), - Vector3(-1, 1 * flip_sign, 1) - }; - - Vector3 src_uv[4] = { - Vector3(0, 1, 0), - Vector3(1, 1, 0), - Vector3(1, 0, 0), - Vector3(0, 0, 0) - }; - - if (current_env->bg_mode == VS::ENV_BG_TEXTURE) { - - //regular texture - //adjust aspect - - float aspect_t = t->width / float(t->height); - float aspect_v = viewport.width / float(viewport.height); - - if (aspect_v > aspect_t) { - //wider than texture - for (int i = 0; i < 4; i++) { - src_uv[i].y = (src_uv[i].y - 0.5) * (aspect_t / aspect_v) + 0.5; - } - - } else { - //narrower than texture - for (int i = 0; i < 4; i++) { - src_uv[i].x = (src_uv[i].x - 0.5) * (aspect_v / aspect_t) + 0.5; - } - } - - float scale = current_env->bg_param[VS::ENV_BG_PARAM_SCALE]; - for (int i = 0; i < 4; i++) { - - src_uv[i].x *= scale; - src_uv[i].y *= scale; - } - } else { - - //skybox uv vectors - float vw, vh, zn; - camera_projection.get_viewport_size(vw, vh); - zn = camera_projection.get_z_near(); - - float scale = current_env->bg_param[VS::ENV_BG_PARAM_SCALE]; - - for (int i = 0; i < 4; i++) { - - Vector3 uv = src_uv[i]; - uv.x = (uv.x * 2.0 - 1.0) * vw * scale; - uv.y = -(uv.y * 2.0 - 1.0) * vh * scale; - uv.z = -zn; - src_uv[i] = camera_transform.basis.xform(uv).normalized(); - src_uv[i].z = -src_uv[i].z; - } - } - - _draw_primitive(4, vertices, NULL, NULL, src_uv); - - copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false); -} - -void RasterizerGLES2::end_scene() { - - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - - bool use_fb = false; - - if (framebuffer.active) { - - //detect when to use the framebuffer object - if (using_canvas_bg || texscreen_used || framebuffer.scale != 1) { - use_fb = true; - } else if (current_env) { - use_fb = false; - for (int i = 0; i < VS::ENV_FX_MAX; i++) { - - if (i == VS::ENV_FX_FOG) //does not need fb - continue; - - if (current_env->fx_enabled[i]) { - use_fb = true; - break; - } - } - } - } - - if (use_fb) { - - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); - glViewport(0, 0, viewport.width / framebuffer.scale, viewport.height / framebuffer.scale); - glScissor(0, 0, viewport.width / framebuffer.scale, viewport.height / framebuffer.scale); - - material_shader.set_conditional(MaterialShaderGLES2::USE_8BIT_HDR, !use_fp16_fb && current_env && current_env->fx_enabled[VS::ENV_FX_HDR]); - - } else { - if (current_rt) { - glScissor(0, 0, viewport.width, viewport.height); - } else { - glScissor(viewport.x, window_size.height - (viewport.height + viewport.y), viewport.width, viewport.height); - } - } - - glEnable(GL_SCISSOR_TEST); - _glClearDepth(1.0); - - bool draw_tex_background = false; - - if (current_debug == VS::SCENARIO_DEBUG_OVERDRAW) { - - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } else if (current_rt && current_rt_transparent) { - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - } else if (current_env) { - - switch (current_env->bg_mode) { - - case VS::ENV_BG_CANVAS: - case VS::ENV_BG_KEEP: { - //copy from framebuffer if framebuffer - glClear(GL_DEPTH_BUFFER_BIT); - } break; - case VS::ENV_BG_DEFAULT_COLOR: - case VS::ENV_BG_COLOR: { - - Color bgcolor; - if (current_env->bg_mode == VS::ENV_BG_COLOR) - bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR]; - else - bgcolor = ProjectSettings::get_singleton()->get("render/default_clear_color"); - bgcolor = _convert_color(bgcolor); - float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0; - glClearColor(bgcolor.r, bgcolor.g, bgcolor.b, a); - _glClearDepth(1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - } break; - case VS::ENV_BG_TEXTURE: - case VS::ENV_BG_CUBEMAP: { - - glClear(GL_DEPTH_BUFFER_BIT); - draw_tex_background = true; - } break; - } - } else { - - Color c = _convert_color(Color(0.3, 0.3, 0.3)); - glClearColor(c.r, c.g, c.b, 0.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - - glDisable(GL_SCISSOR_TEST); - - //material_shader.set_uniform_camera(MaterialShaderGLES2::PROJECTION_MATRIX, camera_projection); - - /* - printf("setting projection to "); - for (int i=0; i<16; i++) { - printf("%f, ", ((float*)camera_projection.matrix)[i]); - }; - printf("\n"); - - print_line(String("setting camera to ")+camera_transform_inverse); - */ - //material_shader.set_uniform_default(MaterialShaderGLES2::CAMERA_INVERSE, camera_transform_inverse); - - current_depth_test = true; - current_depth_mask = true; - texscreen_copied = false; - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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); - } - glDisable(GL_BLEND); - current_blend_mode = VS::MATERIAL_BLEND_MODE_MIX; - - //material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); - opaque_render_list.sort_mat_light_type_flags(); - _render_list_forward(&opaque_render_list, camera_transform, camera_transform_inverse, camera_projection, false, fragment_lighting); - - if (draw_tex_background) { - - //most 3D vendors recommend drawing a texture bg or skybox here, - //after opaque geometry has been drawn - //so the zbuffer can get rid of most pixels - _draw_tex_bg(); - } - - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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); - } - glDisable(GL_BLEND); - current_blend_mode = VS::MATERIAL_BLEND_MODE_MIX; - material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW, false); - if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { - glColorMask(1, 1, 1, 0); //don't touch alpha - } - - alpha_render_list.sort_z(); - _render_list_forward(&alpha_render_list, camera_transform, camera_transform_inverse, camera_projection, false, fragment_lighting, true); - glColorMask(1, 1, 1, 1); - - //material_shader.set_conditional( MaterialShaderGLES2::USE_FOG,false); - - DEBUG_TEST_ERROR("Drawing Scene"); - -#ifdef GLEW_ENABLED - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -#endif - - if (use_fb) { - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - glDisableVertexAttribArray(i); - } - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_SCISSOR_TEST); - glDepthMask(false); - - if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR]) { - - int hdr_tm = current_env->fx_param[VS::ENV_FX_PARAM_HDR_TONEMAPPER]; - switch (hdr_tm) { - case VS::ENV_FX_HDR_TONE_MAPPER_LINEAR: { - - } break; - case VS::ENV_FX_HDR_TONE_MAPPER_LOG: { - copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER, true); - - } break; - case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT: { - copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER, true); - } break; - case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE: { - - copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER, true); - copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE, true); - } break; - } - - _process_hdr(); - } - if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { - _process_glow_bloom(); - int glow_transfer_mode = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE]; - if (glow_transfer_mode == 1) - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN, true); - if (glow_transfer_mode == 2) - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT, true); - } - - glBindFramebuffer(GL_FRAMEBUFFER, current_rt ? current_rt->fbo : base_framebuffer); - - Size2 size; - if (current_rt) { - glBindFramebuffer(GL_FRAMEBUFFER, current_rt->fbo); - glViewport(0, 0, viewport.width, viewport.height); - size = Size2(viewport.width, viewport.height); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); - glViewport(viewport.x, window_size.height - (viewport.height + viewport.y), viewport.width, viewport.height); - size = Size2(viewport.width, viewport.height); - } - - //time to copy!!! - copy_shader.set_conditional(CopyShaderGLES2::USE_BCS, current_env && current_env->fx_enabled[VS::ENV_FX_BCS]); - copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB, current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW, current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR, current_env && current_env->fx_enabled[VS::ENV_FX_HDR]); - copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, true); - copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA, current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]); - - copy_shader.bind(); - //copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0); - - if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[0].color); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::GLOW_SOURCE), 1); - } - - if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR]) { - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, current_vd->lum_color); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::HDR_SOURCE), 2); - copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_EXPOSURE, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE])); - copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_WHITE, float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_WHITE])); - } - - if (current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]) - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE, Size2(1.0 / size.x, 1.0 / size.y)); - - if (current_env && current_env->fx_enabled[VS::ENV_FX_BCS]) { - - Vector3 bcs; - bcs.x = current_env->fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]; - bcs.y = current_env->fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]; - bcs.z = current_env->fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]; - copy_shader.set_uniform(CopyShaderGLES2::BCS, bcs); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, framebuffer.color); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - - _copy_screen_quad(); - - copy_shader.set_conditional(CopyShaderGLES2::USE_BCS, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_HDR, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER, false); - - material_shader.set_conditional(MaterialShaderGLES2::USE_8BIT_HDR, false); - - if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR] && GLOBAL_DEF("rasterizer/debug_hdr", false)) { - _debug_luminances(); - } - } - - current_env = NULL; - current_debug = VS::SCENARIO_DEBUG_DISABLED; - if (GLOBAL_DEF("rasterizer/debug_shadow_maps", false)) { - _debug_shadows(); - } - //_debug_luminances(); - //_debug_samplers(); - - if (using_canvas_bg) { - using_canvas_bg = false; - glColorMask(1, 1, 1, 1); //don't touch alpha - } -} -void RasterizerGLES2::end_shadow_map() { - - ERR_FAIL_COND(!shadow); - - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DITHER); - glEnable(GL_DEPTH_TEST); - glDepthMask(true); - - ShadowBuffer *sb = shadow->near_shadow_buffer; - - ERR_FAIL_COND(!sb); - - glBindFramebuffer(GL_FRAMEBUFFER, sb->fbo); - - if (!use_rgba_shadowmaps) - glColorMask(0, 0, 0, 0); - - //glEnable(GL_POLYGON_OFFSET_FILL); - //glPolygonOffset( 8.0f, 16.0f); - - CameraMatrix cm; - float z_near, z_far; - Transform light_transform; - - float dp_direction = 0.0; - bool flip_facing = false; - Rect2 vp_rect; - - switch (shadow->base->type) { - - case VS::LIGHT_DIRECTIONAL: { - - if (shadow->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - - cm = shadow->custom_projection[shadow_pass]; - light_transform = shadow->custom_transform[shadow_pass]; - - if (shadow_pass == 0) { - - vp_rect = Rect2(0, sb->size / 2, sb->size / 2, sb->size / 2); - glViewport(0, sb->size / 2, sb->size / 2, sb->size / 2); - glScissor(0, sb->size / 2, sb->size / 2, sb->size / 2); - } else if (shadow_pass == 1) { - - vp_rect = Rect2(0, 0, sb->size / 2, sb->size / 2); - glViewport(0, 0, sb->size / 2, sb->size / 2); - glScissor(0, 0, sb->size / 2, sb->size / 2); - - } else if (shadow_pass == 2) { - - vp_rect = Rect2(sb->size / 2, sb->size / 2, sb->size / 2, sb->size / 2); - glViewport(sb->size / 2, sb->size / 2, sb->size / 2, sb->size / 2); - glScissor(sb->size / 2, sb->size / 2, sb->size / 2, sb->size / 2); - } else if (shadow_pass == 3) { - - vp_rect = Rect2(sb->size / 2, 0, sb->size / 2, sb->size / 2); - glViewport(sb->size / 2, 0, sb->size / 2, sb->size / 2); - glScissor(sb->size / 2, 0, sb->size / 2, sb->size / 2); - } - - glEnable(GL_SCISSOR_TEST); - - } else if (shadow->base->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - - if (shadow_pass == 0) { - - cm = shadow->custom_projection[0]; - light_transform = shadow->custom_transform[0]; - vp_rect = Rect2(0, sb->size / 2, sb->size, sb->size / 2); - glViewport(0, sb->size / 2, sb->size, sb->size / 2); - glScissor(0, sb->size / 2, sb->size, sb->size / 2); - } else { - - cm = shadow->custom_projection[1]; - light_transform = shadow->custom_transform[1]; - vp_rect = Rect2(0, 0, sb->size, sb->size / 2); - glViewport(0, 0, sb->size, sb->size / 2); - glScissor(0, 0, sb->size, sb->size / 2); - } - - glEnable(GL_SCISSOR_TEST); - - } else { - cm = shadow->custom_projection[0]; - light_transform = shadow->custom_transform[0]; - vp_rect = Rect2(0, 0, sb->size, sb->size); - glViewport(0, 0, sb->size, sb->size); - } - - z_near = cm.get_z_near(); - z_far = cm.get_z_far(); - - _glClearDepth(1.0f); - glClearColor(1, 1, 1, 1); - - if (use_rgba_shadowmaps) - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - else - glClear(GL_DEPTH_BUFFER_BIT); - - glDisable(GL_SCISSOR_TEST); - - } break; - case VS::LIGHT_OMNI: { - - material_shader.set_conditional(MaterialShaderGLES2::USE_DUAL_PARABOLOID, true); - dp_direction = shadow_pass ? 1.0 : -1.0; - flip_facing = (shadow_pass == 1); - light_transform = shadow->transform; - z_near = 0; - z_far = shadow->base->vars[VS::LIGHT_PARAM_RADIUS]; - shadow->dp.x = 1.0 / z_far; - shadow->dp.y = dp_direction; - - if (shadow_pass == 0) { - vp_rect = Rect2(0, sb->size / 2, sb->size, sb->size / 2); - glViewport(0, sb->size / 2, sb->size, sb->size / 2); - glScissor(0, sb->size / 2, sb->size, sb->size / 2); - } else { - vp_rect = Rect2(0, 0, sb->size, sb->size / 2); - glViewport(0, 0, sb->size, sb->size / 2); - glScissor(0, 0, sb->size, sb->size / 2); - } - glEnable(GL_SCISSOR_TEST); - shadow->projection = cm; - - glClearColor(1, 1, 1, 1); - _glClearDepth(1.0f); - if (use_rgba_shadowmaps) - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - else - glClear(GL_DEPTH_BUFFER_BIT); - glDisable(GL_SCISSOR_TEST); - - } break; - case VS::LIGHT_SPOT: { - - float far = shadow->base->vars[VS::LIGHT_PARAM_RADIUS]; - ERR_FAIL_COND(far <= 0); - float near = far / 200.0; - if (near < 0.05) - near = 0.05; - - float angle = shadow->base->vars[VS::LIGHT_PARAM_SPOT_ANGLE]; - - cm.set_perspective(angle * 2.0, 1.0, near, far); - - shadow->projection = cm; // cache - light_transform = shadow->transform; - z_near = cm.get_z_near(); - z_far = cm.get_z_far(); - - glViewport(0, 0, sb->size, sb->size); - vp_rect = Rect2(0, 0, sb->size, sb->size); - _glClearDepth(1.0f); - glClearColor(1, 1, 1, 1); - if (use_rgba_shadowmaps) - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - else - glClear(GL_DEPTH_BUFFER_BIT); - - } break; - } - - Transform light_transform_inverse = light_transform.affine_inverse(); - - opaque_render_list.sort_mat_geom(); - _render_list_forward(&opaque_render_list, light_transform, light_transform_inverse, cm, flip_facing, false); - - material_shader.set_conditional(MaterialShaderGLES2::USE_DUAL_PARABOLOID, false); - - //if (!use_rgba_shadowmaps) - - if (shadow_filter == SHADOW_FILTER_ESM) { - - copy_shader.set_conditional(CopyShaderGLES2::USE_RGBA_DEPTH, use_rgba_shadowmaps); - copy_shader.set_conditional(CopyShaderGLES2::USE_HIGHP_SOURCE, !use_rgba_shadowmaps); - - Vector2 psize(1.0 / sb->size, 1.0 / sb->size); - float pscale = 1.0; - int passes = shadow->base->vars[VS::LIGHT_PARAM_SHADOW_BLUR_PASSES]; - glDisable(GL_BLEND); - glDisable(GL_CULL_FACE); -#ifdef GLEW_ENABLED - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -#endif - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - glDisableVertexAttribArray(i); - } - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDisable(GL_SCISSOR_TEST); - - if (!use_rgba_shadowmaps) { - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glDepthMask(true); - } else { - glDisable(GL_DEPTH_TEST); - } - - for (int i = 0; i < passes; i++) { - - Vector2 src_sb_uv[4] = { - (vp_rect.pos + Vector2(0, vp_rect.size.y)) / sb->size, - (vp_rect.pos + vp_rect.size) / sb->size, - (vp_rect.pos + Vector2(vp_rect.size.x, 0)) / sb->size, - (vp_rect.pos) / sb->size - }; - /* - Vector2 src_uv[4]={ - Vector2( 0, 1), - Vector2( 1, 1), - Vector2( 1, 0), - Vector2( 0, 0) - }; -*/ - static const Vector2 dst_pos[4] = { - Vector2(-1, 1), - Vector2(1, 1), - Vector2(1, -1), - Vector2(-1, -1) - }; - - glBindFramebuffer(GL_FRAMEBUFFER, blur_shadow_buffer.fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, sb->depth); -#ifdef GLEW_ENABLED -//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); -#endif - - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_V_PASS, true); - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS, false); - - copy_shader.bind(); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE, psize); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE, pscale); - copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE, 1); - //copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - - _draw_gui_primitive(4, dst_pos, NULL, src_sb_uv); - - Vector2 src_bb_uv[4] = { - (vp_rect.pos + Vector2(0, vp_rect.size.y)) / blur_shadow_buffer.size, - (vp_rect.pos + vp_rect.size) / blur_shadow_buffer.size, - (vp_rect.pos + Vector2(vp_rect.size.x, 0)) / blur_shadow_buffer.size, - (vp_rect.pos) / blur_shadow_buffer.size, - }; - - glBindFramebuffer(GL_FRAMEBUFFER, sb->fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, blur_shadow_buffer.depth); -#ifdef GLEW_ENABLED - -//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); -#endif - - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_V_PASS, false); - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS, true); - copy_shader.bind(); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE, psize); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE, pscale); - copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE, 1); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE), 0); - - _draw_gui_primitive(4, dst_pos, NULL, src_bb_uv); - } - - glDepthFunc(GL_LEQUAL); - copy_shader.set_conditional(CopyShaderGLES2::USE_RGBA_DEPTH, false); - copy_shader.set_conditional(CopyShaderGLES2::USE_HIGHP_SOURCE, false); - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_V_PASS, false); - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS, false); - } - - DEBUG_TEST_ERROR("Drawing Shadow"); - shadow = NULL; - glBindFramebuffer(GL_FRAMEBUFFER, current_rt ? current_rt->fbo : base_framebuffer); - glColorMask(1, 1, 1, 1); - //glDisable(GL_POLYGON_OFFSET_FILL); -} - -void RasterizerGLES2::_debug_draw_shadow(GLuint tex, const Rect2 &p_rect) { - - Transform2D modelview; - modelview.translate(p_rect.pos.x, p_rect.pos.y); - canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, modelview); - glBindTexture(GL_TEXTURE_2D, tex); - - Vector3 coords[4] = { - Vector3(p_rect.pos.x, p_rect.pos.y, 0), - Vector3(p_rect.pos.x + p_rect.size.width, - p_rect.pos.y, 0), - Vector3(p_rect.pos.x + p_rect.size.width, - p_rect.pos.y + p_rect.size.height, 0), - Vector3(p_rect.pos.x, - p_rect.pos.y + p_rect.size.height, 0) - }; - - Vector3 texcoords[4] = { - Vector3(0.0f, 0.0f, 0), - Vector3(1.0f, 0.0f, 0), - Vector3(1.0f, 1.0f, 0), - Vector3(0.0f, 1.0f, 0), - }; - - _draw_primitive(4, coords, 0, 0, texcoords); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); -} - -void RasterizerGLES2::_debug_draw_shadows_type(Vector<ShadowBuffer> &p_shadows, Point2 &ofs) { - - Size2 debug_size(128, 128); - //Size2 debug_size(512,512); - - int useblur = shadow_filter == SHADOW_FILTER_ESM ? 1 : 0; - for (int i = 0; i < p_shadows.size() + useblur; i++) { - - ShadowBuffer *sb = i == p_shadows.size() ? &blur_shadow_buffer : &p_shadows[i]; - - if (!sb->owner && i != p_shadows.size()) - continue; - - _debug_draw_shadow(sb->depth, Rect2(ofs, debug_size)); - ofs.x += debug_size.x; - if ((ofs.x + debug_size.x) > viewport.width) { - - ofs.x = 0; - ofs.y += debug_size.y; - } - } -} - -void RasterizerGLES2::_debug_luminances() { - - canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32, !use_fp16_fb); - canvas_begin(); - glDisable(GL_BLEND); - canvas_shader.bind(); - - Size2 debug_size(128, 128); - Size2 ofs; - - for (int i = 0; i <= framebuffer.luminance.size(); i++) { - - if (i == framebuffer.luminance.size()) { - if (!current_vd) - break; - _debug_draw_shadow(current_vd->lum_color, Rect2(ofs, debug_size)); - } else { - _debug_draw_shadow(framebuffer.luminance[i].color, Rect2(ofs, debug_size)); - } - ofs.x += debug_size.x / 2; - if ((ofs.x + debug_size.x) > viewport.width) { - - ofs.x = 0; - ofs.y += debug_size.y; - } - } - - canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32, false); -} - -void RasterizerGLES2::_debug_samplers() { - canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32, false); - canvas_begin(); - glDisable(GL_BLEND); - _set_color_attrib(Color(1, 1, 1, 1)); - canvas_shader.bind(); - - List<RID> samplers; - sampled_light_owner.get_owned_list(&samplers); - - Size2 debug_size(128, 128); - Size2 ofs; - - for (List<RID>::Element *E = samplers.front(); E; E = E->next()) { - - SampledLight *sl = sampled_light_owner.get(E->get()); - - _debug_draw_shadow(sl->texture, Rect2(ofs, debug_size)); - - ofs.x += debug_size.x / 2; - if ((ofs.x + debug_size.x) > viewport.width) { - - ofs.x = 0; - ofs.y += debug_size.y; - } - } -} -void RasterizerGLES2::_debug_shadows() { - - canvas_begin(); - glDisable(GL_BLEND); - Size2 ofs; - - /* - for(int i=0;i<16;i++) { - glActiveTexture(GL_TEXTURE0+i); - //glDisable(GL_TEXTURE_2D); - } - glActiveTexture(GL_TEXTURE0); - //glEnable(GL_TEXTURE_2D); - */ - - _debug_draw_shadows_type(near_shadow_buffers, ofs); - //_debug_draw_shadows_type(far_shadow_buffers,ofs); -} - -void RasterizerGLES2::end_frame() { - - //print_line("VTX: "+itos(_rinfo.vertex_count)+" OBJ: "+itos(_rinfo.object_count)+" MAT: "+itos(_rinfo.mat_change_count)+" SHD: "+itos(_rinfo.shader_change_count)+" CI: "+itos(_rinfo.ci_draw_commands)); - - //print_line("TOTAL VTX: "+itos(_rinfo.vertex_count)); - OS::get_singleton()->swap_buffers(); -} - -void RasterizerGLES2::flush_frame() { - - glFlush(); -} - -/* CANVAS API */ - -void RasterizerGLES2::begin_canvas_bg() { - - if (framebuffer.active) { - using_canvas_bg = true; - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); - glViewport(0, 0, viewport.width, viewport.height); - } else { - using_canvas_bg = false; - } -} - -void RasterizerGLES2::canvas_begin() { - - if (using_canvas_bg) { - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); - glColorMask(1, 1, 1, 0); //don't touch alpha - } - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); -#ifdef GLEW_ENABLED - glDisable(GL_POINT_SPRITE); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); -#endif - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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); - for (int i = 0; i < VS::ARRAY_MAX; i++) { - glDisableVertexAttribArray(i); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, white_tex); - canvas_tex = RID(); - //material_shader.unbind(); - canvas_shader.unbind(); - canvas_shader.set_custom_shader(0); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE, false); - canvas_shader.bind(); - canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0); - canvas_use_modulate = false; - _set_color_attrib(Color(1, 1, 1)); - canvas_transform = Transform(); - canvas_transform.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f); - float csy = 1.0; - if (current_rt && current_rt_vflip) - csy = -1.0; - - canvas_transform.scale(Vector3(2.0f / viewport.width, csy * -2.0f / viewport.height, 1.0f)); - canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX, canvas_transform); - canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, Transform2D()); - canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, Transform2D()); - - canvas_opacity = 1.0; - canvas_blend_mode = VS::MATERIAL_BLEND_MODE_MIX; - canvas_texscreen_used = false; - uses_texpixel_size = false; - - canvas_last_material = NULL; -} - -void RasterizerGLES2::canvas_disable_blending() { - - glDisable(GL_BLEND); -} - -void RasterizerGLES2::canvas_set_opacity(float p_opacity) { - - canvas_opacity = p_opacity; -} - -void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { - - if (p_mode == canvas_blend_mode) - return; - switch (p_mode) { - - case VS::MATERIAL_BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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 VS::MATERIAL_BLEND_MODE_ADD: { - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - - } break; - case VS::MATERIAL_BLEND_MODE_SUB: { - - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case VS::MATERIAL_BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_DST_COLOR, GL_ZERO); - } break; - case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } break; - } - - canvas_blend_mode = p_mode; -} - -void RasterizerGLES2::canvas_begin_rect(const Transform2D &p_transform) { - - canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, p_transform); - canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, Transform2D()); -} - -void RasterizerGLES2::canvas_set_clip(bool p_clip, const Rect2 &p_rect) { - - if (p_clip) { - - glEnable(GL_SCISSOR_TEST); - //glScissor(viewport.x+p_rect.pos.x,viewport.y+ (viewport.height-(p_rect.pos.y+p_rect.size.height)), - - int x = p_rect.pos.x; - int y = window_size.height - (p_rect.pos.y + p_rect.size.y); - int w = p_rect.size.x; - int h = p_rect.size.y; - - glScissor(x, y, w, h); - - } else { - - glDisable(GL_SCISSOR_TEST); - } -} - -void RasterizerGLES2::canvas_end_rect() { - - //glPopMatrix(); -} - -RasterizerGLES2::Texture *RasterizerGLES2::_bind_canvas_texture(const RID &p_texture) { - - if (p_texture == canvas_tex && !rebind_texpixel_size) { - if (canvas_tex.is_valid()) { - Texture *texture = texture_owner.get(p_texture); - return texture; - } - return NULL; - } - - rebind_texpixel_size = false; - - if (p_texture.is_valid()) { - - Texture *texture = texture_owner.get(p_texture); - if (!texture) { - canvas_tex = RID(); - glBindTexture(GL_TEXTURE_2D, white_tex); - - return NULL; - } - - if (texture->render_target) - texture->render_target->last_pass = frame; - - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - canvas_tex = p_texture; - if (uses_texpixel_size) { - canvas_shader.set_uniform(CanvasShaderGLES2::TEXPIXEL_SIZE, Size2(1.0 / texture->width, 1.0 / texture->height)); - } - return texture; - - } else { - - glBindTexture(GL_TEXTURE_2D, white_tex); - canvas_tex = p_texture; - } - - return NULL; -} - -void RasterizerGLES2::canvas_draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width, bool p_antialiased) { - - _bind_canvas_texture(RID()); - Color c = p_color; - c.a *= canvas_opacity; - _set_color_attrib(c); - - Vector3 verts[2] = { - Vector3(p_from.x, p_from.y, 0), - Vector3(p_to.x, p_to.y, 0) - }; - -#ifdef GLEW_ENABLED - if (p_antialiased) - glEnable(GL_LINE_SMOOTH); -#endif - glLineWidth(p_width); - _draw_primitive(2, verts, 0, 0, 0); - -#ifdef GLEW_ENABLED - if (p_antialiased) - glDisable(GL_LINE_SMOOTH); -#endif - - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::_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 - -#ifndef GLES_NO_CLIENT_ARRAYS - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), p_vertices); - - if (p_colors) { - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), p_colors); - } else { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - } - - if (p_uvs) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), p_uvs); - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - glDrawArrays(prim[p_points], 0, p_points); - -#else - - glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer); - float b[32]; - int ofs = 0; - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(float) * 2, ((float *)0) + ofs); - for (int i = 0; i < p_points; i++) { - b[ofs++] = p_vertices[i].x; - b[ofs++] = p_vertices[i].y; - } - - if (p_colors) { - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(float) * 4, ((float *)0) + ofs); - for (int i = 0; i < p_points; i++) { - b[ofs++] = p_colors[i].r; - b[ofs++] = p_colors[i].g; - b[ofs++] = p_colors[i].b; - b[ofs++] = p_colors[i].a; - } - - } else { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - } - - if (p_uvs) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(float) * 2, ((float *)0) + ofs); - for (int i = 0; i < p_points; i++) { - b[ofs++] = p_uvs[i].x; - b[ofs++] = p_uvs[i].y; - } - - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - glBufferSubData(GL_ARRAY_BUFFER, 0, ofs * 4, &b[0]); - glDrawArrays(prim[p_points], 0, p_points); - glBindBuffer(GL_ARRAY_BUFFER, 0); - -#endif - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::_draw_gui_primitive2(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs, const Vector2 *p_uvs2) { - - static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), p_vertices); - if (p_colors) { - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), p_colors); - } else { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - } - - if (p_uvs) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), p_uvs); - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - if (p_uvs2) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); - glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false, sizeof(Vector2), p_uvs2); - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); - } - - glDrawArrays(prim[p_points], 0, p_points); - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::_draw_textured_quad(const Rect2 &p_rect, const Rect2 &p_src_region, const Size2 &p_tex_size, bool p_h_flip, bool p_v_flip, bool p_transpose) { - - Vector2 texcoords[4] = { - Vector2(p_src_region.pos.x / p_tex_size.width, - p_src_region.pos.y / p_tex_size.height), - - Vector2((p_src_region.pos.x + p_src_region.size.width) / p_tex_size.width, - p_src_region.pos.y / p_tex_size.height), - - Vector2((p_src_region.pos.x + p_src_region.size.width) / p_tex_size.width, - (p_src_region.pos.y + p_src_region.size.height) / p_tex_size.height), - - Vector2(p_src_region.pos.x / p_tex_size.width, - (p_src_region.pos.y + p_src_region.size.height) / p_tex_size.height) - }; - - if (p_transpose) { - SWAP(texcoords[1], texcoords[3]); - } - if (p_h_flip) { - SWAP(texcoords[0], texcoords[1]); - SWAP(texcoords[2], texcoords[3]); - } - if (p_v_flip) { - SWAP(texcoords[1], texcoords[2]); - SWAP(texcoords[0], texcoords[3]); - } - - Vector2 coords[4] = { - Vector2(p_rect.pos.x, p_rect.pos.y), - Vector2(p_rect.pos.x + p_rect.size.width, p_rect.pos.y), - Vector2(p_rect.pos.x + p_rect.size.width, p_rect.pos.y + p_rect.size.height), - Vector2(p_rect.pos.x, p_rect.pos.y + p_rect.size.height) - }; - - _draw_gui_primitive(4, coords, 0, texcoords); - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::_draw_quad(const Rect2 &p_rect) { - - Vector2 coords[4] = { - Vector2(p_rect.pos.x, p_rect.pos.y), - Vector2(p_rect.pos.x + p_rect.size.width, p_rect.pos.y), - Vector2(p_rect.pos.x + p_rect.size.width, p_rect.pos.y + p_rect.size.height), - Vector2(p_rect.pos.x, p_rect.pos.y + p_rect.size.height) - }; - - _draw_gui_primitive(4, coords, 0, 0); - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::canvas_draw_rect(const Rect2 &p_rect, int p_flags, const Rect2 &p_source, RID p_texture, const Color &p_modulate) { - - Color m = p_modulate; - m.a *= canvas_opacity; - _set_color_attrib(m); - Texture *texture = _bind_canvas_texture(p_texture); - - if (texture) { - - bool untile = false; - - if (p_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; - } - - if (!(p_flags & CANVAS_RECT_REGION)) { - - Rect2 region = Rect2(0, 0, texture->width, texture->height); - _draw_textured_quad(p_rect, region, region.size, p_flags & CANVAS_RECT_FLIP_H, p_flags & CANVAS_RECT_FLIP_V, p_flags & CANVAS_RECT_TRANSPOSE); - - } else { - - _draw_textured_quad(p_rect, p_source, Size2(texture->width, texture->height), p_flags & CANVAS_RECT_FLIP_H, p_flags & CANVAS_RECT_FLIP_V, p_flags & CANVAS_RECT_TRANSPOSE); - } - - 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 { - - //glDisable(GL_TEXTURE_2D); - _draw_quad(p_rect); - //print_line("rect: "+p_rect); - } - - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::canvas_draw_style_box(const Rect2 &p_rect, const Rect2 &p_src_region, RID p_texture, const float *p_margin, bool p_draw_center, const Color &p_modulate) { - - Color m = p_modulate; - m.a *= canvas_opacity; - _set_color_attrib(m); - - Texture *texture = _bind_canvas_texture(p_texture); - ERR_FAIL_COND(!texture); - - Rect2 region = p_src_region; - if (region.size.width <= 0) - region.size.width = texture->width; - if (region.size.height <= 0) - region.size.height = texture->height; - /* CORNERS */ - _draw_textured_quad( // top left - Rect2(p_rect.pos, Size2(p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP])), - Rect2(region.pos, Size2(p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP])), - Size2(texture->width, texture->height)); - - _draw_textured_quad( // top right - Rect2(Point2(p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y), Size2(p_margin[MARGIN_RIGHT], p_margin[MARGIN_TOP])), - Rect2(Point2(region.pos.x + region.size.width - p_margin[MARGIN_RIGHT], region.pos.y), Size2(p_margin[MARGIN_RIGHT], p_margin[MARGIN_TOP])), - Size2(texture->width, texture->height)); - - _draw_textured_quad( // bottom left - Rect2(Point2(p_rect.pos.x, p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT], p_margin[MARGIN_BOTTOM])), - Rect2(Point2(region.pos.x, region.pos.y + region.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT], p_margin[MARGIN_BOTTOM])), - Size2(texture->width, texture->height)); - - _draw_textured_quad( // bottom right - Rect2(Point2(p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT], p_margin[MARGIN_BOTTOM])), - Rect2(Point2(region.pos.x + region.size.width - p_margin[MARGIN_RIGHT], region.pos.y + region.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT], p_margin[MARGIN_BOTTOM])), - Size2(texture->width, texture->height)); - - Rect2 rect_center(p_rect.pos + Point2(p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2(p_rect.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], p_rect.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM])); - - Rect2 src_center(Point2(region.pos.x + p_margin[MARGIN_LEFT], region.pos.y + p_margin[MARGIN_TOP]), Size2(region.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], region.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM])); - - _draw_textured_quad( // top - Rect2(Point2(rect_center.pos.x, p_rect.pos.y), Size2(rect_center.size.width, p_margin[MARGIN_TOP])), - Rect2(Point2(src_center.pos.x, region.pos.y), Size2(src_center.size.width, p_margin[MARGIN_TOP])), - Size2(texture->width, texture->height)); - - _draw_textured_quad( // bottom - Rect2(Point2(rect_center.pos.x, rect_center.pos.y + rect_center.size.height), Size2(rect_center.size.width, p_margin[MARGIN_BOTTOM])), - Rect2(Point2(src_center.pos.x, src_center.pos.y + src_center.size.height), Size2(src_center.size.width, p_margin[MARGIN_BOTTOM])), - Size2(texture->width, texture->height)); - - _draw_textured_quad( // left - Rect2(Point2(p_rect.pos.x, rect_center.pos.y), Size2(p_margin[MARGIN_LEFT], rect_center.size.height)), - Rect2(Point2(region.pos.x, region.pos.y + p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_LEFT], src_center.size.height)), - Size2(texture->width, texture->height)); - - _draw_textured_quad( // right - Rect2(Point2(rect_center.pos.x + rect_center.size.width, rect_center.pos.y), Size2(p_margin[MARGIN_RIGHT], rect_center.size.height)), - Rect2(Point2(src_center.pos.x + src_center.size.width, region.pos.y + p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_RIGHT], src_center.size.height)), - Size2(texture->width, texture->height)); - - if (p_draw_center) { - - _draw_textured_quad( - rect_center, - src_center, - Size2(texture->width, texture->height)); - } - - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::canvas_draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width) { - - ERR_FAIL_COND(p_points.size() < 1); - _set_color_attrib(Color(1, 1, 1, canvas_opacity)); - _bind_canvas_texture(p_texture); - _draw_gui_primitive(p_points.size(), p_points.ptr(), p_colors.ptr(), p_uvs.ptr()); - - _rinfo.ci_draw_commands++; -} - -void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int *p_indices, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, const RID &p_texture, bool p_singlecolor) { - - bool do_colors = false; - Color m; - if (p_singlecolor) { - m = *p_colors; - m.a *= canvas_opacity; - _set_color_attrib(m); - } else if (!p_colors) { - m = Color(1, 1, 1, canvas_opacity); - _set_color_attrib(m); - } else - do_colors = true; - - Texture *texture = _bind_canvas_texture(p_texture); - -#ifndef GLES_NO_CLIENT_ARRAYS - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), p_vertices); - if (do_colors) { - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), p_colors); - } else { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - } - - if (texture && p_uvs) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), p_uvs); - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - if (p_indices) { -#ifdef GLEW_ENABLED - glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices); -#else - static const int _max_draw_poly_indices = 16 * 1024; // change this size if needed!!! - ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); - static uint16_t _draw_poly_indices[_max_draw_poly_indices]; - for (int i = 0; i < p_vertex_count; i++) { - _draw_poly_indices[i] = p_indices[i]; - }; - glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, _draw_poly_indices); -#endif - } else { - glDrawArrays(GL_TRIANGLES, 0, p_vertex_count); - } - -#else //WebGL specific impl. - glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer); - float *b = GlobalVertexBuffer; - int ofs = 0; - if (p_vertex_count > MAX_POLYGON_VERTICES) { - print_line("Too many vertices to render"); - return; - } - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(float) * 2, ((float *)0) + ofs); - for (int i = 0; i < p_vertex_count; i++) { - b[ofs++] = p_vertices[i].x; - b[ofs++] = p_vertices[i].y; - } - - if (p_colors && do_colors) { - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(float) * 4, ((float *)0) + ofs); - for (int i = 0; i < p_vertex_count; i++) { - b[ofs++] = p_colors[i].r; - b[ofs++] = p_colors[i].g; - b[ofs++] = p_colors[i].b; - b[ofs++] = p_colors[i].a; - } - - } else { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - } - - if (p_uvs) { - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(float) * 2, ((float *)0) + ofs); - for (int i = 0; i < p_vertex_count; i++) { - b[ofs++] = p_uvs[i].x; - b[ofs++] = p_uvs[i].y; - } - - } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - } - - glBufferSubData(GL_ARRAY_BUFFER, 0, ofs * 4, &b[0]); - - //bind the indices buffer. - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); - - static const int _max_draw_poly_indices = 16 * 1024; // change this size if needed!!! - ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); - static uint16_t _draw_poly_indices[_max_draw_poly_indices]; - for (int i = 0; i < p_vertex_count; i++) { - _draw_poly_indices[i] = p_indices[i]; - //OS::get_singleton()->print("ind: %d ", p_indices[i]); - }; - - //copy the data to GPU. - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, p_vertex_count * sizeof(uint16_t), &_draw_poly_indices[0]); - - //draw the triangles. - glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, 0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -#endif - - _rinfo.ci_draw_commands++; -}; - -void RasterizerGLES2::canvas_set_transform(const Transform2D &p_transform) { - - canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, p_transform); - - //canvas_transform = Variant(p_transform); -} - -RID RasterizerGLES2::canvas_light_occluder_create() { - - CanvasOccluder *co = memnew(CanvasOccluder); - co->index_id = 0; - co->vertex_id = 0; - co->len = 0; - - return canvas_occluder_owner.make_rid(co); -} - -void RasterizerGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) { - - CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); - ERR_FAIL_COND(!co); - - co->lines = p_lines; - - if (p_lines.size() != co->len) { - - if (co->index_id) - glDeleteBuffers(1, &co->index_id); - if (co->vertex_id) - glDeleteBuffers(1, &co->vertex_id); - - co->index_id = 0; - co->vertex_id = 0; - co->len = 0; - } - - if (p_lines.size()) { - - PoolVector<float> geometry; - PoolVector<uint16_t> indices; - int lc = p_lines.size(); - - geometry.resize(lc * 6); - indices.resize(lc * 3); - - PoolVector<float>::Write vw = geometry.write(); - PoolVector<uint16_t>::Write iw = indices.write(); - - PoolVector<Vector2>::Read lr = p_lines.read(); - - const int POLY_HEIGHT = 16384; - - for (int i = 0; i < lc / 2; i++) { - - vw[i * 12 + 0] = lr[i * 2 + 0].x; - vw[i * 12 + 1] = lr[i * 2 + 0].y; - vw[i * 12 + 2] = POLY_HEIGHT; - - vw[i * 12 + 3] = lr[i * 2 + 1].x; - vw[i * 12 + 4] = lr[i * 2 + 1].y; - vw[i * 12 + 5] = POLY_HEIGHT; - - vw[i * 12 + 6] = lr[i * 2 + 1].x; - vw[i * 12 + 7] = lr[i * 2 + 1].y; - vw[i * 12 + 8] = -POLY_HEIGHT; - - vw[i * 12 + 9] = lr[i * 2 + 0].x; - vw[i * 12 + 10] = lr[i * 2 + 0].y; - vw[i * 12 + 11] = -POLY_HEIGHT; - - iw[i * 6 + 0] = i * 4 + 0; - iw[i * 6 + 1] = i * 4 + 1; - iw[i * 6 + 2] = i * 4 + 2; - - iw[i * 6 + 3] = i * 4 + 2; - iw[i * 6 + 4] = i * 4 + 3; - iw[i * 6 + 5] = i * 4 + 0; - } - - //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush - - if (!co->vertex_id) { - glGenBuffers(1, &co->vertex_id); - glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW); - } else { - - glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr()); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - if (!co->index_id) { - - glGenBuffers(1, &co->index_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_STATIC_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; - } -} - -RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) { - - CanvasLightShadow *cls = memnew(CanvasLightShadow); - if (p_width > max_texture_size) - p_width = max_texture_size; - - cls->size = p_width; - glActiveTexture(GL_TEXTURE0); - - glGenFramebuffers(1, &cls->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); - - // Create a render buffer - glGenRenderbuffers(1, &cls->rbo); - glBindRenderbuffer(GL_RENDERBUFFER, cls->rbo); - - // Create a texture for storing the depth - glGenTextures(1, &cls->depth); - glBindTexture(GL_TEXTURE_2D, cls->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Remove artifact on the edges of the shadowmap - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - cls->height = 16; - - //print_line("ERROR? "+itos(glGetError())); - if (read_depth_supported) { - - // We'll use a depth texture to store the depths in the shadow map - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cls->size, cls->height, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - -#ifdef GLEW_ENABLED - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#endif - - // Attach the depth texture to FBO depth attachment point - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, cls->depth, 0); - -#ifdef GLEW_ENABLED - glDrawBuffer(GL_NONE); -#endif - - } else { - // We'll use a RGBA texture into which we pack the depth info - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - // Attach the RGBA texture to FBO color attachment point - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, cls->depth, 0); - cls->rgba = cls->depth; - - // Allocate 16-bit depth buffer - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height); - - // Attach the render buffer as depth buffer - will be ignored - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, cls->rbo); - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); -//printf("errnum: %x\n",status); -#ifdef GLEW_ENABLED - if (read_depth_supported) { - //glDrawBuffer(GL_BACK); - } -#endif - glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); - DEBUG_TEST_ERROR("2D Shadow Buffer Init"); - ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID()); - -#ifdef GLEW_ENABLED - if (read_depth_supported) { - //glDrawBuffer(GL_BACK); - } -#endif - - return canvas_light_shadow_owner.make_rid(cls); -} - -void RasterizerGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, CanvasLightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) { - - CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_buffer); - ERR_FAIL_COND(!cls); - - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DITHER); - glDisable(GL_CULL_FACE); - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - glDepthMask(true); - - glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); - - if (!use_rgba_shadowmaps) - glColorMask(0, 0, 0, 0); - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - 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 near = p_near; - real_t far = p_far; - real_t aspect = 1.0; - - real_t ymax = near * 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, near, far); - } - - Vector3 cam_target = Matrix3(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()); - - canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX, projection); - canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX, light); - - if (i == 0) - *p_xform_cache = projection; - - glViewport(0, (cls->height / 4) * i, cls->size, cls->height / 4); - - CanvasLightOccluderInstance *instance = p_occluders; - - while (instance) { - - CanvasOccluder *cc = canvas_occluder_owner.get(instance->polygon_buffer); - if (!cc || cc->len == 0 || !(p_light_mask & instance->light_mask)) { - - instance = instance->next; - continue; - } - - canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX, instance->xform_cache); - if (cull != instance->cull_cache) { - - cull = instance->cull_cache; - switch (cull) { - case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { - - glDisable(GL_CULL_FACE); - - } break; - case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { - - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); - } break; - case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { - - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - } break; - } - } - /* - if (i==0) { - for(int i=0;i<cc->lines.size();i++) { - Vector2 p = instance->xform_cache.xform(cc->lines.get(i)); - Plane pp(Vector3(p.x,p.y,0),1); - pp.normal = light.xform(pp.normal); - pp = projection.xform4(pp); - print_line(itos(i)+": "+pp.normal/pp.d); - //pp=light_mat.xform4(pp); - //print_line(itos(i)+": "+pp.normal/pp.d); - } - } -*/ - glBindBuffer(GL_ARRAY_BUFFER, cc->vertex_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cc->index_id); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); - glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, 0); - - instance = instance->next; - } - } - - glDisableVertexAttribArray(VS::ARRAY_VERTEX); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - if (shadow_filter == SHADOW_FILTER_ESM) { -//blur the buffer -#if 0 - //this is ignord, it did not make any difference.. - if (read_depth_supported) { - glDepthFunc(GL_ALWAYS); - } else { - glDisable(GL_DEPTH_TEST); - glDepthMask(false); - } - glDisable(GL_CULL_FACE); - glViewport(0, 0, cls->size,cls->height); - - int passes=1; - CanvasLightShadow *blur = canvas_light_shadow_owner.get(canvas_shadow_blur); - - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,true); - copy_shader.bind(); - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,1); - copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1); - glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0); - - for(int i=0;i<passes;i++) { - - glBindFramebuffer(GL_FRAMEBUFFER, blur->fbo); - glActiveTexture(GL_TEXTURE0); - - if (read_depth_supported) - glBindTexture(GL_TEXTURE_2D,cls->depth); - else - glBindTexture(GL_TEXTURE_2D,cls->rgba); - - - { - Vector2 src_sb_uv[4]={ - Vector2( 0, 1), - Vector2( 1, 1), - Vector2( 1, 0), - Vector2( 0, 0) - }; - static const Vector2 dst_pos[4]={ - Vector2(-1, 1), - Vector2( 1, 1), - Vector2( 1,-1), - Vector2(-1,-1) - }; - - - - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/cls->size); - _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv); - } - - glActiveTexture(GL_TEXTURE0); - if (read_depth_supported) - glBindTexture(GL_TEXTURE_2D,blur->depth); - else - glBindTexture(GL_TEXTURE_2D,blur->rgba); - - glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); - - { - float hlimit = float(cls->size) / blur->size; - //hlimit*=2.0; - Vector2 src_sb_uv[4]={ - Vector2( 0, 1), - Vector2( hlimit, 1), - Vector2( hlimit, 0), - Vector2( 0, 0) - }; - static const Vector2 dst_pos[4]={ - Vector2(-1, 1), - Vector2( 1, 1), - Vector2( 1,-1), - Vector2(-1,-1) - }; - - - copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/blur->size); - _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv); - } - - } - copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false); - glDepthFunc(GL_LEQUAL); -#endif - } - - glBindFramebuffer(GL_FRAMEBUFFER, current_rt ? current_rt->fbo : base_framebuffer); - glColorMask(1, 1, 1, 1); -} - -void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight *p_lights_with_shadow) { - - CanvasLight *light = p_lights_with_shadow; - - canvas_begin(); //reset - - int h = 10; - int w = viewport.width; - int ofs = h; - - //print_line(" debug lights "); - while (light) { - - //print_line("debug light"); - if (light->shadow_buffer.is_valid()) { - - //print_line("sb is valid"); - CanvasLightShadow *sb = canvas_light_shadow_owner.get(light->shadow_buffer); - if (sb) { - glActiveTexture(GL_TEXTURE0); - if (read_depth_supported) - glBindTexture(GL_TEXTURE_2D, sb->depth); - else - glBindTexture(GL_TEXTURE_2D, sb->rgba); - _draw_textured_quad(Rect2(h, ofs, w - h * 2, h), Rect2(0, 0, sb->size, 10), Size2(sb->size, 10), false, false); - ofs += h * 2; - } - } - - light = light->shadows_next_ptr; - } -} - -void RasterizerGLES2::_canvas_normal_set_flip(const Vector2 &p_flip) { - - if (p_flip == normal_flip) - return; - normal_flip = p_flip; - canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP, normal_flip); -} - -template <bool use_normalmap> -void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item, CanvasItem *current_clip, bool &reclip) { - - int cc = p_item->commands.size(); - CanvasItem::Command **commands = p_item->commands.ptr(); - - for (int i = 0; i < cc; i++) { - - CanvasItem::Command *c = commands[i]; - - switch (c->type) { - case CanvasItem::Command::TYPE_LINE: { - - CanvasItem::CommandLine *line = static_cast<CanvasItem::CommandLine *>(c); - canvas_draw_line(line->from, line->to, line->color, line->width, line->antialiased); - } break; - case CanvasItem::Command::TYPE_RECT: { - - CanvasItem::CommandRect *rect = static_cast<CanvasItem::CommandRect *>(c); -//canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); -#if 0 - int flags=0; - - if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { - flags|=Rasterizer::CANVAS_RECT_REGION; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { - flags|=Rasterizer::CANVAS_RECT_TILE; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { - - flags|=Rasterizer::CANVAS_RECT_FLIP_H; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { - - flags|=Rasterizer::CANVAS_RECT_FLIP_V; - } -#else - - int flags = rect->flags; -#endif - if (use_normalmap) - _canvas_normal_set_flip(Vector2((flags & CANVAS_RECT_FLIP_H) ? -1 : 1, (flags & CANVAS_RECT_FLIP_V) ? -1 : 1)); - canvas_draw_rect(rect->rect, flags, rect->source, rect->texture, rect->modulate); - - } break; - case CanvasItem::Command::TYPE_STYLE: { - - CanvasItem::CommandStyle *style = static_cast<CanvasItem::CommandStyle *>(c); - if (use_normalmap) - _canvas_normal_set_flip(Vector2(1, 1)); - canvas_draw_style_box(style->rect, style->source, style->texture, style->margin, style->draw_center, style->color); - - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { - - if (use_normalmap) - _canvas_normal_set_flip(Vector2(1, 1)); - CanvasItem::CommandPrimitive *primitive = static_cast<CanvasItem::CommandPrimitive *>(c); - canvas_draw_primitive(primitive->points, primitive->colors, primitive->uvs, primitive->texture, primitive->width); - } break; - case CanvasItem::Command::TYPE_POLYGON: { - - if (use_normalmap) - _canvas_normal_set_flip(Vector2(1, 1)); - CanvasItem::CommandPolygon *polygon = static_cast<CanvasItem::CommandPolygon *>(c); - canvas_draw_polygon(polygon->count, polygon->indices.ptr(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->texture, polygon->colors.size() == 1); - - } break; - - case CanvasItem::Command::TYPE_POLYGON_PTR: { - - if (use_normalmap) - _canvas_normal_set_flip(Vector2(1, 1)); - CanvasItem::CommandPolygonPtr *polygon = static_cast<CanvasItem::CommandPolygonPtr *>(c); - canvas_draw_polygon(polygon->count, polygon->indices, polygon->points, polygon->uvs, polygon->colors, polygon->texture, false); - } break; - case CanvasItem::Command::TYPE_CIRCLE: { - - CanvasItem::CommandCircle *circle = static_cast<CanvasItem::CommandCircle *>(c); - static const int numpoints = 32; - Vector2 points[numpoints + 1]; - points[numpoints] = circle->pos; - int indices[numpoints * 3]; - - for (int i = 0; i < numpoints; i++) { - - points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / numpoints), Math::cos(i * Math_PI * 2.0 / numpoints)) * circle->radius; - indices[i * 3 + 0] = i; - indices[i * 3 + 1] = (i + 1) % numpoints; - indices[i * 3 + 2] = numpoints; - } - canvas_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 CanvasItem::Command::TYPE_TRANSFORM: { - - CanvasItem::CommandTransform *transform = static_cast<CanvasItem::CommandTransform *>(c); - canvas_set_transform(transform->xform); - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - CanvasItem::CommandBlendMode *bm = static_cast<CanvasItem::CommandBlendMode *>(c); - canvas_set_blend_mode(bm->blend_mode); - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - CanvasItem::CommandClipIgnore *ci = static_cast<CanvasItem::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 x; - int y; - int w; - int h; - - if (current_rt) { - x = current_clip->final_clip_rect.pos.x; - y = current_clip->final_clip_rect.pos.y; - w = current_clip->final_clip_rect.size.x; - h = current_clip->final_clip_rect.size.y; - } else { - x = current_clip->final_clip_rect.pos.x; - y = window_size.height - (current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y); - w = current_clip->final_clip_rect.size.x; - h = current_clip->final_clip_rect.size.y; - } - - glScissor(x, y, w, h); - - reclip = false; - } - } - } - - } break; - } - } -} - -void RasterizerGLES2::_canvas_item_setup_shader_params(ShaderMaterial *material, Shader *shader) { - - if (canvas_shader.bind()) - rebind_texpixel_size = true; - - if (material->shader_version != shader->version) { - //todo optimize uniforms - material->shader_version = shader->version; - } - - if (shader->has_texscreen && framebuffer.active) { - - int x = viewport.x; - int y = window_size.height - (viewport.height + viewport.y); - - canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT, Vector2(float(viewport.width) / framebuffer.width, float(viewport.height) / framebuffer.height)); - canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP, Color(float(x) / framebuffer.width, float(y) / framebuffer.height, float(x + viewport.width) / framebuffer.width, float(y + viewport.height) / framebuffer.height)); - canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX, max_texture_units - 1); - glActiveTexture(GL_TEXTURE0 + max_texture_units - 1); - glBindTexture(GL_TEXTURE_2D, framebuffer.sample_color); - if (framebuffer.scale == 1 && !canvas_texscreen_used) { -#ifdef GLEW_ENABLED - if (current_rt) { - glReadBuffer(GL_COLOR_ATTACHMENT0); - } else { - glReadBuffer(GL_BACK); - } -#endif - if (current_rt) { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport.x, viewport.y, viewport.x, viewport.y, viewport.width, viewport.height); - canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP, Color(float(x) / framebuffer.width, float(viewport.y) / framebuffer.height, float(x + viewport.width) / framebuffer.width, float(y + viewport.height) / framebuffer.height)); - //window_size.height-(viewport.height+viewport.y) - } else { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, y, x, y, viewport.width, viewport.height); - } - - canvas_texscreen_used = true; - } - - glActiveTexture(GL_TEXTURE0); - } - - if (shader->has_screen_uv) { - canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT, Vector2(1.0 / viewport.width, 1.0 / viewport.height)); - } - - uses_texpixel_size = shader->uses_texpixel_size; -} - -void RasterizerGLES2::_canvas_item_setup_shader_uniforms(ShaderMaterial *material, Shader *shader) { - - //this can be optimized.. - int tex_id = 1; - int idx = 0; - for (Map<StringName, ShaderLanguage::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { - - Map<StringName, Variant>::Element *F = material->shader_param.find(E->key()); - - if ((E->get().type == ShaderLanguage::TYPE_TEXTURE || E->get().type == ShaderLanguage::TYPE_CUBEMAP)) { - - RID rid; - if (F) { - rid = F->get(); - } - - if (!rid.is_valid()) { - - Map<StringName, RID>::Element *DT = shader->default_textures.find(E->key()); - if (DT) { - rid = DT->get(); - } - } - - if (rid.is_valid()) { - - int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. - - glActiveTexture(GL_TEXTURE0 + tex_id); - Texture *t = texture_owner.get(rid); - if (!t) - glBindTexture(GL_TEXTURE_2D, white_tex); - else - glBindTexture(t->target, t->tex_id); - - glUniform1i(loc, tex_id); - tex_id++; - } - } else { - Variant &v = F ? F->get() : E->get().default_value; - canvas_shader.set_custom_uniform(idx, v); - } - - idx++; - } - - if (tex_id > 1) { - glActiveTexture(GL_TEXTURE0); - } - - if (shader->uses_time) { - canvas_shader.set_uniform(CanvasShaderGLES2::TIME, Math::fmod(last_time, shader_time_rollback)); - draw_next_frame = true; - } - //if uses TIME - draw_next_frame=true -} - -void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list, int p_z, const Color &p_modulate, CanvasLight *p_light) { - - CanvasItem *current_clip = NULL; - Shader *shader_cache = NULL; - - bool rebind_shader = true; - - canvas_opacity = 1.0; - canvas_use_modulate = p_modulate != Color(1, 1, 1, 1); - canvas_modulate = p_modulate; - canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE, canvas_use_modulate); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD, false); - - bool reset_modulate = false; - bool prev_distance_field = false; - - while (p_item_list) { - - CanvasItem *ci = p_item_list; - - if (ci->vp_render) { - if (draw_viewport_func) { - draw_viewport_func(ci->vp_render->owner, ci->vp_render->udata, ci->vp_render->rect); - } - memdelete(ci->vp_render); - ci->vp_render = NULL; - canvas_last_material = NULL; - canvas_use_modulate = p_modulate != Color(1, 1, 1, 1); - canvas_modulate = p_modulate; - canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE, canvas_use_modulate); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD, false); - prev_distance_field = false; - rebind_shader = true; - reset_modulate = true; - } - - if (prev_distance_field != ci->distance_field) { - - canvas_shader.set_conditional(CanvasShaderGLES2::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); - //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 x = viewport.x+current_clip->final_clip_rect.pos.x; - int y = window_size.height-(viewport.y+current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y); - int w = current_clip->final_clip_rect.size.x; - int h = current_clip->final_clip_rect.size.y; -*/ - int x; - int y; - int w; - int h; - - if (current_rt) { - x = current_clip->final_clip_rect.pos.x; - y = current_clip->final_clip_rect.pos.y; - w = current_clip->final_clip_rect.size.x; - h = current_clip->final_clip_rect.size.y; - } else { - x = current_clip->final_clip_rect.pos.x; - y = window_size.height - (current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y); - w = current_clip->final_clip_rect.size.x; - h = current_clip->final_clip_rect.size.y; - } - - glScissor(x, y, w, h); - - } else { - - glDisable(GL_SCISSOR_TEST); - } - } - - if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale == 1) { - - Rect2 rect; - int x, y; - - if (ci->copy_back_buffer->full) { - - x = viewport.x; - y = window_size.height - (viewport.height + viewport.y); - } else { - x = viewport.x + ci->copy_back_buffer->screen_rect.pos.x; - y = window_size.height - (viewport.y + ci->copy_back_buffer->screen_rect.pos.y + ci->copy_back_buffer->screen_rect.size.y); - } - glActiveTexture(GL_TEXTURE0 + max_texture_units - 1); - glBindTexture(GL_TEXTURE_2D, framebuffer.sample_color); - -#ifdef GLEW_ENABLED - if (current_rt) { - glReadBuffer(GL_COLOR_ATTACHMENT0); - } else { - glReadBuffer(GL_BACK); - } -#endif - if (current_rt) { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport.x, viewport.y, viewport.x, viewport.y, viewport.width, viewport.height); - //window_size.height-(viewport.height+viewport.y) - } else { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, y, x, y, viewport.width, viewport.height); - } - - canvas_texscreen_used = true; - glActiveTexture(GL_TEXTURE0); - } - - //begin rect - CanvasItem *material_owner = ci->material_owner ? ci->material_owner : ci; - ShaderMaterial *material = material_owner->material; - - if (material != canvas_last_material || rebind_shader) { - - Shader *shader = NULL; - if (material && material->shader.is_valid()) { - shader = shader_owner.get(material->shader); - if (shader && !shader->valid) { - shader = NULL; - } - } - - shader_cache = shader; - - if (shader) { - canvas_shader.set_custom_shader(shader->custom_code_id); - _canvas_item_setup_shader_params(material, shader); - } else { - shader_cache = NULL; - canvas_shader.set_custom_shader(0); - canvas_shader.bind(); - uses_texpixel_size = false; - } - - canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX, canvas_transform); - if (canvas_use_modulate) - reset_modulate = true; - canvas_last_material = material; - rebind_shader = false; - } - - if (material && shader_cache) { - - _canvas_item_setup_shader_uniforms(material, shader_cache); - } - - bool unshaded = (material && material->shading_mode == VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode != VS::MATERIAL_BLEND_MODE_MIX; - - if (unshaded) { - canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE, Color(1, 1, 1, 1)); - reset_modulate = true; - } else if (reset_modulate) { - canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE, canvas_modulate); - reset_modulate = false; - } - - canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, ci->final_transform); - canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, Transform2D()); - - bool reclip = false; - - if (ci == p_item_list || ci->blend_mode != canvas_blend_mode) { - - switch (ci->blend_mode) { - - case VS::MATERIAL_BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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 VS::MATERIAL_BLEND_MODE_ADD: { - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - - } break; - case VS::MATERIAL_BLEND_MODE_SUB: { - - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } break; - case VS::MATERIAL_BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_DST_COLOR, GL_ZERO); - } break; - case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } break; - } - - canvas_blend_mode = ci->blend_mode; - } - - canvas_opacity = ci->final_opacity; - - if (unshaded || (p_modulate.a > 0.001 && (!material || material->shading_mode != VS::CANVAS_ITEM_SHADING_ONLY_LIGHT) && !ci->light_masked)) - _canvas_item_render_commands<false>(ci, current_clip, reclip); - - if (canvas_blend_mode == VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) { - - CanvasLight *light = p_light; - bool light_used = false; - VS::CanvasLightMode mode = VS::CANVAS_LIGHT_MODE_ADD; - - 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) { - - canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, true); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE, false); - light_used = true; - normal_flip = Vector2(1, 1); - } - - bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask & light->item_shadow_mask; - - canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow); - - bool light_rebind = canvas_shader.bind(); - - if (light_rebind) { - - if (material && shader_cache) { - _canvas_item_setup_shader_params(material, shader_cache); - _canvas_item_setup_shader_uniforms(material, shader_cache); - } - - canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, ci->final_transform); - canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, Transform2D()); - canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX, canvas_transform); - if (canvas_use_modulate) - canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE, canvas_modulate); - canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP, Vector2(1, 1)); - canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE, 1.0 / light->shadow_buffer_size); - } - - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX, light->light_shader_xform); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS, light->light_shader_pos); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR, Color(light->color.r * light->energy, light->color.g * light->energy, light->color.b * light->energy, light->color.a)); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT, light->height); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX, light->xform_cache.affine_inverse()); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, light->mode == VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0); - - if (has_shadow) { - - CanvasLightShadow *cls = canvas_light_shadow_owner.get(light->shadow_buffer); - glActiveTexture(GL_TEXTURE0 + max_texture_units - 3); - if (read_depth_supported) - glBindTexture(GL_TEXTURE_2D, cls->depth); - else - glBindTexture(GL_TEXTURE_2D, cls->rgba); - - canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE, max_texture_units - 3); - canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX, light->shadow_matrix_cache); - canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER, light->shadow_esm_mult); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR, light->shadow_color); - } - - glActiveTexture(GL_TEXTURE0 + max_texture_units - 2); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE, max_texture_units - 2); - Texture *t = texture_owner.get(light->texture); - if (!t) { - glBindTexture(GL_TEXTURE_2D, white_tex); - } else { - - glBindTexture(t->target, t->tex_id); - } - - glActiveTexture(GL_TEXTURE0); - _canvas_item_render_commands<true>(ci, current_clip, reclip); //redraw using light - } - - light = light->next_ptr; - } - - if (light_used) { - - canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, false); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE, canvas_use_modulate); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, false); - - canvas_shader.bind(); - - if (material && shader_cache) { - _canvas_item_setup_shader_params(material, shader_cache); - _canvas_item_setup_shader_uniforms(material, shader_cache); - } - - canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, ci->final_transform); - canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, Transform2D()); - if (canvas_use_modulate) - canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE, canvas_modulate); - - glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_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); - } - } - } - - if (reclip) { - - 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 x; - int y; - int w; - int h; - - if (current_rt) { - x = current_clip->final_clip_rect.pos.x; - y = current_clip->final_clip_rect.pos.y; - w = current_clip->final_clip_rect.size.x; - h = current_clip->final_clip_rect.size.y; - } else { - x = current_clip->final_clip_rect.pos.x; - y = window_size.height - (current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y); - w = current_clip->final_clip_rect.size.x; - h = current_clip->final_clip_rect.size.y; - } - - glScissor(x, y, w, h); - } - - p_item_list = p_item_list->next; - } - - if (current_clip) { - glDisable(GL_SCISSOR_TEST); - } -} - -/* ENVIRONMENT */ - -RID RasterizerGLES2::environment_create() { - - Environment *env = memnew(Environment); - return environment_owner.make_rid(env); -} - -void RasterizerGLES2::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) { - - ERR_FAIL_INDEX(p_bg, VS::ENV_BG_MAX); - Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_mode = p_bg; -} - -VS::EnvironmentBG RasterizerGLES2::environment_get_background(RID p_env) const { - - const Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); - return env->bg_mode; -} - -void RasterizerGLES2::environment_set_background_param(RID p_env, VS::EnvironmentBGParam p_param, const Variant &p_value) { - - ERR_FAIL_INDEX(p_param, VS::ENV_BG_PARAM_MAX); - Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_param[p_param] = p_value; -} -Variant RasterizerGLES2::environment_get_background_param(RID p_env, VS::EnvironmentBGParam p_param) const { - - ERR_FAIL_INDEX_V(p_param, VS::ENV_BG_PARAM_MAX, Variant()); - const Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env, Variant()); - return env->bg_param[p_param]; -} - -void RasterizerGLES2::environment_set_enable_fx(RID p_env, VS::EnvironmentFx p_effect, bool p_enabled) { - - ERR_FAIL_INDEX(p_effect, VS::ENV_FX_MAX); - Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_enabled[p_effect] = p_enabled; -} -bool RasterizerGLES2::environment_is_fx_enabled(RID p_env, VS::EnvironmentFx p_effect) const { - - ERR_FAIL_INDEX_V(p_effect, VS::ENV_FX_MAX, false); - const Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env, false); - return env->fx_enabled[p_effect]; -} - -void RasterizerGLES2::environment_fx_set_param(RID p_env, VS::EnvironmentFxParam p_param, const Variant &p_value) { - - ERR_FAIL_INDEX(p_param, VS::ENV_FX_PARAM_MAX); - Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_param[p_param] = p_value; -} -Variant RasterizerGLES2::environment_fx_get_param(RID p_env, VS::EnvironmentFxParam p_param) const { - - ERR_FAIL_INDEX_V(p_param, VS::ENV_FX_PARAM_MAX, Variant()); - const Environment *env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env, Variant()); - return env->fx_param[p_param]; -} - -RID RasterizerGLES2::sampled_light_dp_create(int p_width, int p_height) { - - SampledLight *slight = memnew(SampledLight); - slight->w = p_width; - slight->h = p_height; - slight->multiplier = 1.0; - slight->is_float = float_linear_supported; - - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &slight->texture); - glBindTexture(GL_TEXTURE_2D, slight->texture); - // for debug, but glitchy - //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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Remove artifact on the edges of the shadowmap - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - if (slight->is_float) { -#ifdef GLEW_ENABLED - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_width, p_height, 0, GL_RGBA, GL_FLOAT, NULL); -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_FLOAT, NULL); -#endif - } else { - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } - - return sampled_light_owner.make_rid(slight); -} - -void RasterizerGLES2::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { - - SampledLight *slight = sampled_light_owner.get(p_sampled_light); - ERR_FAIL_COND(!slight); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, slight->texture); - - if (slight->is_float) { - -#ifdef GLEW_ENABLED - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, slight->w, slight->h, GL_RGBA, GL_FLOAT, p_data); -#else - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, slight->w, slight->h, GL_RGBA, GL_FLOAT, p_data); -#endif - - } else { - //convert to bytes - uint8_t *tex8 = (uint8_t *)alloca(slight->w * slight->h * 4); - const float *src = (const float *)p_data; - - for (int i = 0; i < slight->w * slight->h * 4; i++) { - - tex8[i] = Math::fast_ftoi(CLAMP(src[i] * 255.0, 0.0, 255.0)); - } - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, slight->w, slight->h, GL_RGBA, GL_UNSIGNED_BYTE, p_data); - } - - slight->multiplier = p_multiplier; -} - -/*MISC*/ - -bool RasterizerGLES2::is_texture(const RID &p_rid) const { - - return texture_owner.owns(p_rid); -} -bool RasterizerGLES2::is_material(const RID &p_rid) const { - - return material_owner.owns(p_rid); -} -bool RasterizerGLES2::is_mesh(const RID &p_rid) const { - - return mesh_owner.owns(p_rid); -} -bool RasterizerGLES2::is_immediate(const RID &p_rid) const { - - return immediate_owner.owns(p_rid); -} -bool RasterizerGLES2::is_multimesh(const RID &p_rid) const { - - return multimesh_owner.owns(p_rid); -} -bool RasterizerGLES2::is_particles(const RID &p_beam) const { - - return particles_owner.owns(p_beam); -} - -bool RasterizerGLES2::is_light(const RID &p_rid) const { - - return light_owner.owns(p_rid); -} -bool RasterizerGLES2::is_light_instance(const RID &p_rid) const { - - return light_instance_owner.owns(p_rid); -} -bool RasterizerGLES2::is_particles_instance(const RID &p_rid) const { - - return particles_instance_owner.owns(p_rid); -} -bool RasterizerGLES2::is_skeleton(const RID &p_rid) const { - - return skeleton_owner.owns(p_rid); -} -bool RasterizerGLES2::is_environment(const RID &p_rid) const { - - return environment_owner.owns(p_rid); -} -bool RasterizerGLES2::is_shader(const RID &p_rid) const { - - return shader_owner.owns(p_rid); -} - -bool RasterizerGLES2::is_canvas_light_occluder(const RID &p_rid) const { - - return false; -} - -void RasterizerGLES2::free(const RID &p_rid) { - if (texture_owner.owns(p_rid)) { - - // delete the texture - Texture *texture = texture_owner.get(p_rid); - - //glDeleteTextures( 1,&texture->tex_id ); - _rinfo.texture_mem -= texture->total_data_size; - texture_owner.free(p_rid); - memdelete(texture); - - } else if (shader_owner.owns(p_rid)) { - - // delete the texture - Shader *shader = shader_owner.get(p_rid); - - switch (shader->mode) { - case VS::SHADER_MATERIAL: { - material_shader.free_custom_shader(shader->custom_code_id); - } break; - case VS::SHADER_POST_PROCESS: { - //postprocess_shader.free_custom_shader(shader->custom_code_id); - } break; - } - - if (shader->dirty_list.in_list()) - _shader_dirty_list.remove(&shader->dirty_list); - - //material_shader.free_custom_shader(shader->custom_code_id); - shader_owner.free(p_rid); - memdelete(shader); - - } else if (material_owner.owns(p_rid)) { - - Material *material = material_owner.get(p_rid); - ERR_FAIL_COND(!material); - - _free_fixed_material(p_rid); //just in case - material_owner.free(p_rid); - memdelete(material); - - } else if (mesh_owner.owns(p_rid)) { - - Mesh *mesh = mesh_owner.get(p_rid); - ERR_FAIL_COND(!mesh); - for (int i = 0; i < mesh->surfaces.size(); i++) { - - Surface *surface = mesh->surfaces[i]; - if (surface->array_local != 0) { - memfree(surface->array_local); - }; - if (surface->index_array_local != 0) { - memfree(surface->index_array_local); - }; - - if (mesh->morph_target_count > 0) { - - for (int i = 0; i < mesh->morph_target_count; i++) { - - memdelete_arr(surface->morph_targets_local[i].array); - } - memdelete_arr(surface->morph_targets_local); - surface->morph_targets_local = NULL; - } - - if (surface->vertex_id) - glDeleteBuffers(1, &surface->vertex_id); - if (surface->index_id) - glDeleteBuffers(1, &surface->index_id); - - memdelete(surface); - }; - - mesh->surfaces.clear(); - - mesh_owner.free(p_rid); - memdelete(mesh); - - } else if (multimesh_owner.owns(p_rid)) { - - MultiMesh *multimesh = multimesh_owner.get(p_rid); - ERR_FAIL_COND(!multimesh); - - if (multimesh->tex_id) { - glDeleteTextures(1, &multimesh->tex_id); - } - - multimesh_owner.free(p_rid); - memdelete(multimesh); - - } else if (immediate_owner.owns(p_rid)) { - - Immediate *immediate = immediate_owner.get(p_rid); - ERR_FAIL_COND(!immediate); - - immediate_owner.free(p_rid); - memdelete(immediate); - } else if (particles_owner.owns(p_rid)) { - - Particles *particles = particles_owner.get(p_rid); - ERR_FAIL_COND(!particles); - - particles_owner.free(p_rid); - memdelete(particles); - } else if (particles_instance_owner.owns(p_rid)) { - - ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); - ERR_FAIL_COND(!particles_isntance); - - particles_instance_owner.free(p_rid); - memdelete(particles_isntance); - - } else if (skeleton_owner.owns(p_rid)) { - - Skeleton *skeleton = skeleton_owner.get(p_rid); - ERR_FAIL_COND(!skeleton); - - if (skeleton->dirty_list.in_list()) - _skeleton_dirty_list.remove(&skeleton->dirty_list); - if (skeleton->tex_id) { - glDeleteTextures(1, &skeleton->tex_id); - } - skeleton_owner.free(p_rid); - memdelete(skeleton); - - } else if (light_owner.owns(p_rid)) { - - Light *light = light_owner.get(p_rid); - ERR_FAIL_COND(!light) - - light_owner.free(p_rid); - memdelete(light); - - } else if (light_instance_owner.owns(p_rid)) { - - LightInstance *light_instance = light_instance_owner.get(p_rid); - ERR_FAIL_COND(!light_instance); - light_instance->clear_shadow_buffers(); - light_instance_owner.free(p_rid); - memdelete(light_instance); - - } else if (environment_owner.owns(p_rid)) { - - Environment *env = environment_owner.get(p_rid); - ERR_FAIL_COND(!env); - - environment_owner.free(p_rid); - memdelete(env); - - } else if (viewport_data_owner.owns(p_rid)) { - - ViewportData *viewport_data = viewport_data_owner.get(p_rid); - ERR_FAIL_COND(!viewport_data); - glDeleteFramebuffers(1, &viewport_data->lum_fbo); - glDeleteTextures(1, &viewport_data->lum_color); - viewport_data_owner.free(p_rid); - memdelete(viewport_data); - - } else if (render_target_owner.owns(p_rid)) { - - RenderTarget *render_target = render_target_owner.get(p_rid); - ERR_FAIL_COND(!render_target); - render_target_set_size(p_rid, 0, 0); //clears framebuffer - texture_owner.free(render_target->texture); - memdelete(render_target->texture_ptr); - render_target_owner.free(p_rid); - memdelete(render_target); - } else if (sampled_light_owner.owns(p_rid)) { - - SampledLight *sampled_light = sampled_light_owner.get(p_rid); - ERR_FAIL_COND(!sampled_light); - glDeleteTextures(1, &sampled_light->texture); - sampled_light_owner.free(p_rid); - memdelete(sampled_light); - } else if (canvas_occluder_owner.owns(p_rid)) { - - CanvasOccluder *co = canvas_occluder_owner.get(p_rid); - if (co->index_id) - glDeleteBuffers(1, &co->index_id); - if (co->vertex_id) - glDeleteBuffers(1, &co->vertex_id); - - canvas_occluder_owner.free(p_rid); - memdelete(co); - - } else if (canvas_light_shadow_owner.owns(p_rid)) { - - CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid); - glDeleteFramebuffers(1, &cls->fbo); - glDeleteRenderbuffers(1, &cls->rbo); - glDeleteTextures(1, &cls->depth); - /* - if (!read_depth_supported) { - glDeleteTextures(1,&cls->rgba); - } - */ - - canvas_light_shadow_owner.free(p_rid); - memdelete(cls); - }; -} - -bool RasterizerGLES2::ShadowBuffer::init(int p_size, bool p_use_depth) { - - size = p_size; - // Create a framebuffer object - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - // Create a render buffer - glGenRenderbuffers(1, &rbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - - // Create a texture for storing the depth - glGenTextures(1, &depth); - glBindTexture(GL_TEXTURE_2D, depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - // Remove artifact on the edges of the shadowmap - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - //print_line("ERROR? "+itos(glGetError())); - if (p_use_depth) { - - // We'll use a depth texture to store the depths in the shadow map - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - -#ifdef GLEW_ENABLED - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#endif - - // Attach the depth texture to FBO depth attachment point - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, depth, 0); - -#ifdef GLEW_ENABLED - glDrawBuffer(GL_NONE); -#endif - } else { - // We'll use a RGBA texture into which we pack the depth info - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - // Attach the RGBA texture to FBO color attachment point - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, depth, 0); - - // Allocate 16-bit depth buffer - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size); - - // Attach the render buffer as depth buffer - will be ignored - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, rbo); - } - -#if 0 - - if (!p_use_depth) { - - - print_line("try no depth!"); - - glGenTextures(1, &rgba); - glBindTexture(GL_TEXTURE_2D, rgba); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rgba, 0); -/* - glGenRenderbuffers(1, &depth); - glBindRenderbuffer(GL_RENDERBUFFER, depth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, p_size, p_size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); -*/ - glGenTextures(1, &depth); - glBindTexture(GL_TEXTURE_2D, depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, size, size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0); - - } else { - - //glGenRenderbuffers(1, &rbo); - //glBindRenderbuffer(GL_RENDERBUFFER, rbo); - - glGenTextures(1, &depth); - glBindTexture(GL_TEXTURE_2D, depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0); - - } - -#endif - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); -//printf("errnum: %x\n",status); -#ifdef GLEW_ENABLED - if (p_use_depth) { - //glDrawBuffer(GL_BACK); - } -#endif - glBindFramebuffer(GL_FRAMEBUFFER, 0); - DEBUG_TEST_ERROR("Shadow Buffer Init"); - ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, false); - -#ifdef GLEW_ENABLED - if (p_use_depth) { - //glDrawBuffer(GL_BACK); - } -#endif - -#if 0 - glGenFramebuffers(1, &fbo_blur); - glBindFramebuffer(GL_FRAMEBUFFER, fbo_blur); - - glGenRenderbuffers(1, &rbo_blur); - glBindRenderbuffer(GL_RENDERBUFFER, rbo_blur); - - glGenTextures(1, &blur); - glBindTexture(GL_TEXTURE_2D, blur); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(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); - - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - //glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, size, size, 0, - //GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, NULL); - - // Attach the RGBA texture to FBO color attachment point - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, blur, 0); - - // Allocate 16-bit depth buffer - /* - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size); - - // Attach the render buffer as depth buffer - will be ignored - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, rbo_blur); - */ - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - OS::get_singleton()->print("Status: %x\n",status); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - DEBUG_TEST_ERROR("Shadow Blur Buffer Init"); - ERR_FAIL_COND_V( status != GL_FRAMEBUFFER_COMPLETE,false ); -#endif - - return true; -} - -void RasterizerGLES2::_update_framebuffer() { - - if (!use_framebuffers) - return; - - int scale = GLOBAL_DEF("rasterizer/framebuffer_shrink", 1); - if (scale < 1) - scale = 1; - - int dwidth = OS::get_singleton()->get_video_mode().width / scale; - int dheight = OS::get_singleton()->get_video_mode().height / scale; - - if (framebuffer.fbo && dwidth == framebuffer.width && dheight == framebuffer.height) - return; - - bool use_fbo = true; - - if (framebuffer.fbo != 0) { - - glDeleteFramebuffers(1, &framebuffer.fbo); -#if 0 - glDeleteTextures(1,&framebuffer.depth); -#else - glDeleteRenderbuffers(1, &framebuffer.depth); - -#endif - glDeleteTextures(1, &framebuffer.color); - - for (int i = 0; i < framebuffer.luminance.size(); i++) { - - glDeleteTextures(1, &framebuffer.luminance[i].color); - glDeleteFramebuffers(1, &framebuffer.luminance[i].fbo); - } - - for (int i = 0; i < 3; i++) { - - glDeleteTextures(1, &framebuffer.blur[i].color); - glDeleteFramebuffers(1, &framebuffer.blur[i].fbo); - } - - glDeleteTextures(1, &framebuffer.sample_color); - glDeleteFramebuffers(1, &framebuffer.sample_fbo); - framebuffer.luminance.clear(); - framebuffer.blur_size = 0; - framebuffer.fbo = 0; - } - -#ifdef TOOLS_ENABLED - framebuffer.active = use_fbo; -#else - framebuffer.active = use_fbo && !low_memory_2d; -#endif - framebuffer.width = dwidth; - framebuffer.height = dheight; - framebuffer.scale = scale; - - if (!framebuffer.active) - return; - - glGenFramebuffers(1, &framebuffer.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); - -//print_line("generating fbo, id: "+itos(framebuffer.fbo)); -//depth - -// Create a render buffer - -#if 0 - glGenTextures(1, &framebuffer.depth); - glBindTexture(GL_TEXTURE_2D, framebuffer.depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, framebuffer.width, framebuffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, framebuffer.depth, 0); - -#else - - glGenRenderbuffers(1, &framebuffer.depth); - glBindRenderbuffer(GL_RENDERBUFFER, framebuffer.depth); - - glRenderbufferStorage(GL_RENDERBUFFER, use_depth24 ? _DEPTH_COMPONENT24_OES : GL_DEPTH_COMPONENT16, framebuffer.width, framebuffer.height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, framebuffer.depth); - -#endif - //color - - //GLuint format_rgba = use_fp16_fb?_GL_RGBA16F_EXT:GL_RGBA; - GLuint format_rgba = GL_RGBA; - GLuint format_type = use_fp16_fb ? _GL_HALF_FLOAT_OES : GL_UNSIGNED_BYTE; - GLuint format_internal = GL_RGBA; - - if (use_16bits_fbo) { - format_type = GL_UNSIGNED_SHORT_5_6_5; - format_rgba = GL_RGB; - format_internal = GL_RGB; - } - /*GLuint format_luminance = use_fp16_fb?GL_RGB16F:GL_RGBA; - GLuint format_luminance_type = use_fp16_fb?(use_fu_GL_HALF_FLOAT_OES):GL_UNSIGNED_BYTE; - GLuint format_luminance_components = use_fp16_fb?GL_RGB:GL_RGBA;*/ - - GLuint format_luminance = use_fp16_fb ? _GL_RG_EXT : GL_RGBA; - GLuint format_luminance_type = use_fp16_fb ? (full_float_fb_supported ? GL_FLOAT : _GL_HALF_FLOAT_OES) : GL_UNSIGNED_BYTE; - GLuint format_luminance_components = use_fp16_fb ? _GL_RG_EXT : GL_RGBA; - - glGenTextures(1, &framebuffer.color); - glBindTexture(GL_TEXTURE_2D, framebuffer.color); - glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, framebuffer.width, framebuffer.height, 0, format_internal, format_type, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer.color, 0); -# - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - - glDeleteFramebuffers(1, &framebuffer.fbo); -#if 0 - glDeleteTextures(1,&framebuffer.depth); -#else - glDeleteRenderbuffers(1, &framebuffer.depth); - -#endif - glDeleteTextures(1, &framebuffer.color); - framebuffer.fbo = 0; - framebuffer.active = false; - //print_line("**************** NO FAMEBUFFEEEERRRR????"); - WARN_PRINT(String("Could not create framebuffer!!, code: " + itos(status)).ascii().get_data()); - } - - //sample - - glGenFramebuffers(1, &framebuffer.sample_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.sample_fbo); - glGenTextures(1, &framebuffer.sample_color); - glBindTexture(GL_TEXTURE_2D, framebuffer.sample_color); - glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, framebuffer.width, framebuffer.height, 0, format_internal, format_type, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer.sample_color, 0); -# - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - - glDeleteFramebuffers(1, &framebuffer.fbo); -#if 0 - glDeleteTextures(1,&framebuffer.depth); -#else - glDeleteRenderbuffers(1, &framebuffer.depth); - -#endif - glDeleteTextures(1, &framebuffer.color); - glDeleteTextures(1, &framebuffer.sample_color); - glDeleteFramebuffers(1, &framebuffer.sample_fbo); - framebuffer.fbo = 0; - framebuffer.active = false; - //print_line("**************** NO FAMEBUFFEEEERRRR????"); - WARN_PRINT("Could not create framebuffer!!"); - } - //blur - - int size = GLOBAL_DEF("rasterizer/blur_buffer_size", 256); - - if (size != framebuffer.blur_size) { - - for (int i = 0; i < 3; i++) { - - if (framebuffer.blur[i].fbo) { - glDeleteFramebuffers(1, &framebuffer.blur[i].fbo); - glDeleteTextures(1, &framebuffer.blur[i].color); - framebuffer.blur[i].fbo = 0; - framebuffer.blur[i].color = 0; - } - } - - framebuffer.blur_size = size; - - for (int i = 0; i < 3; i++) { - - glGenFramebuffers(1, &framebuffer.blur[i].fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.blur[i].fbo); - - glGenTextures(1, &framebuffer.blur[i].color); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[i].color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(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); - glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, size, size, 0, - format_internal, format_type, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, framebuffer.blur[i].color, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - DEBUG_TEST_ERROR("Shadow Buffer Init"); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); - } - } - - // luminance - - int base_size = GLOBAL_DEF("rasterizer/luminance_buffer_size", 81); - - if (framebuffer.luminance.empty() || framebuffer.luminance[0].size != base_size) { - - for (int i = 0; i < framebuffer.luminance.size(); i++) { - - glDeleteFramebuffers(1, &framebuffer.luminance[i].fbo); - glDeleteTextures(1, &framebuffer.luminance[i].color); - } - - framebuffer.luminance.clear(); - - while (base_size > 0) { - - FrameBuffer::Luminance lb; - lb.size = base_size; - - glGenFramebuffers(1, &lb.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, lb.fbo); - - glGenTextures(1, &lb.color); - glBindTexture(GL_TEXTURE_2D, lb.color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); - glTexImage2D(GL_TEXTURE_2D, 0, format_luminance, lb.size, lb.size, 0, - format_luminance_components, format_luminance_type, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, lb.color, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - base_size /= 3; - - DEBUG_TEST_ERROR("Shadow Buffer Init"); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); - - framebuffer.luminance.push_back(lb); - } - } -} - -void RasterizerGLES2::set_base_framebuffer(GLuint p_id, Vector2 p_size) { - - base_framebuffer = p_id; - - if (p_size.x != 0) { - window_size = p_size; - }; -} - -#if 0 -void RasterizerGLES2::_update_blur_buffer() { - - int size = GLOBAL_DEF("rasterizer/blur_buffer_size",256); - if (size!=framebuffer.blur_size) { - - for(int i=0;i<3;i++) { - - if (framebuffer.blur[i].fbo) { - glDeleteFramebuffers(1,&framebuffer.blur[i].fbo); - glDeleteTextures(1,&framebuffer.blur[i].color); - framebuffer.blur[i].fbo=0; - framebuffer.blur[i].color=0; - } - } - - framebuffer.blur_size=size; - - for(int i=0;i<3;i++) { - - glGenFramebuffers(1, &framebuffer.blur[i].fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.blur[i].fbo); - - glGenTextures(1, &framebuffer.blur[i].color); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[i].color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(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); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, framebuffer.blur[i].color, 0); - - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - DEBUG_TEST_ERROR("Shadow Buffer Init"); - ERR_CONTINUE( status != GL_FRAMEBUFFER_COMPLETE ); - - - } - - } - - - - - -} -#endif - -bool RasterizerGLES2::_test_depth_shadow_buffer() { - - int size = 16; - - GLuint fbo; - GLuint rbo; - GLuint depth; - - glActiveTexture(GL_TEXTURE0); - - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - // Create a render buffer - glGenRenderbuffers(1, &rbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - - // Create a texture for storing the depth - glGenTextures(1, &depth); - glBindTexture(GL_TEXTURE_2D, depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Remove artifact on the edges of the shadowmap - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // We'll use a depth texture to store the depths in the shadow map - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - -#ifdef GLEW_ENABLED - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#endif - - // Attach the depth texture to FBO depth attachment point - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, depth, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - glDeleteFramebuffers(1, &fbo); - glDeleteRenderbuffers(1, &rbo); - glDeleteTextures(1, &depth); - - return status == GL_FRAMEBUFFER_COMPLETE; -} - -void RasterizerGLES2::init() { - - if (OS::get_singleton()->is_stdout_verbose()) { - print_line("Using GLES2 video driver"); - } - -#ifdef GLEW_ENABLED - GLuint res = glewInit(); - ERR_FAIL_COND(res != GLEW_OK); - if (OS::get_singleton()->is_stdout_verbose()) { - print_line(String("GLES2: Using GLEW ") + (const char *)glewGetString(GLEW_VERSION)); - } - - // Godot makes use of functions from ARB_framebuffer_object extension which is not implemented by all drivers. - // On the other hand, these drivers might implement the older EXT_framebuffer_object extension - // with which current source code is backward compatible. - - bool framebuffer_object_is_supported = glewIsSupported("GL_ARB_framebuffer_object"); - - if (!framebuffer_object_is_supported) { - WARN_PRINT("GL_ARB_framebuffer_object not supported by your graphics card."); - - if (glewIsSupported("GL_EXT_framebuffer_object")) { - // falling-back to the older EXT function if present - WARN_PRINT("Falling-back to GL_EXT_framebuffer_object."); - - glIsRenderbuffer = glIsRenderbufferEXT; - glBindRenderbuffer = glBindRenderbufferEXT; - glDeleteRenderbuffers = glDeleteRenderbuffersEXT; - glGenRenderbuffers = glGenRenderbuffersEXT; - glRenderbufferStorage = glRenderbufferStorageEXT; - glGetRenderbufferParameteriv = glGetRenderbufferParameterivEXT; - glIsFramebuffer = glIsFramebufferEXT; - glBindFramebuffer = glBindFramebufferEXT; - glDeleteFramebuffers = glDeleteFramebuffersEXT; - glGenFramebuffers = glGenFramebuffersEXT; - glCheckFramebufferStatus = glCheckFramebufferStatusEXT; - glFramebufferTexture1D = glFramebufferTexture1DEXT; - glFramebufferTexture2D = glFramebufferTexture2DEXT; - glFramebufferTexture3D = glFramebufferTexture3DEXT; - glFramebufferRenderbuffer = glFramebufferRenderbufferEXT; - glGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameterivEXT; - glGenerateMipmap = glGenerateMipmapEXT; - - framebuffer_object_is_supported = true; - } else { - ERR_PRINT("Framebuffer Object is not supported by your graphics card."); - } - } - - // Check for GL 2.1 compatibility, if not bail out - if (!(glewIsSupported("GL_VERSION_2_1") && framebuffer_object_is_supported)) { - ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n" - "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot is now going to terminate."); - OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n" - "Godot Engine will self-destruct as soon as you acknowledge this error message.", - "Fatal error: Insufficient OpenGL / GLES drivers"); - exit(1); - } -#endif - - scene_pass = 1; - - if (extensions.size() == 0) { - - set_extensions((const char *)glGetString(GL_EXTENSIONS)); - } - - GLint tmp = 0; - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &tmp); - //print_line("GL_MAX_VERTEX_ATTRIBS "+itos(tmp)); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glFrontFace(GL_CW); - //glEnable(GL_TEXTURE_2D); - - default_material = create_default_material(); - - material_shader.init(); - canvas_shader.init(); - copy_shader.init(); - canvas_shadow_shader.init(); - -#ifdef GLEW_ENABLED - material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL, true); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_GLES_OVER_GL, true); - canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_GLES_OVER_GL, true); - copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL, true); -#endif - -#ifdef ANGLE_ENABLED - // Fix for ANGLE - material_shader.set_conditional(MaterialShaderGLES2::DISABLE_FRONT_FACING, true); -#endif - - shadow = NULL; - shadow_pass = 0; - - framebuffer.fbo = 0; - framebuffer.width = 0; - framebuffer.height = 0; - //framebuffer.buff16=false; - //framebuffer.blur[0].fbo=false; - //framebuffer.blur[1].fbo=false; - framebuffer.active = false; - - //do a single initial clear - glClearColor(0, 0, 0, 1); - //glClearDepth(1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glGenTextures(1, &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, 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); - -#ifdef GLEW_ENABLED - - pvr_supported = false; - etc_supported = false; - use_depth24 = true; - s3tc_supported = true; - atitc_supported = false; - //use_texture_instancing=false; - //use_attribute_instancing=true; - use_texture_instancing = false; - use_attribute_instancing = true; - full_float_fb_supported = true; - srgb_supported = true; - latc_supported = true; - s3tc_srgb_supported = true; - use_anisotropic_filter = true; - float_linear_supported = true; - - GLint vtf; - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vtf); - float_supported = extensions.has("GL_OES_texture_float") || extensions.has("GL_ARB_texture_float"); - use_hw_skeleton_xform = vtf > 0 && float_supported; - - read_depth_supported = _test_depth_shadow_buffer(); - use_rgba_shadowmaps = !read_depth_supported; - //print_line("read depth support? "+itos(read_depth_supported)); - - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic_level); - anisotropic_level = MIN(anisotropic_level, float(GLOBAL_DEF("rasterizer/anisotropic_filter_level", 4.0))); -#ifdef OSX_ENABLED - use_rgba_shadowmaps = true; - use_fp16_fb = false; -#else - -#endif - use_half_float = true; - -#else - - for (Set<String>::Element *E = extensions.front(); E; E = E->next()) { - print_line(E->get()); - } - read_depth_supported = extensions.has("GL_OES_depth_texture"); - use_rgba_shadowmaps = !read_depth_supported; - if (shadow_filter >= SHADOW_FILTER_ESM && !extensions.has("GL_EXT_frag_depth")) { - use_rgba_shadowmaps = true; //no other way, go back to rgba - } - pvr_supported = extensions.has("GL_IMG_texture_compression_pvrtc"); - pvr_srgb_supported = extensions.has("GL_EXT_pvrtc_sRGB"); - etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); - use_depth24 = extensions.has("GL_OES_depth24"); - s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); - use_half_float = extensions.has("GL_OES_vertex_half_float"); - atitc_supported = extensions.has("GL_AMD_compressed_ATC_texture"); - - srgb_supported = extensions.has("GL_EXT_sRGB"); -#ifndef ANGLE_ENABLED - s3tc_srgb_supported = s3tc_supported && extensions.has("GL_EXT_texture_compression_s3tc"); -#else - s3tc_srgb_supported = s3tc_supported; -#endif - latc_supported = extensions.has("GL_EXT_texture_compression_latc"); - anisotropic_level = 1.0; - use_anisotropic_filter = extensions.has("GL_EXT_texture_filter_anisotropic"); - if (use_anisotropic_filter) { - glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic_level); - anisotropic_level = MIN(anisotropic_level, float(GLOBAL_DEF("rasterizer/anisotropic_filter_level", 4.0))); - } - - print_line("S3TC: " + itos(s3tc_supported) + " ATITC: " + itos(atitc_supported)); - - GLint vtf; - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vtf); - float_supported = extensions.has("GL_OES_texture_float") || extensions.has("GL_ARB_texture_float"); - use_hw_skeleton_xform = vtf > 0 && float_supported; - float_linear_supported = extensions.has("GL_OES_texture_float_linear"); - - /* - if (extensions.has("GL_QCOM_tiled_rendering")) - use_hw_skeleton_xform=false; - */ - GLint mva; - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mva); - if (vtf == 0 && mva > 8) { - //tegra 3, mali 400 - use_attribute_instancing = true; - use_texture_instancing = false; - } else if (vtf > 0 && extensions.has("GL_OES_texture_float")) { - //use_texture_instancing=true; - use_texture_instancing = false; // i don't get it, uniforms are faster. - use_attribute_instancing = false; - - } else { - - use_texture_instancing = false; - use_attribute_instancing = false; - } - - if (use_fp16_fb) { - use_fp16_fb = extensions.has("GL_OES_texture_half_float") && extensions.has("GL_EXT_color_buffer_half_float") && extensions.has("GL_EXT_texture_rg"); - } - - full_float_fb_supported = extensions.has("GL_EXT_color_buffer_float"); - -//etc_supported=false; - -#endif - - //use_rgba_shadowmaps=true; - - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); - //read_depth_supported=false; - - canvas_shadow_blur = canvas_light_shadow_buffer_create(max_texture_size); - - { - //shadowmaps - - //don't use a shadowbuffer too big in GLES, this should be the maximum - int max_shadow_size = GLOBAL_DEF("rasterizer/max_shadow_buffer_size", 1024); - int smsize = max_shadow_size; - while (smsize >= 16) { - - ShadowBuffer sb; - bool s = sb.init(smsize, !use_rgba_shadowmaps); - if (s) - near_shadow_buffers.push_back(sb); - smsize /= 2; - } - - blur_shadow_buffer.init(max_shadow_size, !use_rgba_shadowmaps); - - //material_shader - material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS, !use_rgba_shadowmaps); - canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_DEPTH_SHADOWS, !use_rgba_shadowmaps); - } - - shadow_material = material_create(); //empty with nothing - shadow_mat_ptr = material_owner.get(shadow_material); - - // Now create a second shadow material for double-sided shadow instances - shadow_material_double_sided = material_create(); - shadow_mat_double_sided_ptr = material_owner.get(shadow_material_double_sided); - shadow_mat_double_sided_ptr->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED] = true; - - overdraw_material = create_overdraw_debug_material(); - copy_shader.set_conditional(CopyShaderGLES2::USE_8BIT_HDR, !use_fp16_fb); - canvas_shader.set_conditional(CanvasShaderGLES2::USE_DEPTH_SHADOWS, read_depth_supported); - - canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/use_2d_pixel_snap", false)); - - npo2_textures_available = true; - //fragment_lighting=false; - _rinfo.texture_mem = 0; - current_env = NULL; - current_rt = NULL; - current_vd = NULL; - current_debug = VS::SCENARIO_DEBUG_DISABLED; - camera_ortho = false; - - glGenBuffers(1, &gui_quad_buffer); - glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer); -#ifdef GLES_NO_CLIENT_ARRAYS //WebGL specific implementation. - glBufferData(GL_ARRAY_BUFFER, 8 * MAX_POLYGON_VERTICES, NULL, GL_DYNAMIC_DRAW); -#else - glBufferData(GL_ARRAY_BUFFER, 128, NULL, GL_DYNAMIC_DRAW); -#endif - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - -#ifdef GLES_NO_CLIENT_ARRAYS //webgl indices buffer - glGenBuffers(1, &indices_buffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 16 * 1024, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // unbind -#endif - - shader_time_rollback = GLOBAL_DEF("rasterizer/shader_time_rollback", 300); - - using_canvas_bg = false; - _update_framebuffer(); - DEBUG_TEST_ERROR("Initializing"); -} - -void RasterizerGLES2::finish() { - - free(default_material); - free(shadow_material); - free(shadow_material_double_sided); - free(canvas_shadow_blur); - free(overdraw_material); -} - -int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) { - - switch (p_info) { - - case VS::INFO_OBJECTS_IN_FRAME: { - - return _rinfo.object_count; - } break; - case VS::INFO_VERTICES_IN_FRAME: { - - return _rinfo.vertex_count; - } break; - case VS::INFO_MATERIAL_CHANGES_IN_FRAME: { - - return _rinfo.mat_change_count; - } break; - case VS::INFO_SHADER_CHANGES_IN_FRAME: { - - return _rinfo.shader_change_count; - } break; - case VS::INFO_DRAW_CALLS_IN_FRAME: { - - return _rinfo.draw_calls; - } break; - case VS::INFO_SURFACE_CHANGES_IN_FRAME: { - - return _rinfo.surface_count; - } break; - case VS::INFO_USAGE_VIDEO_MEM_TOTAL: { - - return 0; - } break; - case VS::INFO_VIDEO_MEM_USED: { - - return get_render_info(VS::INFO_TEXTURE_MEM_USED) + get_render_info(VS::INFO_VERTEX_MEM_USED); - } break; - case VS::INFO_TEXTURE_MEM_USED: { - - return _rinfo.texture_mem; - } break; - case VS::INFO_VERTEX_MEM_USED: { - - return 0; - } break; - } - - return 0; -} - -void RasterizerGLES2::set_extensions(const char *p_strings) { - - Vector<String> strings = String(p_strings).split(" ", false); - for (int i = 0; i < strings.size(); i++) { - - extensions.insert(strings[i]); - //print_line(strings[i]); - } -} - -bool RasterizerGLES2::needs_to_draw_next_frame() const { - - return draw_next_frame; -} - -bool RasterizerGLES2::has_feature(VS::Features p_feature) const { - - switch (p_feature) { - case VS::FEATURE_SHADERS: return true; - case VS::FEATURE_NEEDS_RELOAD_HOOK: return use_reload_hooks; - default: return false; - } -} - -void RasterizerGLES2::reload_vram() { - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glFrontFace(GL_CW); - - //do a single initial clear - glClearColor(0, 0, 0, 1); - //glClearDepth(1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glGenTextures(1, &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, 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); - - List<RID> textures; - texture_owner.get_owned_list(&textures); - keep_copies = false; - for (List<RID>::Element *E = textures.front(); E; E = E->next()) { - - RID tid = E->get(); - Texture *t = texture_owner.get(tid); - ERR_CONTINUE(!t); - t->tex_id = 0; - t->data_size = 0; - glGenTextures(1, &t->tex_id); - t->active = false; - if (t->render_target) - continue; - texture_allocate(tid, t->width, t->height, t->format, t->flags); - bool had_image = false; - for (int i = 0; i < 6; i++) { - if (!t->image[i].empty()) { - texture_set_data(tid, t->image[i], VS::CubeMapSide(i)); - had_image = true; - } - } - - if (!had_image && t->reloader) { - Object *rl = ObjectDB::get_instance(t->reloader); - if (rl) - rl->call(t->reloader_func, tid); - } - } - keep_copies = true; - - List<RID> render_targets; - render_target_owner.get_owned_list(&render_targets); - for (List<RID>::Element *E = render_targets.front(); E; E = E->next()) { - RenderTarget *rt = render_target_owner.get(E->get()); - - int w = rt->width; - int h = rt->height; - rt->width = 0; - rt->height = 0; - render_target_set_size(E->get(), w, h); - } - - List<RID> meshes; - mesh_owner.get_owned_list(&meshes); - for (List<RID>::Element *E = meshes.front(); E; E = E->next()) { - - Mesh *mesh = mesh_owner.get(E->get()); - Vector<Surface *> surfaces = mesh->surfaces; - mesh->surfaces.clear(); - for (int i = 0; i < surfaces.size(); i++) { - mesh_add_surface(E->get(), surfaces[i]->primitive, surfaces[i]->data, surfaces[i]->morph_data, surfaces[i]->alpha_sort); - mesh_surface_set_material(E->get(), i, surfaces[i]->material); - - if (surfaces[i]->array_local != 0) { - memfree(surfaces[i]->array_local); - }; - if (surfaces[i]->index_array_local != 0) { - memfree(surfaces[i]->index_array_local); - }; - - memdelete(surfaces[i]); - } - } - - List<RID> skeletons; - skeleton_owner.get_owned_list(&skeletons); - for (List<RID>::Element *E = skeletons.front(); E; E = E->next()) { - - Skeleton *sk = skeleton_owner.get(E->get()); - if (!sk->tex_id) - continue; //does not use hw transform, leave alone - - Vector<Skeleton::Bone> bones = sk->bones; - sk->bones.clear(); - sk->tex_id = 0; - sk->pixel_size = 1.0; - skeleton_resize(E->get(), bones.size()); - sk->bones = bones; - } - - List<RID> multimeshes; - multimesh_owner.get_owned_list(&multimeshes); - for (List<RID>::Element *E = multimeshes.front(); E; E = E->next()) { - - MultiMesh *mm = multimesh_owner.get(E->get()); - if (!mm->tex_id) - continue; //does not use hw transform, leave alone - - Vector<MultiMesh::Element> elements = mm->elements; - mm->elements.clear(); - - mm->tw = 1; - mm->th = 1; - mm->tex_id = 0; - mm->last_pass = 0; - mm->visible = -1; - - multimesh_set_instance_count(E->get(), elements.size()); - mm->elements = elements; - } - - if (framebuffer.fbo != 0) { - - framebuffer.fbo = 0; - framebuffer.depth = 0; - framebuffer.color = 0; - - for (int i = 0; i < 3; i++) { - framebuffer.blur[i].fbo = 0; - framebuffer.blur[i].color = 0; - } - - framebuffer.luminance.clear(); - } - - for (int i = 0; i < near_shadow_buffers.size(); i++) { - near_shadow_buffers[i].init(near_shadow_buffers[i].size, !use_rgba_shadowmaps); - } - - blur_shadow_buffer.init(near_shadow_buffers[0].size, !use_rgba_shadowmaps); - - canvas_shader.clear_caches(); - material_shader.clear_caches(); - blur_shader.clear_caches(); - copy_shader.clear_caches(); - - List<RID> shaders; - shader_owner.get_owned_list(&shaders); - for (List<RID>::Element *E = shaders.front(); E; E = E->next()) { - - Shader *s = shader_owner.get(E->get()); - s->custom_code_id = 0; - s->version = 1; - s->valid = false; - shader_set_mode(E->get(), s->mode); - } - - List<RID> materials; - material_owner.get_owned_list(&materials); - for (List<RID>::Element *E = materials.front(); E; E = E->next()) { - - Material *m = material_owner.get(E->get()); - RID shader = m->shader; - m->shader_version = 0; - material_set_shader(E->get(), shader); - } -} - -void RasterizerGLES2::set_use_framebuffers(bool p_use) { - - use_framebuffers = p_use; -} - -RasterizerGLES2 *RasterizerGLES2::get_singleton() { - - return _singleton; -}; - -int RasterizerGLES2::RenderList::max_elements = RenderList::DEFAULT_MAX_ELEMENTS; - -void RasterizerGLES2::set_force_16_bits_fbo(bool p_force) { - - use_16bits_fbo = p_force; -} - -RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays, bool p_keep_ram_copy, bool p_default_fragment_lighting, bool p_use_reload_hooks) { - - _singleton = this; - shrink_textures_x2 = false; - RenderList::max_elements = GLOBAL_DEF("rasterizer/max_render_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS); - if (RenderList::max_elements > 64000) - RenderList::max_elements = 64000; - if (RenderList::max_elements < 1024) - RenderList::max_elements = 1024; - - opaque_render_list.init(); - alpha_render_list.init(); - - skinned_buffer_size = GLOBAL_DEF("rasterizer/skeleton_buffer_size_kb", DEFAULT_SKINNED_BUFFER_SIZE); - if (skinned_buffer_size < 256) - skinned_buffer_size = 256; - if (skinned_buffer_size > 16384) - skinned_buffer_size = 16384; - skinned_buffer_size *= 1024; - skinned_buffer = memnew_arr(uint8_t, skinned_buffer_size); - - keep_copies = p_keep_ram_copy; - use_reload_hooks = p_use_reload_hooks; - pack_arrays = p_compress_arrays; - p_default_fragment_lighting = false; - fragment_lighting = GLOBAL_DEF("rasterizer/use_fragment_lighting", true); - read_depth_supported = true; //todo check for extension - shadow_filter = ShadowFilterTechnique((int)(GLOBAL_DEF("rasterizer/shadow_filter", SHADOW_FILTER_PCF5))); - ProjectSettings::get_singleton()->set_custom_property_info("rasterizer/shadow_filter", PropertyInfo(Variant::INT, "rasterizer/shadow_filter", PROPERTY_HINT_ENUM, "None,PCF5,PCF13,ESM")); - use_fp16_fb = bool(GLOBAL_DEF("rasterizer/fp16_framebuffer", true)); - use_shadow_mapping = true; - use_fast_texture_filter = !bool(GLOBAL_DEF("rasterizer/trilinear_mipmap_filter", true)); - low_memory_2d = bool(GLOBAL_DEF("rasterizer/low_memory_2d_mode", false)); - skel_default.resize(1024 * 4); - for (int i = 0; i < 1024 / 3; i++) { - - float *ptr = skel_default.ptr(); - ptr += i * 4 * 4; - ptr[0] = 1.0; - ptr[1] = 0.0; - ptr[2] = 0.0; - ptr[3] = 0.0; - - ptr[4] = 0.0; - ptr[5] = 1.0; - ptr[6] = 0.0; - ptr[7] = 0.0; - - ptr[8] = 0.0; - ptr[9] = 0.0; - ptr[10] = 1.0; - ptr[12] = 0.0; - } - - base_framebuffer = 0; - frame = 0; - draw_next_frame = false; - use_framebuffers = true; - framebuffer.active = false; - tc0_id_cache = 0; - tc0_idx = 0; - use_16bits_fbo = false; -}; - -void RasterizerGLES2::restore_framebuffer() { - - glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); -} - -RasterizerGLES2::~RasterizerGLES2() { - - memdelete_arr(skinned_buffer); -}; - -#endif diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h deleted file mode 100644 index e86d3ba298..0000000000 --- a/drivers/gles2/rasterizer_gles2.h +++ /dev/null @@ -1,1686 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 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 RASTERIZER_GLES2_H -#define RASTERIZER_GLES2_H - -#include "servers/visual/rasterizer.h" - -#define MAX_POLYGON_VERTICES 4096 //used for WebGL canvas_draw_polygon call. - -#ifdef GLES2_ENABLED - -#include "camera_matrix.h" -#include "image.h" -#include "list.h" -#include "map.h" -#include "rid.h" -#include "self_list.h" -#include "servers/visual_server.h" -#include "sort.h" - -#include "platform_config.h" -#ifndef GLES2_INCLUDE_H -#include <GLES2/gl2.h> -#else -#include GLES2_INCLUDE_H -#endif - -#include "drivers/gles2/shader_compiler_gles2.h" -#include "drivers/gles2/shaders/blur.glsl.h" -#include "drivers/gles2/shaders/canvas.glsl.h" -#include "drivers/gles2/shaders/canvas_shadow.glsl.h" -#include "drivers/gles2/shaders/copy.glsl.h" -#include "drivers/gles2/shaders/material.glsl.h" -#include "servers/visual/particle_system_sw.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class RasterizerGLES2 : public Rasterizer { - - enum { - - MAX_SCENE_LIGHTS = 2048, - LIGHT_SPOT_BIT = 0x80, - DEFAULT_SKINNED_BUFFER_SIZE = 2048, // 10k vertices - MAX_HW_LIGHTS = 1, - }; - - uint8_t *skinned_buffer; - int skinned_buffer_size; - bool pvr_supported; - bool pvr_srgb_supported; - bool s3tc_supported; - bool s3tc_srgb_supported; - bool latc_supported; - bool etc_supported; - bool atitc_supported; - bool npo2_textures_available; - bool read_depth_supported; - bool use_framebuffers; - bool full_float_fb_supported; - bool use_shadow_mapping; - bool use_fp16_fb; - bool srgb_supported; - bool float_supported; - bool float_linear_supported; - bool use_16bits_fbo; - - ShadowFilterTechnique shadow_filter; - - bool use_shadow_esm; - bool use_shadow_pcf; - bool use_hw_skeleton_xform; - bool use_depth24; - bool use_texture_instancing; - bool use_attribute_instancing; - bool use_rgba_shadowmaps; - bool use_anisotropic_filter; - float anisotropic_level; - - bool use_half_float; - bool low_memory_2d; - - bool shrink_textures_x2; - - Vector<float> skel_default; - - Image _get_gl_image_and_format(const Image &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, int &r_gl_components, bool &r_has_alpha_cache, bool &r_compressed); - - struct RenderTarget; - - struct Texture { - - String path; - uint32_t flags; - int width, height; - int alloc_width, alloc_height; - Image::Format format; - - GLenum target; - GLenum gl_format_cache; - GLenum gl_internal_format_cache; - int gl_components_cache; - int data_size; //original data size, useful for retrieving back - bool has_alpha; - bool format_has_alpha; - bool compressed; - bool disallow_mipmaps; - int total_data_size; - bool ignore_mipmaps; - - ObjectID reloader; - StringName reloader_func; - Image image[6]; - - int mipmaps; - - bool active; - GLuint tex_id; - - RenderTarget *render_target; - - Texture() { - - ignore_mipmaps = false; - render_target = NULL; - flags = width = height = 0; - tex_id = 0; - data_size = 0; - format = Image::FORMAT_L8; - gl_components_cache = 0; - format_has_alpha = false; - has_alpha = false; - active = false; - disallow_mipmaps = false; - compressed = false; - total_data_size = 0; - target = GL_TEXTURE_2D; - mipmaps = 0; - - reloader = 0; - } - - ~Texture() { - - if (tex_id != 0) { - - glDeleteTextures(1, &tex_id); - } - } - }; - - mutable RID_Owner<Texture> texture_owner; - - struct Shader { - - String vertex_code; - String fragment_code; - String light_code; - int vertex_line; - int fragment_line; - int light_line; - VS::ShaderMode mode; - - uint32_t custom_code_id; - uint32_t version; - - bool valid; - bool has_alpha; - bool can_zpass; - bool has_texscreen; - bool has_screen_uv; - bool writes_vertex; - bool uses_discard; - bool uses_time; - bool uses_normal; - bool uses_texpixel_size; - - Map<StringName, ShaderLanguage::Uniform> uniforms; - StringName first_texture; - - Map<StringName, RID> default_textures; - - SelfList<Shader> dirty_list; - - Shader() - : dirty_list(this) { - - valid = false; - custom_code_id = 0; - has_alpha = false; - version = 1; - vertex_line = 0; - fragment_line = 0; - light_line = 0; - can_zpass = true; - has_texscreen = false; - has_screen_uv = false; - writes_vertex = false; - uses_discard = false; - uses_time = false; - uses_normal = false; - } - }; - - mutable RID_Owner<Shader> shader_owner; - mutable SelfList<Shader>::List _shader_dirty_list; - _FORCE_INLINE_ void _shader_make_dirty(Shader *p_shader); - void _update_shader(Shader *p_shader) const; - - struct Material { - - bool flags[VS::MATERIAL_FLAG_MAX]; - - VS::MaterialBlendMode blend_mode; - VS::MaterialDepthDrawMode depth_draw_mode; - - float line_width; - bool has_alpha; - - mutable uint32_t shader_version; - - RID shader; // shader material - Shader *shader_cache; - - struct UniformData { - - bool inuse; - bool istexture; - Variant value; - int index; - }; - - mutable Map<StringName, UniformData> shader_params; - - uint64_t last_pass; - - Material() { - - for (int i = 0; i < VS::MATERIAL_FLAG_MAX; i++) - flags[i] = false; - flags[VS::MATERIAL_FLAG_VISIBLE] = true; - - line_width = 1; - has_alpha = false; - depth_draw_mode = VS::MATERIAL_DEPTH_DRAW_OPAQUE_ONLY; - blend_mode = VS::MATERIAL_BLEND_MODE_MIX; - last_pass = 0; - shader_version = 0; - shader_cache = NULL; - } - }; - - _FORCE_INLINE_ void _update_material_shader_params(Material *p_material) const; - mutable RID_Owner<Material> material_owner; - - struct Geometry { - - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_IMMEDIATE, - GEOMETRY_PARTICLES, - GEOMETRY_MULTISURFACE, - }; - - Type type; - RID material; - bool has_alpha; - bool material_owned; - - Geometry() { - has_alpha = false; - material_owned = false; - } - virtual ~Geometry(){}; - }; - - struct GeometryOwner { - - virtual ~GeometryOwner() {} - }; - - struct Mesh; - - struct Surface : public Geometry { - - struct ArrayData { - - uint32_t ofs, size, datatype, count; - bool normalize; - bool bind; - - ArrayData() { - ofs = 0; - size = 0; - count = 0; - datatype = 0; - normalize = 0; - bind = false; - } - }; - - Mesh *mesh; - - Array data; - Array morph_data; - ArrayData array[VS::ARRAY_MAX]; - // support for vertex array objects - GLuint array_object_id; - // support for vertex buffer object - GLuint vertex_id; // 0 means, unconfigured - GLuint index_id; // 0 means, unconfigured - // no support for the above, array in localmem. - uint8_t *array_local; - uint8_t *index_array_local; - Vector<AABB> skeleton_bone_aabb; - Vector<bool> skeleton_bone_used; - - //bool packed; - - struct MorphTarget { - uint32_t configured_format; - uint8_t *array; - }; - - MorphTarget *morph_targets_local; - int morph_target_count; - AABB aabb; - - int array_len; - int index_array_len; - int max_bone; - - float vertex_scale; - float uv_scale; - float uv2_scale; - - bool alpha_sort; - - VS::PrimitiveType primitive; - - uint32_t format; - uint32_t configured_format; - - int stride; - int local_stride; - uint32_t morph_format; - - bool active; - - Point2 uv_min; - Point2 uv_max; - - Surface() { - - array_len = 0; - local_stride = 0; - morph_format = 0; - type = GEOMETRY_SURFACE; - primitive = VS::PRIMITIVE_POINTS; - index_array_len = 0; - vertex_scale = 1.0; - uv_scale = 1.0; - uv2_scale = 1.0; - - alpha_sort = false; - - format = 0; - stride = 0; - morph_targets_local = 0; - morph_target_count = 0; - - array_local = index_array_local = 0; - vertex_id = index_id = 0; - - active = false; - //packed=false; - } - - ~Surface() { - } - }; - - struct Mesh { - - bool active; - Vector<Surface *> surfaces; - int morph_target_count; - VS::MorphTargetMode morph_target_mode; - AABB custom_aabb; - - mutable uint64_t last_pass; - Mesh() { - morph_target_mode = VS::MORPH_MODE_NORMALIZED; - morph_target_count = 0; - last_pass = 0; - active = false; - } - }; - mutable RID_Owner<Mesh> mesh_owner; - - Error _surface_set_arrays(Surface *p_surface, uint8_t *p_mem, uint8_t *p_index_mem, const Array &p_arrays, bool p_main); - - struct MultiMesh; - - struct MultiMeshSurface : public Geometry { - - Surface *surface; - MultiMeshSurface() { type = GEOMETRY_MULTISURFACE; } - }; - - struct MultiMesh : public GeometryOwner { - - struct Element { - - float matrix[16]; - uint8_t color[4]; - Element() { - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - }; - }; - - AABB aabb; - RID mesh; - int visible; - - //IDirect3DVertexBuffer9* instance_buffer; - Vector<Element> elements; - Vector<MultiMeshSurface> cache_surfaces; - mutable uint64_t last_pass; - GLuint tex_id; - int tw; - int th; - - SelfList<MultiMesh> dirty_list; - - MultiMesh() - : dirty_list(this) { - - tw = 1; - th = 1; - tex_id = 0; - last_pass = 0; - visible = -1; - } - }; - - mutable RID_Owner<MultiMesh> multimesh_owner; - mutable SelfList<MultiMesh>::List _multimesh_dirty_list; - - struct Immediate : public Geometry { - - struct Chunk { - - RID texture; - VS::PrimitiveType primitive; - Vector<Vector3> vertices; - Vector<Vector3> normals; - Vector<Plane> tangents; - Vector<Color> colors; - Vector<Vector2> uvs; - Vector<Vector2> uvs2; - }; - - List<Chunk> chunks; - bool building; - int mask; - AABB aabb; - - Immediate() { - type = GEOMETRY_IMMEDIATE; - building = false; - } - }; - - mutable RID_Owner<Immediate> immediate_owner; - - struct Particles : public Geometry { - - ParticleSystemSW data; // software particle system - - Particles() { - type = GEOMETRY_PARTICLES; - } - }; - - mutable RID_Owner<Particles> particles_owner; - - struct ParticlesInstance : public GeometryOwner { - - RID particles; - - ParticleSystemProcessSW particles_process; - Transform transform; - - ParticlesInstance() {} - }; - - mutable RID_Owner<ParticlesInstance> particles_instance_owner; - ParticleSystemDrawInfoSW particle_draw_info; - - struct Skeleton { - - struct Bone { - - float mtx[4][4]; //used - - Bone() { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - - mtx[i][j] = (i == j) ? 1 : 0; - } - } - } - - _ALWAYS_INLINE_ void transform_add_mul3(const float *p_src, float *r_dst, float p_weight) const { - - r_dst[0] += ((mtx[0][0] * p_src[0]) + (mtx[1][0] * p_src[1]) + (mtx[2][0] * p_src[2]) + mtx[3][0]) * p_weight; - r_dst[1] += ((mtx[0][1] * p_src[0]) + (mtx[1][1] * p_src[1]) + (mtx[2][1] * p_src[2]) + mtx[3][1]) * p_weight; - r_dst[2] += ((mtx[0][2] * p_src[0]) + (mtx[1][2] * p_src[1]) + (mtx[2][2] * p_src[2]) + mtx[3][2]) * p_weight; - } - _ALWAYS_INLINE_ void transform3_add_mul3(const float *p_src, float *r_dst, float p_weight) const { - - r_dst[0] += ((mtx[0][0] * p_src[0]) + (mtx[1][0] * p_src[1]) + (mtx[2][0] * p_src[2])) * p_weight; - r_dst[1] += ((mtx[0][1] * p_src[0]) + (mtx[1][1] * p_src[1]) + (mtx[2][1] * p_src[2])) * p_weight; - r_dst[2] += ((mtx[0][2] * p_src[0]) + (mtx[1][2] * p_src[1]) + (mtx[2][2] * p_src[2])) * p_weight; - } - - _ALWAYS_INLINE_ AABB transform_aabb(const AABB &p_aabb) const { - - float vertices[8][3] = { - { p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z + p_aabb.size.z }, - { p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z }, - { p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z + p_aabb.size.z }, - { p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z }, - { p_aabb.pos.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z + p_aabb.size.z }, - { p_aabb.pos.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z }, - { p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z + p_aabb.size.z }, - { p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z } - }; - - AABB ret; - - for (int i = 0; i < 8; i++) { - - Vector3 xv( - - ((mtx[0][0] * vertices[i][0]) + (mtx[1][0] * vertices[i][1]) + (mtx[2][0] * vertices[i][2]) + mtx[3][0]), - ((mtx[0][1] * vertices[i][0]) + (mtx[1][1] * vertices[i][1]) + (mtx[2][1] * vertices[i][2]) + mtx[3][1]), - ((mtx[0][2] * vertices[i][0]) + (mtx[1][2] * vertices[i][1]) + (mtx[2][2] * vertices[i][2]) + mtx[3][2])); - - if (i == 0) - ret.pos = xv; - else - ret.expand_to(xv); - } - - return ret; - } - }; - - GLuint tex_id; - float pixel_size; //for texture - Vector<Bone> bones; - - SelfList<Skeleton> dirty_list; - - Skeleton() - : dirty_list(this) { - tex_id = 0; - pixel_size = 1.0; - } - }; - - mutable RID_Owner<Skeleton> skeleton_owner; - mutable SelfList<Skeleton>::List _skeleton_dirty_list; - - template <bool USE_NORMAL, bool USE_TANGENT, bool INPLACE> - void _skeleton_xform(const uint8_t *p_src_array, int p_src_stride, uint8_t *p_dst_array, int p_dst_stride, int p_elements, const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms); - - struct Light { - - VS::LightType type; - float vars[VS::LIGHT_PARAM_MAX]; - Color colors[3]; - bool shadow_enabled; - RID projector; - bool volumetric_enabled; - Color volumetric_color; - VS::LightOmniShadowMode omni_shadow_mode; - VS::LightDirectionalShadowMode directional_shadow_mode; - float directional_shadow_param[3]; - - Light() { - - vars[VS::LIGHT_PARAM_SPOT_ATTENUATION] = 1; - vars[VS::LIGHT_PARAM_SPOT_ANGLE] = 45; - vars[VS::LIGHT_PARAM_ATTENUATION] = 1.0; - vars[VS::LIGHT_PARAM_ENERGY] = 1.0; - vars[VS::LIGHT_PARAM_RADIUS] = 1.0; - vars[VS::LIGHT_PARAM_SHADOW_DARKENING] = 0.0; - vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET] = 0.2; - vars[VS::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE] = 1.4; - vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER] = 60.0; - vars[VS::LIGHT_PARAM_SHADOW_BLUR_PASSES] = 1; - colors[VS::LIGHT_COLOR_DIFFUSE] = Color(1, 1, 1); - colors[VS::LIGHT_COLOR_SPECULAR] = Color(1, 1, 1); - shadow_enabled = false; - volumetric_enabled = false; - - directional_shadow_param[VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_SPLIT_WEIGHT] = 0.5; - directional_shadow_param[VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE] = 0; - directional_shadow_param[VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_ZOFFSET_SCALE] = 2.0; - omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DEFAULT; - directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; - } - }; - - struct Environment { - - VS::EnvironmentBG bg_mode; - Variant bg_param[VS::ENV_BG_PARAM_MAX]; - bool fx_enabled[VS::ENV_FX_MAX]; - Variant fx_param[VS::ENV_FX_PARAM_MAX]; - - Environment() { - - bg_mode = VS::ENV_BG_DEFAULT_COLOR; - bg_param[VS::ENV_BG_PARAM_COLOR] = Color(0, 0, 0); - bg_param[VS::ENV_BG_PARAM_TEXTURE] = RID(); - bg_param[VS::ENV_BG_PARAM_CUBEMAP] = RID(); - bg_param[VS::ENV_BG_PARAM_ENERGY] = 1.0; - bg_param[VS::ENV_BG_PARAM_SCALE] = 1.0; - bg_param[VS::ENV_BG_PARAM_GLOW] = 0.0; - bg_param[VS::ENV_BG_PARAM_CANVAS_MAX_LAYER] = 0; - - for (int i = 0; i < VS::ENV_FX_MAX; i++) - fx_enabled[i] = false; - - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES] = 1; - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE] = 1.0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH] = 1.0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE] = 0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM] = 0.0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_THRESHOLD] = 0.5; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES] = 1; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_BEGIN] = 100.0; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_RANGE] = 10.0; - fx_param[VS::ENV_FX_PARAM_HDR_TONEMAPPER] = VS::ENV_FX_HDR_TONE_MAPPER_LINEAR; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE] = 0.4; - fx_param[VS::ENV_FX_PARAM_HDR_WHITE] = 1.0; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_THRESHOLD] = 0.95; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_SCALE] = 0.2; - fx_param[VS::ENV_FX_PARAM_HDR_MIN_LUMINANCE] = 0.4; - fx_param[VS::ENV_FX_PARAM_HDR_MAX_LUMINANCE] = 8.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED] = 0.5; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN] = 100.0; - fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION] = 1.0; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR] = Color(0, 0, 0); - fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR] = Color(0, 0, 0); - fx_param[VS::ENV_FX_PARAM_FOG_BG] = true; - fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS] = 1.0; - fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST] = 1.0; - fx_param[VS::ENV_FX_PARAM_BCS_SATURATION] = 1.0; - } - }; - - mutable RID_Owner<Environment> environment_owner; - - struct SampledLight { - - int w, h; - GLuint texture; - float multiplier; - bool is_float; - }; - - mutable RID_Owner<SampledLight> sampled_light_owner; - - struct ViewportData { - - //1x1 fbo+texture for storing previous HDR value - GLuint lum_fbo; - GLuint lum_color; - - ViewportData() { - lum_fbo = 0; - lum_color = 0; - } - }; - - mutable RID_Owner<ViewportData> viewport_data_owner; - - struct RenderTarget { - - Texture *texture_ptr; - RID texture; - GLuint fbo; - GLuint color; - GLuint depth; - int width, height; - uint64_t last_pass; - }; - - mutable RID_Owner<RenderTarget> render_target_owner; - - struct ShadowBuffer; - - struct LightInstance { - - struct SplitInfo { - - CameraMatrix camera; - Transform transform; - float near; - float far; - }; - - RID light; - Light *base; - Transform transform; - CameraMatrix projection; - - Transform custom_transform[4]; - CameraMatrix custom_projection[4]; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - uint64_t shadow_pass; - uint64_t last_pass; - uint16_t sort_key; - - Vector2 dp; - - CameraMatrix shadow_projection[4]; - float shadow_split[4]; - - ShadowBuffer *near_shadow_buffer; - - void clear_shadow_buffers() { - - clear_near_shadow_buffers(); - } - - void clear_near_shadow_buffers() { - - if (near_shadow_buffer) { - near_shadow_buffer->owner = NULL; - near_shadow_buffer = NULL; - } - } - - LightInstance() { - shadow_pass = 0; - last_pass = 0; - sort_key = 0; - near_shadow_buffer = NULL; - } - }; - mutable RID_Owner<Light> light_owner; - mutable RID_Owner<LightInstance> light_instance_owner; - - LightInstance *light_instances[MAX_SCENE_LIGHTS]; - LightInstance *directional_lights[4]; - int light_instance_count; - int directional_light_count; - int last_light_id; - bool current_depth_test; - bool current_depth_mask; - VS::MaterialBlendMode current_blend_mode; - bool use_fast_texture_filter; - int max_texture_size; - - bool fragment_lighting; - RID shadow_material; - RID shadow_material_double_sided; - Material *shadow_mat_ptr; - Material *shadow_mat_double_sided_ptr; - - int max_texture_units; - GLuint base_framebuffer; - - GLuint gui_quad_buffer; - GLuint indices_buffer; - - struct RenderList { - - enum { - DEFAULT_MAX_ELEMENTS = 4096, - MAX_LIGHTS = 4, - SORT_FLAG_SKELETON = 1, - SORT_FLAG_INSTANCING = 2, - }; - - static int max_elements; - - struct Element { - - float depth; - const InstanceData *instance; - const Skeleton *skeleton; - const Geometry *geometry; - const Geometry *geometry_cmp; - const Material *material; - const GeometryOwner *owner; - bool *additive_ptr; - bool additive; - bool mirror; - union { -#ifdef BIG_ENDIAN_ENABLED - struct { - uint8_t sort_flags; - uint8_t light_type; - uint16_t light; - }; -#else - struct { - uint16_t light; - uint8_t light_type; - uint8_t sort_flags; - }; -#endif - uint32_t sort_key; - }; - }; - - Element *_elements; - Element **elements; - int element_count; - - void clear() { - - element_count = 0; - } - - struct SortZ { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - - return A->depth > B->depth; - } - }; - - void sort_z() { - - SortArray<Element *, SortZ> sorter; - sorter.sort(elements, element_count); - } - - struct SortMatGeom { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - // TODO move to a single uint64 (one comparison) - if (A->material->shader_cache == B->material->shader_cache) { - if (A->material == B->material) { - - return A->geometry_cmp < B->geometry_cmp; - } else { - - return (A->material < B->material); - } - } else { - - return A->material->shader_cache < B->material->shader_cache; - } - } - }; - - void sort_mat_geom() { - - SortArray<Element *, SortMatGeom> sorter; - sorter.sort(elements, element_count); - } - - struct SortMatLight { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - - if (A->geometry_cmp == B->geometry_cmp) { - - if (A->material == B->material) { - - return A->light < B->light; - } else { - - return (A->material < B->material); - } - } else { - - return (A->geometry_cmp < B->geometry_cmp); - } - } - }; - - void sort_mat_light() { - - SortArray<Element *, SortMatLight> sorter; - sorter.sort(elements, element_count); - } - - struct SortMatLightType { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - - if (A->light_type == B->light_type) { - if (A->material->shader_cache == B->material->shader_cache) { - if (A->material == B->material) { - - return (A->geometry_cmp < B->geometry_cmp); - } else { - - return (A->material < B->material); - } - } else { - - return (A->material->shader_cache < B->material->shader_cache); - } - } else { - - return A->light_type < B->light_type; - } - } - }; - - void sort_mat_light_type() { - - SortArray<Element *, SortMatLightType> sorter; - sorter.sort(elements, element_count); - } - - struct SortMatLightTypeFlags { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - - if (A->sort_key == B->sort_key) { - if (A->material->shader_cache == B->material->shader_cache) { - if (A->material == B->material) { - - return (A->geometry_cmp < B->geometry_cmp); - } else { - - return (A->material < B->material); - } - } else { - - return (A->material->shader_cache < B->material->shader_cache); - } - } else { - - return A->sort_key < B->sort_key; //one is null and one is not - } - } - }; - - void sort_mat_light_type_flags() { - - SortArray<Element *, SortMatLightTypeFlags> sorter; - sorter.sort(elements, element_count); - } - _FORCE_INLINE_ Element *add_element() { - - if (element_count >= max_elements) - return NULL; - elements[element_count] = &_elements[element_count]; - return elements[element_count++]; - } - - void init() { - - element_count = 0; - elements = memnew_arr(Element *, max_elements); - _elements = memnew_arr(Element, max_elements); - for (int i = 0; i < max_elements; i++) - elements[i] = &_elements[i]; // assign elements - } - - RenderList() { - } - ~RenderList() { - memdelete_arr(elements); - memdelete_arr(_elements); - } - }; - - RenderList opaque_render_list; - RenderList alpha_render_list; - - RID default_material; - - CameraMatrix camera_projection; - Transform camera_transform; - Transform camera_transform_inverse; - float camera_z_near; - float camera_z_far; - Size2 camera_vp_size; - bool camera_ortho; - Set<String> extensions; - bool texscreen_copied; - bool texscreen_used; - - Plane camera_plane; - - void _add_geometry(const Geometry *p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner, int p_material = -1); - void _render_list_forward(RenderList *p_render_list, const Transform &p_view_transform, const Transform &p_view_transform_inverse, const CameraMatrix &p_projection, bool p_reverse_cull = false, bool p_fragment_light = false, bool p_alpha_pass = false); - - //void _setup_light(LightInstance* p_instance, int p_idx); - void _setup_light(uint16_t p_light); - - _FORCE_INLINE_ void _setup_shader_params(const Material *p_material); - bool _setup_material(const Geometry *p_geometry, const Material *p_material, bool p_no_const_light, bool p_opaque_pass); - void _setup_skeleton(const Skeleton *p_skeleton); - - Error _setup_geometry(const Geometry *p_geometry, const Material *p_material, const Skeleton *p_skeleton, const float *p_morphs); - void _render(const Geometry *p_geometry, const Material *p_material, const Skeleton *p_skeleton, const GeometryOwner *p_owner, const Transform &p_xform); - - /***********/ - /* SHADOWS */ - /***********/ - - struct ShadowBuffer { - - int size; - GLuint fbo; - GLuint rbo; - GLuint depth; - GLuint rgba; //for older devices -#if 0 - GLuint fbo_blur; - GLuint rbo_blur; - GLuint blur; -#endif - - LightInstance *owner; - bool init(int p_size, bool p_use_depth); - ShadowBuffer() { - size = 0; - depth = 0; - owner = NULL; - } - }; - - Vector<ShadowBuffer> near_shadow_buffers; - ShadowBuffer blur_shadow_buffer; - - Vector<ShadowBuffer> far_shadow_buffers; - - LightInstance *shadow; - int shadow_pass; - - float shadow_near_far_split_size_ratio; - bool _allocate_shadow_buffers(LightInstance *p_instance, Vector<ShadowBuffer> &p_buffers); - void _debug_draw_shadow(GLuint tex, const Rect2 &p_rect); - void _debug_draw_shadows_type(Vector<ShadowBuffer> &p_shadows, Point2 &ofs); - void _debug_shadows(); - void _debug_luminances(); - void _debug_samplers(); - - /***********/ - /* FBOs */ - /***********/ - - struct FrameBuffer { - - GLuint fbo; - GLuint color; - GLuint depth; - - int width, height; - int scale; - bool active; - - int blur_size; - - struct Blur { - - GLuint fbo; - GLuint color; - - Blur() { - fbo = 0; - color = 0; - } - } blur[3]; - - struct Luminance { - - int size; - GLuint fbo; - GLuint color; - - Luminance() { - fbo = 0; - color = 0; - size = 0; - } - }; - - Vector<Luminance> luminance; - - GLuint sample_fbo; - GLuint sample_color; - - FrameBuffer() { - blur_size = 0; - } - - } framebuffer; - - void _update_framebuffer(); - void _process_glow_and_bloom(); - //void _update_blur_buffer(); - - /*********/ - /* FRAME */ - /*********/ - - struct _Rinfo { - - int texture_mem; - int vertex_count; - int object_count; - int mat_change_count; - int surface_count; - int shader_change_count; - int ci_draw_commands; - int draw_calls; - - } _rinfo; - - /*******************/ - /* CANVAS OCCLUDER */ - /*******************/ - - struct CanvasOccluder { - - GLuint vertex_id; // 0 means, unconfigured - GLuint index_id; // 0 means, unconfigured - DVector<Vector2> lines; - int len; - }; - - RID_Owner<CanvasOccluder> canvas_occluder_owner; - - /***********************/ - /* CANVAS LIGHT SHADOW */ - /***********************/ - - struct CanvasLightShadow { - - int size; - int height; - GLuint fbo; - GLuint rbo; - GLuint depth; - GLuint rgba; //for older devices - - GLuint blur; - }; - - RID_Owner<CanvasLightShadow> canvas_light_shadow_owner; - - RID canvas_shadow_blur; - - /* ETC */ - - RenderTarget *current_rt; - bool current_rt_transparent; - bool current_rt_vflip; - ViewportData *current_vd; - - GLuint white_tex; - RID canvas_tex; - float canvas_opacity; - Color canvas_modulate; - bool canvas_use_modulate; - bool uses_texpixel_size; - bool rebind_texpixel_size; - Transform canvas_transform; - ShaderMaterial *canvas_last_material; - bool canvas_texscreen_used; - Vector2 normal_flip; - _FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2 &p_flip); - - _FORCE_INLINE_ Texture *_bind_canvas_texture(const RID &p_texture); - VS::MaterialBlendMode canvas_blend_mode; - - int _setup_geometry_vinfo; - - bool pack_arrays; - bool keep_copies; - bool use_reload_hooks; - bool cull_front; - bool lights_use_shadow; - _FORCE_INLINE_ void _set_cull(bool p_front, bool p_reverse_cull = false); - _FORCE_INLINE_ Color _convert_color(const Color &p_color); - - void _process_glow_bloom(); - void _process_hdr(); - void _draw_tex_bg(); - - bool using_canvas_bg; - Size2 window_size; - VS::ViewportRect viewport; - double last_time; - double time_delta; - uint64_t frame; - uint64_t scene_pass; - bool draw_next_frame; - Environment *current_env; - VS::ScenarioDebugMode current_debug; - RID overdraw_material; - float shader_time_rollback; - - mutable MaterialShaderGLES2 material_shader; - mutable CanvasShaderGLES2 canvas_shader; - BlurShaderGLES2 blur_shader; - CopyShaderGLES2 copy_shader; - mutable CanvasShadowShaderGLES2 canvas_shadow_shader; - - mutable ShaderCompilerGLES2 shader_precompiler; - - void _draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color *p_colors, const Vector3 *p_uvs, const Plane *p_tangents = NULL, int p_instanced = 1); - _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_gui_primitive2(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs, const Vector2 *p_uvs2); - void _draw_textured_quad(const Rect2 &p_rect, const Rect2 &p_src_region, const Size2 &p_tex_size, bool p_h_flip = false, bool p_v_flip = false, bool p_transpose = false); - void _draw_quad(const Rect2 &p_rect); - void _copy_screen_quad(); - void _copy_to_texscreen(); - - bool _test_depth_shadow_buffer(); - - Vector3 chunk_vertex; - Vector3 chunk_normal; - Plane chunk_tangent; - Color chunk_color; - Vector2 chunk_uv; - Vector2 chunk_uv2; - GLuint tc0_id_cache; - GLuint tc0_idx; - - template <bool use_normalmap> - _FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item, CanvasItem *current_clip, bool &reclip); - _FORCE_INLINE_ void _canvas_item_setup_shader_params(ShaderMaterial *material, Shader *p_shader); - _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(ShaderMaterial *material, Shader *p_shader); - -public: - /* TEXTURE API */ - - virtual RID texture_create(); - virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT); - virtual void texture_set_data(RID p_texture, const Image &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT); - virtual Image texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) 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 uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual bool texture_has_alpha(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); - virtual void texture_set_reload_hook(RID p_texture, ObjectID p_owner, const StringName &p_function) const; - - virtual void texture_set_path(RID p_texture, const String &p_path); - virtual String texture_get_path(RID p_texture) const; - virtual void texture_debug_usage(List<VS::TextureInfo> *r_info); - - virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); - - GLuint _texture_get_name(RID p_tex); - - /* SHADER API */ - - virtual RID shader_create(VS::ShaderMode p_mode = VS::SHADER_MATERIAL); - - virtual void shader_set_mode(RID p_shader, VS::ShaderMode p_mode); - virtual VS::ShaderMode shader_get_mode(RID p_shader) const; - - virtual void shader_set_code(RID p_shader, const String &p_vertex, const String &p_fragment, const String &p_light, int p_vertex_ofs = 0, int p_fragment_ofs = 0, int p_light_ofs = 0); - virtual String shader_get_fragment_code(RID p_shader) const; - virtual String shader_get_vertex_code(RID p_shader) const; - virtual String shader_get_light_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; - - virtual Variant shader_get_default_param(RID p_shader, const StringName &p_name); - - /* COMMON MATERIAL API */ - - virtual RID material_create(); - - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_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 void material_set_flag(RID p_material, VS::MaterialFlag p_flag, bool p_enabled); - virtual bool material_get_flag(RID p_material, VS::MaterialFlag p_flag) const; - - virtual void material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode); - virtual VS::MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const; - - virtual void material_set_blend_mode(RID p_material, VS::MaterialBlendMode p_mode); - virtual VS::MaterialBlendMode material_get_blend_mode(RID p_material) const; - - virtual void material_set_line_width(RID p_material, float p_line_width); - virtual float material_get_line_width(RID p_material) const; - - /* MESH API */ - - virtual RID mesh_create(); - - virtual void mesh_add_surface(RID p_mesh, VS::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), bool p_alpha_sort = false); - virtual Array mesh_get_surface_arrays(RID p_mesh, int p_surface) const; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh, int p_surface) const; - virtual void mesh_add_custom_surface(RID p_mesh, const Variant &p_dat); - - virtual void mesh_set_morph_target_count(RID p_mesh, int p_amount); - virtual int mesh_get_morph_target_count(RID p_mesh) const; - - virtual void mesh_set_morph_target_mode(RID p_mesh, VS::MorphTargetMode p_mode); - virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material, bool p_owned = false); - 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 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 void mesh_remove_surface(RID p_mesh, int p_index); - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) const; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - /* MULTIMESH API */ - - virtual RID multimesh_create(); - - virtual void multimesh_set_instance_count(RID p_multimesh, int p_count); - virtual int multimesh_get_instance_count(RID p_multimesh) const; - - virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh); - virtual void multimesh_set_aabb(RID p_multimesh, const AABB &p_aabb); - virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform); - virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); - - virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_multimesh) const; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const; - virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; - - virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible); - virtual int multimesh_get_visible_instances(RID p_multimesh) const; - - /* IMMEDIATE API */ - - virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID()); - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex); - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal); - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent); - virtual void immediate_color(RID p_immediate, const Color &p_color); - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv); - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv); - virtual void immediate_end(RID p_immediate); - virtual void immediate_clear(RID p_immediate); - virtual AABB immediate_get_aabb(RID p_immediate) const; - virtual void immediate_set_material(RID p_immediate, RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; - - /* PARTICLES API */ - - virtual RID particles_create(); - - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual int particles_get_amount(RID p_particles) const; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_is_emitting(RID p_particles) const; - - virtual void particles_set_visibility_aabb(RID p_particles, const AABB &p_visibility); - virtual AABB particles_get_visibility_aabb(RID p_particles) const; - - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3 &p_half_extents); - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const; - - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3 &p_base_velocity); - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3> &p_points); - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3 &p_normal); - virtual Vector3 particles_get_gravity_normal(RID p_particles) const; - - virtual void particles_set_variable(RID p_particles, VS::ParticleVariable p_variable, float p_value); - virtual float particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable, float p_randomness); - virtual float particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos); - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const; - - virtual void particles_set_color_phases(RID p_particles, int p_phases); - virtual int particles_get_color_phases(RID p_particles) const; - - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color &p_color); - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const; - - virtual void particles_set_attractors(RID p_particles, int p_attractors); - virtual int particles_get_attractors(RID p_particles) const; - - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3 &p_pos); - virtual Vector3 particles_get_attractor_pos(RID p_particles, int p_attractor) const; - - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force); - virtual float particles_get_attractor_strength(RID p_particles, int p_attractor) const; - - virtual void particles_set_material(RID p_particles, RID p_material, bool p_owned = false); - virtual RID particles_get_material(RID p_particles) const; - - virtual AABB particles_get_aabb(RID p_particles) const; - - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable); - virtual bool particles_has_height_from_velocity(RID p_particles) const; - - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual bool particles_is_using_local_coordinates(RID p_particles) const; - - /* SKELETON API */ - - virtual RID skeleton_create(); - virtual void skeleton_resize(RID p_skeleton, int p_bones); - 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); - - /* LIGHT API */ - - virtual RID light_create(VS::LightType p_type); - virtual VS::LightType light_get_type(RID p_light) const; - - virtual void light_set_color(RID p_light, VS::LightColor p_type, const Color &p_color); - virtual Color light_get_color(RID p_light, VS::LightColor p_type) const; - - virtual void light_set_shadow(RID p_light, bool p_enabled); - virtual bool light_has_shadow(RID p_light) const; - - virtual void light_set_volumetric(RID p_light, bool p_enabled); - virtual bool light_is_volumetric(RID p_light) const; - - virtual void light_set_projector(RID p_light, RID p_texture); - virtual RID light_get_projector(RID p_light) const; - - virtual void light_set_var(RID p_light, VS::LightParam p_var, float p_value); - virtual float light_get_var(RID p_light, VS::LightParam p_var) const; - - virtual void light_set_operator(RID p_light, VS::LightOp p_op); - virtual VS::LightOp light_get_operator(RID p_light) const; - - virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode); - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const; - - virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode); - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const; - virtual void light_directional_set_shadow_param(RID p_light, VS::LightDirectionalShadowParam p_param, float p_value); - virtual float light_directional_get_shadow_param(RID p_light, VS::LightDirectionalShadowParam p_param) const; - - virtual AABB light_get_aabb(RID p_poly) const; - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform); - - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance, bool p_far = false) const; - virtual int light_instance_get_shadow_passes(RID p_light_instance) const; - virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const; - virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix &p_camera, const Transform &p_transform, float p_split_near = 0, float p_split_far = 0); - virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index = 0) const; - - virtual void shadow_clear_near(); - virtual bool shadow_allocate_near(RID p_light); - virtual bool shadow_allocate_far(RID p_light); - - /* SHADOW */ - - virtual RID particles_instance_create(RID p_particles); - virtual void particles_instance_set_transform(RID p_particles_instance, const Transform &p_transform); - - /* VIEWPORT */ - - virtual RID viewport_data_create(); - - virtual RID render_target_create(); - 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 bool render_target_renedered_in_frame(RID p_render_target); - - /* RENDER API */ - /* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - virtual void begin_frame(); - - virtual void set_viewport(const VS::ViewportRect &p_viewport); - virtual void set_render_target(RID p_render_target, bool p_transparent_bg = false, bool p_vflip = false); - virtual void clear_viewport(const Color &p_color); - virtual void capture_viewport(Image *r_capture); - - virtual void begin_scene(RID p_viewport_data, RID p_env, VS::ScenarioDebugMode p_debug); - - virtual void begin_shadow_map(RID p_light_instance, int p_shadow_pass); - - virtual void set_camera(const Transform &p_world, const CameraMatrix &p_projection, bool p_ortho_hint); - - virtual void add_light(RID p_light_instance); ///< all "add_light" calls happen before add_geometry calls - - typedef Map<StringName, Variant> ParamOverrideMap; - - virtual void add_mesh(const RID &p_mesh, const InstanceData *p_data); - virtual void add_multimesh(const RID &p_multimesh, const InstanceData *p_data); - virtual void add_immediate(const RID &p_immediate, const InstanceData *p_data); - virtual void add_particles(const RID &p_particle_instance, const InstanceData *p_data); - - virtual void end_scene(); - virtual void end_shadow_map(); - - virtual void end_frame(); - - /* CANVAS API */ - - virtual void begin_canvas_bg(); - - virtual void canvas_begin(); - virtual void canvas_disable_blending(); - - virtual void canvas_set_opacity(float p_opacity); - virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode); - virtual void canvas_begin_rect(const Transform2D &p_transform); - virtual void canvas_set_clip(bool p_clip, const Rect2 &p_rect); - virtual void canvas_end_rect(); - virtual void canvas_draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width, bool p_antialiased); - virtual void canvas_draw_rect(const Rect2 &p_rect, int p_flags, const Rect2 &p_source, RID p_texture, const Color &p_modulate); - virtual void canvas_draw_style_box(const Rect2 &p_rect, const Rect2 &p_src_region, RID p_texture, const float *p_margins, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)); - virtual void canvas_draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width); - virtual void canvas_draw_polygon(int p_vertex_count, const int *p_indices, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, const RID &p_texture, bool p_singlecolor); - virtual void canvas_set_transform(const Transform2D &p_transform); - - virtual void canvas_render_items(CanvasItem *p_item_list, int p_z, const Color &p_modulate, CanvasLight *p_light); - virtual void canvas_debug_viewport_shadows(CanvasLight *p_lights_with_shadow); - - /* CANVAS LIGHT SHADOW */ - - //buffer - virtual RID canvas_light_shadow_buffer_create(int p_width); - 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, CanvasLightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache); - - //occluder - virtual RID canvas_light_occluder_create(); - virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2> &p_lines); - - /* ENVIRONMENT */ - - virtual RID environment_create(); - - virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg); - virtual VS::EnvironmentBG environment_get_background(RID p_env) const; - - virtual void environment_set_background_param(RID p_env, VS::EnvironmentBGParam p_param, const Variant &p_value); - virtual Variant environment_get_background_param(RID p_env, VS::EnvironmentBGParam p_param) const; - - virtual void environment_set_enable_fx(RID p_env, VS::EnvironmentFx p_effect, bool p_enabled); - virtual bool environment_is_fx_enabled(RID p_env, VS::EnvironmentFx p_effect) const; - - virtual void environment_fx_set_param(RID p_env, VS::EnvironmentFxParam p_param, const Variant &p_value); - virtual Variant environment_fx_get_param(RID p_env, VS::EnvironmentFxParam p_param) const; - - /* SAMPLED LIGHT */ - virtual RID sampled_light_dp_create(int p_width, int p_height); - virtual void sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier); - - /*MISC*/ - - virtual bool is_texture(const RID &p_rid) const; - virtual bool is_material(const RID &p_rid) const; - virtual bool is_mesh(const RID &p_rid) const; - virtual bool is_immediate(const RID &p_rid) const; - virtual bool is_multimesh(const RID &p_rid) const; - virtual bool is_particles(const RID &p_beam) const; - - virtual bool is_light(const RID &p_rid) const; - virtual bool is_light_instance(const RID &p_rid) const; - virtual bool is_particles_instance(const RID &p_rid) const; - virtual bool is_skeleton(const RID &p_rid) const; - virtual bool is_environment(const RID &p_rid) const; - virtual bool is_shader(const RID &p_rid) const; - - virtual bool is_canvas_light_occluder(const RID &p_rid) const; - - virtual void free(const RID &p_rid); - - virtual void init(); - virtual void finish(); - - virtual int get_render_info(VS::RenderInfo p_info); - - void set_base_framebuffer(GLuint p_id, Vector2 p_size = Vector2(0, 0)); - - virtual void flush_frame(); //not necessary in most cases - void set_extensions(const char *p_strings); - - virtual bool needs_to_draw_next_frame() const; - - void set_use_framebuffers(bool p_use); - void reload_vram(); - - virtual bool has_feature(VS::Features p_feature) const; - - virtual void restore_framebuffer(); - - static RasterizerGLES2 *get_singleton(); - - virtual void set_force_16_bits_fbo(bool p_force); - - RasterizerGLES2(bool p_compress_arrays = false, bool p_keep_ram_copy = true, bool p_default_fragment_lighting = true, bool p_use_reload_hooks = false); - virtual ~RasterizerGLES2(); -}; - -#endif -#endif diff --git a/drivers/gles2/rasterizer_instance_gles2.cpp b/drivers/gles2/rasterizer_instance_gles2.cpp deleted file mode 100644 index 8aedd4def0..0000000000 --- a/drivers/gles2/rasterizer_instance_gles2.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************/ -/* rasterizer_instance_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 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_instance_gles2.h" -#include "rasterizer_gles2.h" - -#ifdef GLES2_ENABLED - -Rasterizer *instance_RasterizerGLES2() { - - return memnew(RasterizerGLES2); -} - -#endif diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp deleted file mode 100644 index 778d28fb99..0000000000 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ /dev/null @@ -1,939 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "shader_compiler_gles2.h" -#include "print_string.h" - -#include "stdio.h" - -//#define DEBUG_SHADER_ENABLED - -typedef ShaderLanguage SL; - -struct CodeGLSL2 { - - String code; -}; - -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) { - - switch (p_type) { - - case SL::TYPE_VOID: return "void"; - case SL::TYPE_BOOL: return "bool"; - case SL::TYPE_FLOAT: return "float"; - case SL::TYPE_VEC2: return "vec2"; - case SL::TYPE_VEC3: return "vec3"; - case SL::TYPE_VEC4: return "vec4"; - case SL::TYPE_MAT2: return "mat2"; - case SL::TYPE_MAT3: return "mat3"; - case SL::TYPE_MAT4: return "mat4"; - case SL::TYPE_TEXTURE: return "sampler2D"; - case SL::TYPE_CUBEMAP: return "samplerCube"; - } - - return ""; -} - -static String _mknum(float p_num) { - return String::num_real(p_num); -} - -static String _opstr(SL::Operator p_op) { - - switch (p_op) { - case SL::OP_ASSIGN: return "="; - case SL::OP_ADD: return "+"; - case SL::OP_SUB: return "-"; - case SL::OP_MUL: return "*"; - case SL::OP_DIV: return "/"; - case SL::OP_ASSIGN_ADD: return "+="; - case SL::OP_ASSIGN_SUB: return "-="; - case SL::OP_ASSIGN_MUL: return "*="; - case SL::OP_ASSIGN_DIV: return "/="; - case SL::OP_NEG: return "-"; - case SL::OP_NOT: return "!"; - case SL::OP_CMP_EQ: return "=="; - case SL::OP_CMP_NEQ: return "!="; - case SL::OP_CMP_LEQ: return "<="; - case SL::OP_CMP_GEQ: return ">="; - case SL::OP_CMP_LESS: return "<"; - case SL::OP_CMP_GREATER: return ">"; - case SL::OP_CMP_OR: return "||"; - case SL::OP_CMP_AND: return "&&"; - default: return ""; - } - - return ""; -} - -//#ifdef DEBUG_SHADER_ENABLED -#if 1 -#define ENDL "\n" -#else -#define ENDL "" -#endif - -String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node, int p_level, bool p_assign_left) { - - String code; - - switch (p_node->type) { - - case SL::Node::TYPE_PROGRAM: { - - SL::ProgramNode *pnode = (SL::ProgramNode *)p_node; - - 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 - code += "{" ENDL; - for (Map<StringName, SL::DataType>::Element *E = bnode->variables.front(); E; E = E->next()) { - - code += _mktab(p_level) + _typestr(E->value()) + " " + replace_string(E->key()) + ";" ENDL; - } - - for (int i = 0; i < bnode->statements.size(); i++) { - - code += _mktab(p_level) + dump_node_code(bnode->statements[i], p_level) + ";" ENDL; - } - - code += "}" ENDL; - - } break; - case SL::Node::TYPE_VARIABLE: { - SL::VariableNode *vnode = (SL::VariableNode *)p_node; - - if (type == ShaderLanguage::SHADER_MATERIAL_VERTEX) { - - if (vnode->name == vname_vertex && p_assign_left) { - vertex_code_writes_vertex = true; - } - if (vnode->name == vname_position && p_assign_left) { - vertex_code_writes_position = true; - } - if (vnode->name == vname_color_interp) { - flags->use_color_interp = true; - } - if (vnode->name == vname_uv_interp) { - flags->use_uv_interp = true; - } - if (vnode->name == vname_uv2_interp) { - flags->use_uv2_interp = true; - } - if (vnode->name == vname_var1_interp) { - flags->use_var1_interp = true; - } - if (vnode->name == vname_var2_interp) { - flags->use_var2_interp = true; - } - if (vnode->name == vname_tangent_interp || vnode->name == vname_binormal_interp) { - flags->use_tangent_interp = true; - } - } - - if (type == ShaderLanguage::SHADER_MATERIAL_FRAGMENT) { - - if (vnode->name == vname_discard) { - uses_discard = true; - } - if (vnode->name == vname_normalmap) { - uses_normalmap = true; - } - if (vnode->name == vname_screen_uv) { - uses_screen_uv = true; - } - if (vnode->name == vname_diffuse_alpha && p_assign_left) { - uses_alpha = true; - } - if (vnode->name == vname_color_interp) { - flags->use_color_interp = true; - } - if (vnode->name == vname_uv_interp) { - flags->use_uv_interp = true; - } - if (vnode->name == vname_uv2_interp) { - flags->use_uv2_interp = true; - } - if (vnode->name == vname_var1_interp) { - flags->use_var1_interp = true; - } - if (vnode->name == vname_var2_interp) { - flags->use_var2_interp = true; - } - if (vnode->name == vname_tangent_interp || vnode->name == vname_binormal_interp) { - flags->use_tangent_interp = true; - } - } - if (type == ShaderLanguage::SHADER_MATERIAL_LIGHT) { - - if (vnode->name == vname_light) { - uses_light = true; - } - - if (vnode->name == vname_shadow) { - uses_shadow_color = true; - } - } - if (type == ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX) { - - if (vnode->name == vname_var1_interp) { - flags->use_var1_interp = true; - } - if (vnode->name == vname_var2_interp) { - flags->use_var2_interp = true; - } - if (vnode->name == vname_world_vec) { - uses_worldvec = true; - } - } - - if (type == ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT) { - - if (vnode->name == vname_texpixel_size) { - uses_texpixel_size = true; - } - if (vnode->name == vname_normal) { - uses_normal = true; - } - if (vnode->name == vname_normalmap || vnode->name == vname_normalmap_depth) { - uses_normalmap = true; - uses_normal = true; - } - - if (vnode->name == vname_screen_uv) { - uses_screen_uv = true; - } - - if (vnode->name == vname_var1_interp) { - flags->use_var1_interp = true; - } - if (vnode->name == vname_var2_interp) { - flags->use_var2_interp = true; - } - } - - if (type == ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT) { - - if (vnode->name == vname_light) { - uses_light = true; - } - - if (vnode->name == vname_normal) { - uses_normal = true; - } - - if (vnode->name == vname_shadow) { - uses_shadow_color = true; - } - } - - if (vnode->name == vname_time) { - uses_time = true; - } - code = replace_string(vnode->name); - - } break; - case SL::Node::TYPE_CONSTANT: { - SL::ConstantNode *cnode = (SL::ConstantNode *)p_node; - switch (cnode->datatype) { - - case SL::TYPE_BOOL: code = cnode->value.operator bool() ? "true" : "false"; break; - case SL::TYPE_FLOAT: - code = _mknum(cnode->value); - break; //force zeros, so GLSL doesn't confuse with integer. - case SL::TYPE_VEC2: { - Vector2 v = cnode->value; - code = "vec2(" + _mknum(v.x) + ", " + _mknum(v.y) + ")"; - } break; - case SL::TYPE_VEC3: { - Vector3 v = cnode->value; - code = "vec3(" + _mknum(v.x) + ", " + _mknum(v.y) + ", " + _mknum(v.z) + ")"; - } break; - case SL::TYPE_VEC4: { - Plane v = cnode->value; - code = "vec4(" + _mknum(v.normal.x) + ", " + _mknum(v.normal.y) + ", " + _mknum(v.normal.z) + ", " + _mknum(v.d) + ")"; - } break; - case SL::TYPE_MAT2: { - Transform2D x = cnode->value; - code = "mat2( vec2(" + _mknum(x[0][0]) + ", " + _mknum(x[0][1]) + "), vec2(" + _mknum(x[1][0]) + ", " + _mknum(x[1][1]) + "))"; - } break; - case SL::TYPE_MAT3: { - Basis x = cnode->value; - code = "mat3( vec3(" + _mknum(x.get_axis(0).x) + ", " + _mknum(x.get_axis(0).y) + ", " + _mknum(x.get_axis(0).z) + "), vec3(" + _mknum(x.get_axis(1).x) + ", " + _mknum(x.get_axis(1).y) + ", " + _mknum(x.get_axis(1).z) + "), vec3(" + _mknum(x.get_axis(2).x) + ", " + _mknum(x.get_axis(2).y) + ", " + _mknum(x.get_axis(2).z) + "))"; - } break; - case SL::TYPE_MAT4: { - Transform x = cnode->value; - code = "mat4( vec4(" + _mknum(x.basis.get_axis(0).x) + ", " + _mknum(x.basis.get_axis(0).y) + ", " + _mknum(x.basis.get_axis(0).z) + ",0.0), vec4(" + _mknum(x.basis.get_axis(1).x) + ", " + _mknum(x.basis.get_axis(1).y) + ", " + _mknum(x.basis.get_axis(1).z) + ",0.0), vec4(" + _mknum(x.basis.get_axis(2).x) + ", " + _mknum(x.basis.get_axis(2).y) + ", " + _mknum(x.basis.get_axis(2).z) + ",0.0), vec4(" + _mknum(x.origin.x) + ", " + _mknum(x.origin.y) + ", " + _mknum(x.origin.z) + ",1.0))"; - } break; - default: code = "<error: " + Variant::get_type_name(cnode->value.get_type()) + " (" + itos(cnode->datatype) + ">"; - } - - } break; - case SL::Node::TYPE_OPERATOR: { - SL::OperatorNode *onode = (SL::OperatorNode *)p_node; - - switch (onode->op) { - - case SL::OP_ASSIGN_MUL: { - - if (onode->arguments[0]->get_datatype() == SL::TYPE_VEC3 && onode->arguments[1]->get_datatype() == SL::TYPE_MAT4) { - - String mul_l = dump_node_code(onode->arguments[0], p_level, true); - String mul_r = dump_node_code(onode->arguments[1], p_level); - code = mul_l + "=(vec4(" + mul_l + ",1.0)*(" + mul_r + ")).xyz"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_MAT4 && onode->arguments[1]->get_datatype() == SL::TYPE_VEC3) { - - String mul_l = dump_node_code(onode->arguments[0], p_level, true); - String mul_r = dump_node_code(onode->arguments[1], p_level); - code = mul_l + "=((" + mul_l + ")*vec4(" + mul_r + ",1.0)).xyz"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_VEC2 && onode->arguments[1]->get_datatype() == SL::TYPE_MAT4) { - - String mul_l = dump_node_code(onode->arguments[0], p_level, true); - String mul_r = dump_node_code(onode->arguments[1], p_level); - code = mul_l + "=(vec4(" + mul_l + ",0.0,1.0)*(" + mul_r + ")).xy"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_MAT4 && onode->arguments[1]->get_datatype() == SL::TYPE_VEC2) { - - String mul_l = dump_node_code(onode->arguments[0], p_level, true); - String mul_r = dump_node_code(onode->arguments[1], p_level); - code = mul_l + "=((" + mul_l + ")*vec4(" + mul_r + ",0.0,1.0)).xy"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_VEC2 && onode->arguments[1]->get_datatype() == SL::TYPE_MAT3) { - String mul_l = dump_node_code(onode->arguments[0], p_level, true); - String mul_r = dump_node_code(onode->arguments[1], p_level); - code = mul_l + "=((" + mul_l + ")*vec3(" + mul_r + ",1.0)).xy"; - break; - } - }; - case SL::OP_ASSIGN: - case SL::OP_ASSIGN_ADD: - case SL::OP_ASSIGN_SUB: - case SL::OP_ASSIGN_DIV: - code = "(" + dump_node_code(onode->arguments[0], p_level, true) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")"; - break; - - case SL::OP_MUL: - - if (onode->arguments[0]->get_datatype() == SL::TYPE_MAT4 && onode->arguments[1]->get_datatype() == SL::TYPE_VEC3) { - - code = "(" + dump_node_code(onode->arguments[0], p_level) + "*vec4(" + dump_node_code(onode->arguments[1], p_level) + ",1.0)).xyz"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_VEC3 && onode->arguments[1]->get_datatype() == SL::TYPE_MAT4) { - - code = "(vec4(" + dump_node_code(onode->arguments[0], p_level) + ",1.0)*" + dump_node_code(onode->arguments[1], p_level) + ").xyz"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_MAT4 && onode->arguments[1]->get_datatype() == SL::TYPE_VEC2) { - - code = "(" + dump_node_code(onode->arguments[0], p_level) + "*vec4(" + dump_node_code(onode->arguments[1], p_level) + ",0.0,1.0)).xy"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_VEC2 && onode->arguments[1]->get_datatype() == SL::TYPE_MAT4) { - - code = "(vec4(" + dump_node_code(onode->arguments[0], p_level) + ",0.0,1.0)*" + dump_node_code(onode->arguments[1], p_level) + ").xy"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_MAT3 && onode->arguments[1]->get_datatype() == SL::TYPE_VEC2) { - - code = "(" + dump_node_code(onode->arguments[0], p_level) + "*vec3(" + dump_node_code(onode->arguments[1], p_level) + ",1.0)).xy"; - break; - } else if (onode->arguments[0]->get_datatype() == SL::TYPE_VEC2 && onode->arguments[1]->get_datatype() == SL::TYPE_MAT3) { - - code = "(vec3(" + dump_node_code(onode->arguments[0], p_level) + ",1.0)*" + dump_node_code(onode->arguments[1], p_level) + ").xy"; - break; - } - - case SL::OP_ADD: - case SL::OP_SUB: - case SL::OP_DIV: - case SL::OP_CMP_EQ: - case SL::OP_CMP_NEQ: - case SL::OP_CMP_LEQ: - case SL::OP_CMP_GEQ: - case SL::OP_CMP_LESS: - case SL::OP_CMP_GREATER: - case SL::OP_CMP_OR: - case SL::OP_CMP_AND: - //handle binary - code = "(" + dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")"; - break; - case SL::OP_NEG: - case SL::OP_NOT: - //handle unary - code = _opstr(onode->op) + dump_node_code(onode->arguments[0], p_level); - break; - case SL::OP_CONSTRUCT: - case SL::OP_CALL: { - String callfunc = dump_node_code(onode->arguments[0], p_level); - - code = callfunc + "("; - /*if (callfunc=="mat4") { - //fix constructor for mat4 - for(int i=1;i<onode->arguments.size();i++) { - if (i>1) - code+=", "; - //transform - code+="vec4( "+dump_node_code(onode->arguments[i],p_level)+(i==4?",1.0)":",0.0)"); - - } - } else*/ if (callfunc == "tex") { - - code = "texture2D( " + dump_node_code(onode->arguments[1], p_level) + "," + dump_node_code(onode->arguments[2], p_level) + ")"; - break; - } else if (callfunc == "texcube") { - - code = "(textureCube( " + dump_node_code(onode->arguments[1], p_level) + ",(" + dump_node_code(onode->arguments[2], p_level) + ")).xyz"; - break; - } else if (callfunc == "texscreen") { - //create the call to sample the screen, and clamp it - uses_texscreen = true; - code = "(texture2D( texscreen_tex, clamp((" + dump_node_code(onode->arguments[1], p_level) + ").xy*texscreen_screen_mult,texscreen_screen_clamp.xy,texscreen_screen_clamp.zw))).rgb"; - //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; - break; - } else if (callfunc == "texpos") { - //create the call to sample the screen, and clamp it - uses_texpos = true; - code = "get_texpos(" + dump_node_code(onode->arguments[1], p_level) + ""; - //code="get_texpos(gl_ProjectionMatrixInverse * texture2D( depth_texture, clamp(("+dump_node_code(onode->arguments[1],p_level)+").xy,vec2(0.0),vec2(1.0))*gl_LightSource[5].specular.zw+gl_LightSource[5].specular.xy)"; - //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; - break; - } else if (custom_h && callfunc == "cosh_custom") { - - if (!cosh_used) { - global_code = - "float cosh_custom(float val)\n" - "{\n" - " float tmp = exp(val);\n" - " float cosH = (tmp + 1.0 / tmp) / 2.0;\n" - " return cosH;\n" - "}\n" + - global_code; - cosh_used = true; - } - code = "cosh_custom(" + dump_node_code(onode->arguments[1], p_level) + ""; - } else if (custom_h && callfunc == "sinh_custom") { - - if (!sinh_used) { - global_code = - "float sinh_custom(float val)\n" - "{\n" - " float tmp = exp(val);\n" - " float sinH = (tmp - 1.0 / tmp) / 2.0;\n" - " return sinH;\n" - "}\n" + - global_code; - sinh_used = true; - } - code = "sinh_custom(" + dump_node_code(onode->arguments[1], p_level) + ""; - } else if (custom_h && callfunc == "tanh_custom") { - - if (!tanh_used) { - global_code = - "float tanh_custom(float val)\n" - "{\n" - " float tmp = exp(val);\n" - " float tanH = (tmp - 1.0 / tmp) / (tmp + 1.0 / tmp);\n" - " return tanH;\n" - "}\n" + - global_code; - tanh_used = true; - } - code = "tanh_custom(" + dump_node_code(onode->arguments[1], p_level) + ""; - - } else { - - for (int i = 1; i < onode->arguments.size(); i++) { - if (i > 1) - code += ", "; - //transform - code += dump_node_code(onode->arguments[i], p_level); - } - } - code += ")"; - break; - } break; - default: {} - } - - } break; - case SL::Node::TYPE_CONTROL_FLOW: { - SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node; - if (cfnode->flow_op == SL::FLOW_OP_IF) { - - code += "if (" + dump_node_code(cfnode->statements[0], p_level) + ") {" ENDL; - code += dump_node_code(cfnode->statements[1], p_level + 1); - if (cfnode->statements.size() == 3) { - - code += "} else {" ENDL; - code += dump_node_code(cfnode->statements[2], p_level + 1); - } - - code += "}" ENDL; - - } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) { - - if (cfnode->statements.size()) { - code = "return " + dump_node_code(cfnode->statements[0], p_level); - } else { - code = "return"; - } - } - - } break; - case SL::Node::TYPE_MEMBER: { - SL::MemberNode *mnode = (SL::MemberNode *)p_node; - String m; - if (mnode->basetype == SL::TYPE_MAT4) { - if (mnode->name == "x") - m = "[0]"; - else if (mnode->name == "y") - m = "[1]"; - else if (mnode->name == "z") - m = "[2]"; - else if (mnode->name == "w") - m = "[3]"; - } else if (mnode->basetype == SL::TYPE_MAT2) { - if (mnode->name == "x") - m = "[0]"; - else if (mnode->name == "y") - m = "[1]"; - - } else if (mnode->basetype == SL::TYPE_MAT3) { - if (mnode->name == "x") - m = "[0]"; - else if (mnode->name == "y") - m = "[1]"; - else if (mnode->name == "z") - m = "[2]"; - - } else { - m = "." + mnode->name; - } - code = dump_node_code(mnode->owner, p_level) + m; - - } break; - } - - return code; -} - -Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) { - - // feed the local replace table and global code - global_code = ""; - - // uniforms first! - - int ubase = 0; - if (uniforms) - ubase = uniforms->size(); - for (Map<StringName, SL::Uniform>::Element *E = p_program->uniforms.front(); E; E = E->next()) { - - String uline = "uniform " + _typestr(E->get().type) + " _" + E->key().operator String() + ";" ENDL; - - global_code += uline; - if (uniforms) { - /* - if (uniforms->has(E->key())) { - //repeated uniform, error - ERR_EXPLAIN("Uniform already exists from other shader: "+String(E->key())); - ERR_FAIL_COND_V(uniforms->has(E->key()),ERR_ALREADY_EXISTS); - } - */ - SL::Uniform u = E->get(); - u.order += ubase; - uniforms->insert(E->key(), u); - } - } - - for (int i = 0; i < p_program->functions.size(); i++) { - - SL::FunctionNode *fnode = p_program->functions[i].function; - - StringName funcname = fnode->name; - String newfuncname = replace_string(funcname); - - String header; - header = _typestr(fnode->return_type) + " " + newfuncname + "("; - for (int i = 0; i < fnode->arguments.size(); i++) { - - if (i > 0) - header += ", "; - header += _typestr(fnode->arguments[i].type) + " " + replace_string(fnode->arguments[i].name); - } - - header += ") {" ENDL; - String fcode = header; - fcode += dump_node_code(fnode->body, 1); - fcode += "}" ENDL; - global_code += fcode; - } - - /* for(Map<StringName,SL::DataType>::Element *E=p_program->preexisting_variables.front();E;E=E->next()) { - - StringName varname=E->key(); - String newvarname=replace_string(varname); - global_code+="uniform "+_typestr(E->get())+" "+newvarname+";" ENDL; - }*/ - - code = dump_node_code(p_program, 0); - -#ifdef DEBUG_SHADER_ENABLED - - print_line("GLOBAL CODE:\n\n"); - print_line(global_code); - global_code = global_code.replace("\n", ""); - print_line("CODE:\n\n"); - print_line(code); - code = code.replace("\n", ""); -#endif - - return OK; -} - -Error ShaderCompilerGLES2::create_glsl_120_code(void *p_str, SL::ProgramNode *p_program) { - - ShaderCompilerGLES2 *compiler = (ShaderCompilerGLES2 *)p_str; - return compiler->compile_node(p_program); -} - -String ShaderCompilerGLES2::replace_string(const StringName &p_string) { - - Map<StringName, StringName>::Element *E = NULL; - E = replace_table.find(p_string); - if (E) - return E->get(); - - E = mode_replace_table[type].find(p_string); - if (E) - return E->get(); - - return "_" + p_string.operator String(); -} - -Error ShaderCompilerGLES2::compile(const String &p_code, ShaderLanguage::ShaderType p_type, String &r_code_line, String &r_globals_line, Flags &r_flags, Map<StringName, ShaderLanguage::Uniform> *r_uniforms) { - - uses_texscreen = false; - uses_texpos = false; - uses_alpha = false; - uses_discard = false; - uses_screen_uv = false; - uses_light = false; - uses_time = false; - uses_normalmap = false; - uses_normal = false; - uses_texpixel_size = false; - uses_worldvec = false; - vertex_code_writes_vertex = false; - vertex_code_writes_position = false; - uses_shadow_color = false; - uniforms = r_uniforms; - flags = &r_flags; - r_flags.use_color_interp = false; - r_flags.use_uv_interp = false; - r_flags.use_uv2_interp = false; - r_flags.use_tangent_interp = false; - r_flags.use_var1_interp = false; - r_flags.use_var2_interp = false; - r_flags.uses_normalmap = false; - r_flags.uses_normal = false; - sinh_used = false; - tanh_used = false; - cosh_used = false; - - String error; - int errline, errcol; - - type = p_type; - Error err = SL::compile(p_code, p_type, create_glsl_120_code, this, &error, &errline, &errcol); - - if (err) { - print_line("***Error precompiling shader: " + error); - print_line("error " + itos(errline) + ":" + itos(errcol)); - return err; - } - - r_flags.uses_alpha = uses_alpha; - r_flags.uses_texscreen = uses_texscreen; - r_flags.uses_texpos = uses_texpos; - r_flags.vertex_code_writes_vertex = vertex_code_writes_vertex; - r_flags.vertex_code_writes_position = vertex_code_writes_position; - r_flags.uses_discard = uses_discard; - r_flags.uses_screen_uv = uses_screen_uv; - r_flags.uses_light = uses_light; - r_flags.uses_time = uses_time; - r_flags.uses_normalmap = uses_normalmap; - r_flags.uses_normal = uses_normal; - r_flags.uses_texpixel_size = uses_texpixel_size; - r_flags.uses_worldvec = uses_worldvec; - r_flags.uses_shadow_color = uses_shadow_color; - r_code_line = code; - r_globals_line = global_code; - return OK; -} - -ShaderCompilerGLES2::ShaderCompilerGLES2() { - -#ifdef GLEW_ENABLED - //use custom functions because they are not supported in GLSL120 - custom_h = true; -#else - custom_h = false; -#endif - - replace_table["bool"] = "bool"; - replace_table["float"] = "float"; - replace_table["vec2"] = "vec2"; - replace_table["vec3"] = "vec3"; - replace_table["vec4"] = "vec4"; - replace_table["mat2"] = "mat2"; - replace_table["mat3"] = "mat3"; - replace_table["mat4"] = "mat4"; - replace_table["texture"] = "sampler2D"; - replace_table["cubemap"] = "samplerCube"; - - replace_table["sin"] = "sin"; - replace_table["cos"] = "cos"; - replace_table["tan"] = "tan"; - replace_table["asin"] = "asin"; - replace_table["acos"] = "acos"; - replace_table["atan"] = "atan"; - replace_table["atan2"] = "atan"; - - if (custom_h) { - replace_table["sinh"] = "sinh_custom"; - replace_table["cosh"] = "cosh_custom"; - replace_table["tanh"] = "tanh_custom"; - } else { - replace_table["sinh"] = "sinh"; - replace_table["cosh"] = "cosh"; - replace_table["tanh"] = "tanh"; - } - - replace_table["pow"] = "pow"; - replace_table["exp"] = "exp"; - replace_table["log"] = "log"; - replace_table["sqrt"] = "sqrt"; - replace_table["abs"] = "abs"; - replace_table["sign"] = "sign"; - replace_table["floor"] = "floor"; - replace_table["trunc"] = "trunc"; -#ifdef GLEW_ENABLED - replace_table["round"] = "roundfix"; -#else - replace_table["round"] = "round"; -#endif - replace_table["ceil"] = "ceil"; - replace_table["fract"] = "fract"; - replace_table["mod"] = "mod"; - replace_table["min"] = "min"; - replace_table["max"] = "max"; - replace_table["clamp"] = "clamp"; - replace_table["mix"] = "mix"; - replace_table["step"] = "step"; - replace_table["smoothstep"] = "smoothstep"; - replace_table["length"] = "length"; - replace_table["distance"] = "distance"; - replace_table["dot"] = "dot"; - replace_table["cross"] = "cross"; - replace_table["normalize"] = "normalize"; - replace_table["reflect"] = "reflect"; - replace_table["refract"] = "refract"; - replace_table["tex"] = "tex"; - replace_table["texa"] = "texa"; - replace_table["tex2"] = "tex2"; - replace_table["texcube"] = "textureCube"; - replace_table["texscreen"] = "texscreen"; - replace_table["texpos"] = "texpos"; - - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_VERTEX"] = "vertex_in.xyz"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_NORMAL"] = "normal_in"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_TANGENT"] = "tangent_in"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_BINORMALF"] = "binormalf"; - - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["POSITION"] = "gl_Position"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["VERTEX"] = "vertex_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["NORMAL"] = "normal_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["TANGENT"] = "tangent_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["BINORMAL"] = "binormal_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["UV"] = "uv_interp.xy"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["UV2"] = "uv_interp.zw"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["COLOR"] = "color_interp"; - //@TODO convert to glsl stuff - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SPEC_EXP"] = "vertex_specular_exp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["WORLD_MATRIX"] = "world_transform"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["INV_CAMERA_MATRIX"] = "camera_inverse_transform"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["PROJECTION_MATRIX"] = "projection_transform"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["MODELVIEW_MATRIX"] = "modelview"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["POINT_SIZE"] = "gl_PointSize"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["VAR1"] = "var1_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["VAR2"] = "var2_interp"; - - //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SCREEN_POS"]="SCREEN_POS"; - //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SCREEN_SIZE"]="SCREEN_SIZE"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["INSTANCE_ID"] = "instance_id"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["TIME"] = "time"; - - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VERTEX"] = "vertex"; - //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["POSITION"]="IN_POSITION"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["NORMAL"] = "normal"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["TANGENT"] = "tangent"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["POSITION"] = "gl_Position"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["BINORMAL"] = "binormal"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["NORMALMAP"] = "normalmap"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["NORMALMAP_DEPTH"] = "normaldepth"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR1"] = "var1_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR2"] = "var2_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["UV"] = "uv"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["UV2"] = "uv2"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SCREEN_UV"] = "screen_uv"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR1"] = "var1_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR2"] = "var2_interp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["COLOR"] = "color"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["DIFFUSE"] = "diffuse.rgb"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["DIFFUSE_ALPHA"] = "diffuse"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SPECULAR"] = "specular"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["EMISSION"] = "emission"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SHADE_PARAM"] = "shade_param"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SPEC_EXP"] = "specular_exp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["GLOW"] = "glow"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["DISCARD"] = "discard_"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["POINT_COORD"] = "gl_PointCoord"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["INV_CAMERA_MATRIX"] = "camera_inverse_transform"; - - //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SCREEN_POS"]="SCREEN_POS"; - //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["TIME"] = "time"; - - ////////////// - - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["NORMAL"] = "normal"; - //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["POSITION"]="IN_POSITION"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT_DIR"] = "light_dir"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT_DIFFUSE"] = "light_diffuse"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT_SPECULAR"] = "light_specular"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["EYE_VEC"] = "eye_vec"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["DIFFUSE"] = "mdiffuse"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SPECULAR"] = "specular"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SPECULAR_EXP"] = "specular_exp"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SHADE_PARAM"] = "shade_param"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT"] = "light"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["POINT_COORD"] = "gl_PointCoord"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["TIME"] = "time"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SHADOW"] = "shadow_color"; - - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["SRC_VERTEX"] = "src_vtx"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["VERTEX"] = "outvec.xy"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["WORLD_VERTEX"] = "outvec.xy"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["UV"] = "uv_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["COLOR"] = "color_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["VAR1"] = "var1_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["VAR2"] = "var2_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["POINT_SIZE"] = "gl_PointSize"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["WORLD_MATRIX"] = "modelview_matrix"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["PROJECTION_MATRIX"] = "projection_matrix"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["EXTRA_MATRIX"] = "extra_matrix"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["TIME"] = "time"; - - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POSITION"] = "gl_Position"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMAL"] = "normal"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMALMAP"] = "normal_map"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMALMAP_DEPTH"] = "normal_depth"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["UV"] = "uv_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["SRC_COLOR"] = "color_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["COLOR"] = "color"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TEXTURE"] = "texture"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TEXTURE_PIXEL_SIZE"] = "texpixel_size"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["VAR1"] = "var1_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["VAR2"] = "var2_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["SCREEN_UV"] = "screen_uv"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POINT_COORD"] = "gl_PointCoord"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TIME"] = "time"; - - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["POSITION"] = "gl_Position"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["NORMAL"] = "normal"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["UV"] = "uv_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["COLOR"] = "color"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["TEXTURE"] = "texture"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["TEXTURE_PIXEL_SIZE"] = "texpixel_size"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["VAR1"] = "var1_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["VAR2"] = "var2_interp"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_VEC"] = "light_vec"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_HEIGHT"] = "light_height"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_COLOR"] = "light"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_SHADOW"] = "light_shadow_color"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_UV"] = "light_uv"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT"] = "light_out"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["SHADOW"] = "shadow_color"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["SCREEN_UV"] = "screen_uv"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["POINT_COORD"] = "gl_PointCoord"; - mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["TIME"] = "time"; - - //mode_replace_table[2]["SCREEN_POS"]="SCREEN_POS"; - //mode_replace_table[2]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE"; - - out_vertex_name = "VERTEX"; - - vname_discard = "DISCARD"; - vname_screen_uv = "SCREEN_UV"; - vname_diffuse_alpha = "DIFFUSE_ALPHA"; - vname_color_interp = "COLOR"; - vname_uv_interp = "UV"; - vname_uv2_interp = "UV2"; - vname_tangent_interp = "TANGENT"; - vname_binormal_interp = "BINORMAL"; - vname_var1_interp = "VAR1"; - vname_var2_interp = "VAR2"; - vname_vertex = "VERTEX"; - vname_position = "POSITION"; - vname_light = "LIGHT"; - vname_time = "TIME"; - vname_normalmap = "NORMALMAP"; - vname_normalmap_depth = "NORMALMAP_DEPTH"; - vname_normal = "NORMAL"; - vname_texpixel_size = "TEXTURE_PIXEL_SIZE"; - vname_world_vec = "WORLD_VERTEX"; - vname_shadow = "SHADOW"; -} diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h deleted file mode 100644 index 02f9e58978..0000000000 --- a/drivers/gles2/shader_compiler_gles2.h +++ /dev/null @@ -1,134 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 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_COMPILER_GLES2_H -#define SHADER_COMPILER_GLES2_H - -#include "servers/visual/shader_language.h" -class ShaderCompilerGLES2 { - - class Uniform; - -public: - struct Flags; - -private: - ShaderLanguage::ProgramNode *program_node; - String dump_node_code(ShaderLanguage::Node *p_node, int p_level, bool p_assign_left = false); - Error compile_node(ShaderLanguage::ProgramNode *p_program); - static Error create_glsl_120_code(void *p_str, ShaderLanguage::ProgramNode *p_program); - - bool uses_light; - bool uses_texscreen; - bool uses_texpos; - bool uses_alpha; - bool uses_discard; - bool uses_time; - bool uses_screen_uv; - bool uses_normalmap; - bool uses_normal; - bool uses_texpixel_size; - bool uses_worldvec; - bool vertex_code_writes_vertex; - bool vertex_code_writes_position; - bool uses_shadow_color; - - bool sinh_used; - bool tanh_used; - bool cosh_used; - - bool custom_h; - - Flags *flags; - - StringName vname_discard; - StringName vname_screen_uv; - StringName vname_diffuse_alpha; - StringName vname_color_interp; - StringName vname_uv_interp; - StringName vname_uv2_interp; - StringName vname_tangent_interp; - StringName vname_binormal_interp; - StringName vname_var1_interp; - StringName vname_var2_interp; - StringName vname_vertex; - StringName vname_position; - StringName vname_light; - StringName vname_time; - StringName vname_normalmap; - StringName vname_normalmap_depth; - StringName vname_normal; - StringName vname_texpixel_size; - StringName vname_world_vec; - StringName vname_shadow; - - Map<StringName, ShaderLanguage::Uniform> *uniforms; - - StringName out_vertex_name; - - String global_code; - String code; - ShaderLanguage::ShaderType type; - - String replace_string(const StringName &p_string); - - Map<StringName, StringName> mode_replace_table[9]; - Map<StringName, StringName> replace_table; - -public: - struct Flags { - - bool uses_alpha; - bool uses_texscreen; - bool uses_texpos; - bool uses_normalmap; - bool vertex_code_writes_vertex; - bool vertex_code_writes_position; - bool uses_discard; - bool uses_screen_uv; - bool use_color_interp; - bool use_uv_interp; - bool use_uv2_interp; - bool use_tangent_interp; - bool use_var1_interp; - bool use_var2_interp; - bool uses_light; - bool uses_time; - bool uses_normal; - bool uses_texpixel_size; - bool uses_worldvec; - bool uses_shadow_color; - }; - - Error compile(const String &p_code, ShaderLanguage::ShaderType p_type, String &r_code_line, String &r_globals_line, Flags &r_flags, Map<StringName, ShaderLanguage::Uniform> *r_uniforms = NULL); - - ShaderCompilerGLES2(); -}; - -#endif // SHADER_COMPILERL_GL_H diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp deleted file mode 100644 index 961bf27a72..0000000000 --- a/drivers/gles2/shader_gles2.cpp +++ /dev/null @@ -1,736 +0,0 @@ -/*************************************************************************/ -/* shader_gles2.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "shader_gles2.h" - -#ifdef GLES2_ENABLED -#include "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 - -ShaderGLES2 *ShaderGLES2::active = NULL; - -//#define DEBUG_SHADER - -#ifdef DEBUG_SHADER - -#define DEBUG_PRINT(m_text) print_line(m_text); - -#else - -#define DEBUG_PRINT(m_text) - -#endif - -void ShaderGLES2::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 ShaderGLES2::get_uniform_location(int p_idx) const { - - ERR_FAIL_COND_V(!version, -1); - - return version->uniform_location[p_idx]; -}; - -bool ShaderGLES2::bind() { - - if (active != this || !version || new_conditional_version.key != conditional_version.key) { - conditional_version = new_conditional_version; - version = get_current_version(); - } else { - - return false; - } - - ERR_FAIL_COND_V(!version, false); - - glUseProgram(version->id); - - DEBUG_TEST_ERROR("Use Program"); - - active = this; - uniforms_dirty = true; - /* - * why on earth is this code here? - for (int i=0;i<texunit_pair_count;i++) { - - glUniform1i(texunit_pairs[i].location, texunit_pairs[i].index); - DEBUG_TEST_ERROR("Uniform 1 i"); - } - -*/ - return true; -} - -void ShaderGLES2::unbind() { - - version = NULL; - glUseProgram(0); - uniforms_dirty = true; - active = NULL; -} - -static String _fix_error_code_line(const String &p_error, int p_code_start, int p_offset) { - - int last_find_pos = -1; - // NVIDIA - String error = p_error; - while ((last_find_pos = p_error.find("(", last_find_pos + 1)) != -1) { - - int end_pos = last_find_pos + 1; - - while (true) { - - if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') { - - end_pos++; - continue; - } else if (p_error[end_pos] == ')') { - break; - } else { - - end_pos = -1; - break; - } - } - - if (end_pos == -1) - continue; - - String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1); - String begin = error.substr(0, last_find_pos + 1); - String end = error.substr(end_pos, error.length()); - int num = numstr.to_int() + p_code_start - p_offset; - error = begin + itos(num) + end; - } - - // ATI - last_find_pos = -1; - while ((last_find_pos = p_error.find("ERROR: ", last_find_pos + 1)) != -1) { - - last_find_pos += 6; - int end_pos = last_find_pos + 1; - - while (true) { - - if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') { - - end_pos++; - continue; - } else if (p_error[end_pos] == ':') { - break; - } else { - - end_pos = -1; - break; - } - } - continue; - if (end_pos == -1) - continue; - - String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1); - print_line("numstr: " + numstr); - String begin = error.substr(0, last_find_pos + 1); - String end = error.substr(end_pos, error.length()); - int num = numstr.to_int() + p_code_start - p_offset; - error = begin + itos(num) + end; - } - return error; -} - -ShaderGLES2::Version *ShaderGLES2::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 GLEW_ENABLED - strings.push_back("#version 120\n"); //ATI requieres this before anything -#endif - int define_line_ofs = 1; - - for (int j = 0; j < conditional_count; j++) { - - bool enable = ((1 << j) & conditional_version.version); - strings.push_back(enable ? conditional_defines[j] : ""); - if (enable) - define_line_ofs++; - - if (enable) { - DEBUG_PRINT(conditional_defines[j]); - } - } - - //keep them around during the function - CharString code_string; - CharString code_string2; - CharString code_globals; - - //print_line("code version? "+itos(conditional_version.code_version)); - - 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; - define_line_ofs += 2; - } - - /* 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]); - DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i])); - } - } - - int strings_base_size = strings.size(); -#if 0 - if (cc) { - - String _code_string = "#define VERTEX_SHADER_CODE "+cc->vertex+"\n"; - String _code_globals = "#define VERTEX_SHADER_GLOBALS "+cc->vertex_globals+"\n"; - - code_string=_code_string.ascii(); - code_globals=_code_globals.ascii(); - DEBUG_PRINT( code_globals.get_data() ); - DEBUG_PRINT( code_string.get_data() ); - strings.push_back(code_globals); - strings.push_back(code_string); - } -#endif - - strings.push_back(vertex_code0.get_data()); - if (cc) { - code_globals = cc->vertex_globals.ascii(); - strings.push_back(code_globals.get_data()); - } - strings.push_back(vertex_code1.get_data()); - - if (cc) { - code_string = cc->vertex.ascii(); - strings.push_back(code_string.get_data()); - } - - strings.push_back(vertex_code2.get_data()); -#ifdef DEBUG_SHADER - - DEBUG_PRINT("\nVertex Code:\n\n" + String(code_string.get_data())); - 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("NO LOG, WTF"); - } else { - - if (iloglen == 0) { - - iloglen = 4096; //buggy driver (Adreno 220+....) - } - - char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); - ilogmem[iloglen] = 0; - glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem); - - String err_string = get_shader_name() + ": Vertex Program Compilation Failed:\n"; - - err_string += ilogmem; - err_string = _fix_error_code_line(err_string, vertex_code_start, define_line_ofs); - ERR_PRINT(err_string.ascii().get_data()); - Memory::free_static(ilogmem); - glDeleteShader(v.vert_id); - glDeleteProgram(v.id); - v.id = 0; - } - - ERR_FAIL_V(NULL); - } - - /* FRAGMENT SHADER */ - - strings.resize(strings_base_size); -#if 0 - if (cc) { - - String _code_string = "#define FRAGMENT_SHADER_CODE "+cc->fragment+"\n"; - String _code_globals = "#define FRAGMENT_SHADER_GLOBALS "+cc->fragment_globals+"\n"; - - code_string=_code_string.ascii(); - code_globals=_code_globals.ascii(); - DEBUG_PRINT( code_globals.get_data() ); - DEBUG_PRINT( code_string.get_data() ); - strings.push_back(code_globals); - strings.push_back(code_string); - } -#endif - - strings.push_back(fragment_code0.get_data()); - if (cc) { - code_globals = cc->fragment_globals.ascii(); - strings.push_back(code_globals.get_data()); - } - strings.push_back(fragment_code1.get_data()); - - if (cc) { - code_string = cc->fragment.ascii(); - strings.push_back(code_string.get_data()); - } - - strings.push_back(fragment_code2.get_data()); - - if (cc) { - code_string2 = cc->light.ascii(); - strings.push_back(code_string2.get_data()); - } - - strings.push_back(fragment_code3.get_data()); - -#ifdef DEBUG_SHADER - DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string.get_data())); - for (int i = 0; i < strings.size(); i++) { - - //print_line("frag strings "+itos(i)+":"+String(strings[i])); - } -#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("NO LOG, WTF"); - } else { - - if (iloglen == 0) { - - iloglen = 4096; //buggy driver (Adreno 220+....) - } - - char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); - ilogmem[iloglen] = 0; - glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem); - - String err_string = get_shader_name() + ": Fragment Program Compilation Failed:\n"; - - err_string += ilogmem; - err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs); - 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); - } - - 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); - } - - 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; - err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs); - 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) - glUniform1i(loc, texunit_pairs[i].index); - } - - if (cc) { - - v.custom_uniform_locations.resize(cc->custom_uniforms.size()); - for (int i = 0; i < cc->custom_uniforms.size(); i++) { - - v.custom_uniform_locations[i] = glGetUniformLocation(v.id, String(cc->custom_uniforms[i]).ascii().get_data()); - } - } - - glUseProgram(0); - - v.ok = true; - - return &v; -} - -GLint ShaderGLES2::get_uniform_location(const String &p_name) const { - - ERR_FAIL_COND_V(!version, -1); - return glGetUniformLocation(version->id, p_name.ascii().get_data()); -} - -void ShaderGLES2::setup(const char **p_conditional_defines, int p_conditional_count, const char **p_uniform_names, int p_uniform_count, const AttributePair *p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start) { - - ERR_FAIL_COND(version); - conditional_version.key = 0; - new_conditional_version.key = 0; - uniform_count = p_uniform_count; - conditional_count = p_conditional_count; - conditional_defines = p_conditional_defines; - uniform_names = p_uniform_names; - vertex_code = p_vertex_code; - fragment_code = p_fragment_code; - texunit_pairs = p_texunit_pairs; - texunit_pair_count = p_texunit_pair_count; - vertex_code_start = p_vertex_code_start; - fragment_code_start = p_fragment_code_start; - attribute_pairs = p_attribute_pairs; - attribute_pair_count = p_attribute_count; - - //split vertex and shader code (thank you, retarded shader compiler programmers from you know what company). - { - String globals_tag = "\nVERTEX_SHADER_GLOBALS"; - String code_tag = "\nVERTEX_SHADER_CODE"; - String code = vertex_code; - int cpos = code.find(globals_tag); - if (cpos == -1) { - vertex_code0 = code.ascii(); - } else { - vertex_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code.find(code_tag); - - if (cpos == -1) { - vertex_code1 = code.ascii(); - } else { - - vertex_code1 = code.substr(0, cpos).ascii(); - vertex_code2 = code.substr(cpos + code_tag.length(), code.length()).ascii(); - } - } - } - - { - String globals_tag = "\nFRAGMENT_SHADER_GLOBALS"; - String code_tag = "\nFRAGMENT_SHADER_CODE"; - String light_code_tag = "\nLIGHT_SHADER_CODE"; - String code = fragment_code; - int cpos = code.find(globals_tag); - if (cpos == -1) { - fragment_code0 = code.ascii(); - } else { - fragment_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code.find(code_tag); - - if (cpos == -1) { - fragment_code1 = code.ascii(); - } else { - - fragment_code1 = code.substr(0, cpos).ascii(); - String code2 = code.substr(cpos + code_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(); - fragment_code3 = code2.substr(cpos + light_code_tag.length(), code2.length()).ascii(); - } - } - } - } -} - -void ShaderGLES2::finish() { - - const VersionKey *V = NULL; - while ((V = version_map.next(V))) { - - Version &v = version_map[*V]; - glDeleteShader(v.vert_id); - glDeleteShader(v.frag_id); - glDeleteProgram(v.id); - memdelete_arr(v.uniform_location); - } -} - -void ShaderGLES2::clear_caches() { - - const VersionKey *V = NULL; - while ((V = version_map.next(V))) { - - Version &v = version_map[*V]; - glDeleteShader(v.vert_id); - glDeleteShader(v.frag_id); - glDeleteProgram(v.id); - memdelete_arr(v.uniform_location); - } - - version_map.clear(); - - custom_code_map.clear(); - version = NULL; - last_custom_code = 1; - uniforms_dirty = true; -} - -uint32_t ShaderGLES2::create_custom_shader() { - - custom_code_map[last_custom_code] = CustomCode(); - custom_code_map[last_custom_code].version = 1; - return last_custom_code++; -} - -void ShaderGLES2::set_custom_shader_code(uint32_t p_code_id, const String &p_vertex, const String &p_vertex_globals, const String &p_fragment, const String &p_light, const String &p_fragment_globals, const Vector<StringName> &p_uniforms, const Vector<const char *> &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->custom_uniforms = p_uniforms; - cc->custom_defines = p_custom_defines; - cc->version++; -} - -void ShaderGLES2::set_custom_shader(uint32_t p_code_id) { - - new_conditional_version.code_version = p_code_id; -} - -void ShaderGLES2::free_custom_shader(uint32_t p_code_id) { - - /* if (! custom_code_map.has( p_code_id )) { - print_line("no code id "+itos(p_code_id)); - } else { - print_line("freed code id "+itos(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; //bye - - custom_code_map.erase(p_code_id); -} - -ShaderGLES2::ShaderGLES2() { - version = NULL; - last_custom_code = 1; - uniforms_dirty = true; -} - -ShaderGLES2::~ShaderGLES2() { - - finish(); -} - -#endif diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h deleted file mode 100644 index 69a66b8ab7..0000000000 --- a/drivers/gles2/shader_gles2.h +++ /dev/null @@ -1,359 +0,0 @@ -/*************************************************************************/ -/* shader_gles2.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 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_GLES2_H -#define SHADER_GLES2_H - -#ifdef GLES2_ENABLED - -#include "platform_config.h" -#ifndef GLES2_INCLUDE_H -#include <GLES2/gl2.h> -#else -#include GLES2_INCLUDE_H -#endif - -#include "camera_matrix.h" -#include "hash_map.h" -#include "map.h" -#include "variant.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - -class ShaderGLES2 { -protected: - struct Enum { - - uint64_t mask; - uint64_t shift; - const char *defines[16]; - }; - - struct EnumValue { - - uint64_t set_mask; - uint64_t clear_mask; - }; - - struct AttributePair { - - const char *name; - int index; - }; - - struct UniformPair { - const char *name; - Variant::Type type_hint; - }; - - struct TexUnitPair { - - const char *name; - int index; - }; - - bool uniforms_dirty; - -private: - //@TODO Optimize to a fixed set of shader pools and use a LRU - int uniform_count; - int texunit_pair_count; - int conditional_count; - int vertex_code_start; - int fragment_code_start; - int attribute_pair_count; - - struct CustomCode { - - String vertex; - String vertex_globals; - String fragment; - String fragment_globals; - String light; - uint32_t version; - Vector<StringName> custom_uniforms; - Vector<const char *> custom_defines; - }; - - struct Version { - - GLuint id; - GLuint vert_id; - GLuint frag_id; - GLint *uniform_location; - Vector<GLint> custom_uniform_locations; - uint32_t code_version; - bool ok; - Version() { - code_version = 0; - ok = false; - uniform_location = NULL; - } - }; - - Version *version; - - union VersionKey { - - struct { - uint32_t version; - uint32_t code_version; - }; - uint64_t key; - bool operator==(const VersionKey &p_key) const { return key == p_key.key; } - bool operator<(const VersionKey &p_key) const { return key < p_key.key; } - }; - - struct VersionKeyHash { - - static _FORCE_INLINE_ uint32_t hash(const VersionKey &p_key) { return HashMapHasherDefault::hash(p_key.key); }; - }; - - //this should use a way more cachefriendly version.. - HashMap<VersionKey, Version, VersionKeyHash> version_map; - - HashMap<uint32_t, CustomCode> custom_code_map; - uint32_t last_custom_code; - - VersionKey conditional_version; - VersionKey new_conditional_version; - - virtual String get_shader_name() const = 0; - - const char **conditional_defines; - const char **uniform_names; - const AttributePair *attribute_pairs; - const TexUnitPair *texunit_pairs; - const char *vertex_code; - const char *fragment_code; - CharString fragment_code0; - CharString fragment_code1; - CharString fragment_code2; - CharString fragment_code3; - - CharString vertex_code0; - CharString vertex_code1; - CharString vertex_code2; - - Version *get_current_version(); - - static ShaderGLES2 *active; - - _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::MATRIX32: { - - 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::MATRIX3: - 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 char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start); - - ShaderGLES2(); - -public: - enum { - CUSTOM_SHADER_DISABLED = 0 - }; - - GLint get_uniform_location(const String &p_name) const; - GLint get_uniform_location(int p_uniform) const; - - static _FORCE_INLINE_ ShaderGLES2 *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_id, const String &p_vertex, const String &p_vertex_globals, const String &p_fragment, const String &p_p_light, const String &p_fragment_globals, const Vector<StringName> &p_uniforms, const Vector<const char *> &p_custom_defines); - void set_custom_shader(uint32_t p_id); - void free_custom_shader(uint32_t p_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; } - - void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) { - - uniform_cameras[p_idx] = p_mat; - uniforms_dirty = true; - }; - - _FORCE_INLINE_ void set_custom_uniform(int p_idx, const Variant &p_value) { - - ERR_FAIL_COND(!version); - ERR_FAIL_INDEX(p_idx, version->custom_uniform_locations.size()); - _set_uniform_variant(version->custom_uniform_locations[p_idx], p_value); - } - - _FORCE_INLINE_ GLint get_custom_uniform_location(int p_idx) { - - ERR_FAIL_COND_V(!version, -1); - ERR_FAIL_INDEX_V(p_idx, version->custom_uniform_locations.size(), -1); - return version->custom_uniform_locations[p_idx]; - } - - virtual void init() = 0; - void finish(); - - virtual ~ShaderGLES2(); -}; - -// called a lot, made inline - -int ShaderGLES2::_get_uniform(int p_which) const { - - ERR_FAIL_INDEX_V(p_which, uniform_count, -1); - ERR_FAIL_COND_V(!version, -1); - return version->uniform_location[p_which]; -} - -void ShaderGLES2::_set_conditional(int p_which, bool p_value) { - - ERR_FAIL_INDEX(p_which, conditional_count); - if (p_value) - new_conditional_version.version |= (1 << p_which); - else - new_conditional_version.version &= ~(1 << p_which); -} - -#endif -#endif diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub deleted file mode 100644 index bf4ec9485d..0000000000 --- a/drivers/gles2/shaders/SCsub +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -if env['BUILDERS'].has_key('GLSL120GLES'): - env.GLSL120GLES('material.glsl') - env.GLSL120GLES('canvas.glsl') - env.GLSL120GLES('canvas_shadow.glsl') - env.GLSL120GLES('blur.glsl') - env.GLSL120GLES('copy.glsl') - -Export('env') diff --git a/drivers/gles2/shaders/blur.glsl b/drivers/gles2/shaders/blur.glsl deleted file mode 100644 index b68a55aee7..0000000000 --- a/drivers/gles2/shaders/blur.glsl +++ /dev/null @@ -1,51 +0,0 @@ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - -attribute highp vec4 vertex_attrib; // attrib:0 -attribute vec2 uv_in; // attrib:4 - -varying vec2 uv_out; - - - -void main() { - - color_interp = color_attrib; - uv_interp = uv_attrib; - vec4 outvec = vec4(vertex, 1.0); - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; - gl_Position = projection_matrix * outvec; -} - -[fragment] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - - // texunit:0 -uniform sampler2D texture; -varying vec2 uv_out; - - -void main() { - - vec4 color = color_interp; - - color *= texture2D( texture, uv_interp ); - - gl_FragColor = color; -} - diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl deleted file mode 100644 index 4b8c553b60..0000000000 --- a/drivers/gles2/shaders/canvas.glsl +++ /dev/null @@ -1,391 +0,0 @@ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - -uniform highp mat4 projection_matrix; -uniform highp mat4 modelview_matrix; -uniform highp mat4 extra_matrix; -attribute highp vec3 vertex; // attrib:0 -attribute vec4 color_attrib; // attrib:3 -attribute highp vec2 uv_attrib; // attrib:4 - -varying vec2 uv_interp; -varying vec4 color_interp; - -#if defined(USE_TIME) -uniform float time; -#endif - - -#ifdef USE_LIGHTING - -uniform highp mat4 light_matrix; -uniform highp mat4 light_local_matrix; -uniform vec2 light_pos; -varying vec4 light_uv_interp; - -varying vec4 local_rot; -uniform vec2 normal_flip; - -#ifdef USE_SHADOWS -varying highp vec2 pos; -#endif - -#endif - -#if defined(ENABLE_VAR1_INTERP) -varying vec4 var1_interp; -#endif - -#if defined(ENABLE_VAR2_INTERP) -varying vec4 var2_interp; -#endif - -//uniform bool snap_pixels; - -VERTEX_SHADER_GLOBALS - -void main() { - - color_interp = color_attrib; - uv_interp = uv_attrib; - highp vec4 outvec = vec4(vertex, 1.0); -{ - vec2 src_vtx=outvec.xy; -VERTEX_SHADER_CODE - -} -#if !defined(USE_WORLD_VEC) - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; -#endif - - - -#ifdef USE_PIXEL_SNAP - - outvec.xy=floor(outvec.xy+0.5); -#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; -#ifdef USE_SHADOWS - pos=outvec.xy; -#endif - - local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy )*normal_flip.x; - local_rot.zw=normalize( (modelview_matrix * ( extra_matrix * vec4(0.0,1.0,0.0,0.0) )).xy )*normal_flip.y; - -#endif - -} - -[fragment] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - - -uniform sampler2D texture; // texunit:0 -uniform sampler2D normal_texture; // texunit:0 - -varying vec2 uv_interp; -varying vec4 color_interp; - -#ifdef MOMO - -#endif - -#if defined(ENABLE_SCREEN_UV) - -uniform vec2 screen_uv_mult; - -#endif - -#if defined(ENABLE_TEXSCREEN) - -uniform vec2 texscreen_screen_mult; -uniform vec4 texscreen_screen_clamp; -uniform sampler2D texscreen_tex; - -#endif - - -#if defined(ENABLE_VAR1_INTERP) -varying vec4 var1_interp; -#endif - -#if defined(ENABLE_VAR2_INTERP) -varying vec4 var2_interp; -#endif - -#if defined(USE_TIME) -uniform float time; -#endif - -#ifdef USE_MODULATE - -uniform vec4 modulate; - -#endif - -#ifdef USE_LIGHTING - -uniform sampler2D light_texture; -uniform vec4 light_color; -uniform vec4 light_shadow_color; -uniform float light_height; -varying vec4 light_uv_interp; -uniform float light_outside_alpha; - -varying vec4 local_rot; - -#ifdef USE_SHADOWS - -uniform highp sampler2D shadow_texture; -uniform float shadow_attenuation; - -uniform highp mat4 shadow_matrix; -varying highp vec2 pos; -uniform float shadowpixel_size; - -#ifdef SHADOW_ESM -uniform float shadow_esm_multiplier; -#endif - -#endif - -#endif - -#if defined(USE_TEXPIXEL_SIZE) -uniform vec2 texpixel_size; -#endif - - -FRAGMENT_SHADER_GLOBALS - - -void main() { - - vec4 color = color_interp; - -#ifdef USE_DISTANCE_FIELD - const float smoothing = 1.0/32.0; - float distance = textureLod(texture, uv_interp,0.0).a; - color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance) * color.a; -#else - color *= texture2D( texture, uv_interp ); - -#endif - - vec3 normal; - normal.xy = textureLod( normal_texture, uv_interp, 0.0 ).xy * 2.0 - 1.0; - normal.z = sqrt(1.0-dot(normal.xy,normal.xy)); - -#if defined(ENABLE_SCREEN_UV) - vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; -#endif - - -{ -#if defined(USE_NORMALMAP) - vec3 normal_map=vec3(0.0,0.0,1.0); - float normal_depth=1.0; -#endif - -FRAGMENT_SHADER_CODE - -#if defined(USE_NORMALMAP) - 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) ); - color = vec4(vec3(enc32),1.0); -#endif - -#ifdef USE_MODULATE - - color*=modulate; -#endif - - -#ifdef USE_LIGHTING - - vec2 light_vec = light_uv_interp.zw;; //for shadow and normal mapping - - normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy; - - float att=1.0; - - vec2 light_uv = light_uv_interp.xy; - vec4 light = texture2D(light_texture,light_uv) * light_color; -#if defined(USE_OUTPUT_SHADOW_COLOR) - vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); -#endif - - 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 { - -#if defined(USE_LIGHT_SHADER_CODE) -//light is written by the light shader - { - vec4 light_out=light*color; -LIGHT_SHADER_CODE - color=light_out; - } - -#else - - vec3 light_normal = normalize(vec3(light_vec,-light_height)); - light*=max(dot(-light_normal,normal),0.0); - - color*=light; -/* -#ifdef USE_NORMAL - color.xy=local_rot.xy;//normal.xy; - color.zw=vec2(0.0,1.0); -#endif -*/ - -//light shader code -#endif - - -#ifdef USE_SHADOWS - - float angle_to_light = -atan(light_vec.x,light_vec.y); - float PI = 3.14159265358979323846264; - /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays - float ang*/ - - float su,sz; - - float abs_angle = abs(angle_to_light); - vec2 point; - float sh; - if (abs_angle<45.0*PI/180.0) { - point = light_vec; - sh=0.0+(1.0/8.0); - } else if (abs_angle>135.0*PI/180.0) { - point = -light_vec; - sh = 0.5+(1.0/8.0); - } else if (angle_to_light>0.0) { - - point = vec2(light_vec.y,-light_vec.x); - sh = 0.25+(1.0/8.0); - } else { - - point = vec2(-light_vec.y,light_vec.x); - sh = 0.75+(1.0/8.0); - - } - - - highp vec4 s = shadow_matrix * vec4(point,0.0,1.0); - s.xyz/=s.w; - su=s.x*0.5+0.5; - sz=s.z*0.5+0.5; - - highp float shadow_attenuation=0.0; - -#ifdef USE_DEPTH_SHADOWS - -#define SHADOW_DEPTH(m_tex,m_uv) (texture2D((m_tex),(m_uv)).r) - -#else - -//#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) -#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) - -#endif - - - -#ifdef SHADOW_PCF5 - - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0; - shadow_attenuation/=5.0; - -#endif - -#ifdef SHADOW_PCF13 - - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*3.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*4.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*5.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*6.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*3.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*4.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*5.0,sh))<sz?0.0:1.0; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*6.0,sh))<sz?0.0:1.0; - shadow_attenuation/=13.0; - -#endif - -#ifdef SHADOW_ESM - - - { - float unnormalized = su/shadowpixel_size; - float fractional = fract(unnormalized); - unnormalized = floor(unnormalized); - float zc = SHADOW_DEPTH(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh)); - float zn = SHADOW_DEPTH(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh)); - float z = mix(zc,zn,fractional); - shadow_attenuation=clamp(exp(shadow_esm_multiplier* ( z - sz )),0.0,1.0); - } - -#endif - -#if !defined(SHADOW_PCF5) && !defined(SHADOW_PCF13) && !defined(SHADOW_ESM) - - shadow_attenuation = SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; - -#endif - -#if defined(USE_OUTPUT_SHADOW_COLOR) - color=mix(shadow_color,color,shadow_attenuation); -#else - //color*=shadow_attenuation; - color=mix(light_shadow_color,color,shadow_attenuation); -#endif -//use shadows -#endif - } - -//use lighting -#endif - //color.rgb*=color.a; - gl_FragColor = color; - - -} - diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl deleted file mode 100644 index 40cf321dce..0000000000 --- a/drivers/gles2/shaders/canvas_shadow.glsl +++ /dev/null @@ -1,62 +0,0 @@ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - -uniform highp mat4 projection_matrix; -uniform highp mat4 light_matrix; -uniform highp mat4 world_matrix; - -attribute highp vec3 vertex; // attrib:0 - -#ifndef USE_DEPTH_SHADOWS - -varying vec4 position_interp; - -#endif - - -void main() { - - gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0))); - -#ifndef USE_DEPTH_SHADOWS - position_interp = gl_Position; -#endif - -} - -[fragment] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - -#ifndef USE_DEPTH_SHADOWS - -varying vec4 position_interp; - -#endif - -void main() { - -#ifdef USE_DEPTH_SHADOWS - -#else - highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias; - highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); - comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - gl_FragColor = comp; -#endif - -} - diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl deleted file mode 100644 index 23680ffe91..0000000000 --- a/drivers/gles2/shaders/copy.glsl +++ /dev/null @@ -1,557 +0,0 @@ -[vertex] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - -attribute highp vec4 vertex_attrib; // attrib:0 -#ifdef USE_CUBEMAP -attribute vec3 cube_in; // attrib:4 -#else -attribute vec2 uv_in; // attrib:4 -#endif -attribute vec2 uv2_in; // attrib:5 - - -#ifdef USE_CUBEMAP -varying vec3 cube_interp; -#else -varying vec2 uv_interp; -#endif - -varying vec2 uv2_interp; - -void main() { - -#ifdef USE_CUBEMAP - cube_interp = cube_in; -#else - uv_interp = uv_in; -#endif - uv2_interp = uv2_in; - gl_Position = vertex_attrib; -} - -[fragment] - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#else -precision mediump float; -precision mediump int; -#endif - - - -float sRGB_gamma_correct(float c){ - float a = 0.055; - if(c < 0.0031308) - return 12.92*c; - else - return (1.0+a)*pow(c, 1.0/2.4) - a; -} - -#define LUM_RANGE 4.0 - - -#ifdef USE_ARRAY -uniform sampler2DArray source; -#elif defined(USE_CUBEMAP) -varying vec3 cube_interp; -uniform samplerCube source_cube; -#else -varying vec2 uv_interp; -#ifdef HIGHP_SOURCE -uniform highp sampler2D source; -#else -uniform sampler2D source; -#endif -#endif -varying vec2 uv2_interp; - - -#ifdef USE_DEPTH -uniform highp sampler2D source_depth; //texunit:1 -#endif - -#ifdef USE_GLOW - -uniform sampler2D glow_source; - -#endif - - -#if defined(USE_HDR) && defined(USE_GLOW_COPY) -uniform highp float hdr_glow_threshold; -uniform highp float hdr_glow_scale; -#endif - -#ifdef USE_HDR - -uniform sampler2D hdr_source; -uniform highp float tonemap_exposure; -uniform highp float tonemap_white; -#endif - -#ifdef USE_BCS - -uniform vec3 bcs; - -#endif - -#ifdef USE_GLOW_COPY - -uniform float bloom; -uniform float bloom_threshold; - -#endif - -#if defined(SHADOW_BLUR_V_PASS) || defined(SHADOW_BLUR_H_PASS) || defined(BLUR_V_PASS) || defined(BLUR_H_PASS) || defined(USE_HDR_REDUCE) - -uniform vec2 pixel_size; -uniform float pixel_scale; -uniform float blur_magnitude; - -#ifdef USE_HDR_STORE - -uniform highp float hdr_time_delta; -uniform highp float hdr_exp_adj_speed; -uniform highp float min_luminance; -uniform highp float max_luminance; -uniform sampler2D source_vd_lum; - -#endif - -//endif -#elif defined(USE_FXAA) - -uniform vec2 pixel_size; - -#endif - -#ifdef USE_ENERGY - -uniform highp float energy; - -#endif - -#ifdef USE_CUSTOM_ALPHA -uniform float custom_alpha; -#endif - - -void main() { - - //vec4 color = color_interp; - - -#ifdef USE_ARRAY - highp vec4 color = textureLod( source, vec3(uv_interp,0.0),0.0 ); -#elif defined(USE_CUBEMAP) - highp vec4 color = textureCube( source_cube, normalize(cube_interp) ); - -#else - highp vec4 color = texture2D( source, uv_interp ); -#endif - - - -#endif - -#ifdef USE_FXAA - -#define FXAA_REDUCE_MIN (1.0/ 128.0) -#define FXAA_REDUCE_MUL (1.0 / 8.0) -#define FXAA_SPAN_MAX 8.0 - - { - vec3 rgbNW = texture2D(source, uv_interp + vec2(-1.0, -1.0) * pixel_size).xyz; - vec3 rgbNE = texture2D(source, uv_interp + vec2(1.0, -1.0) * pixel_size).xyz; - vec3 rgbSW = texture2D(source, uv_interp + vec2(-1.0, 1.0) * pixel_size).xyz; - vec3 rgbSE = texture2D(source, uv_interp + vec2(1.0, 1.0) * pixel_size).xyz; - vec3 rgbM = color.rgb; - vec3 luma = vec3(0.299, 0.587, 0.114); - float lumaNW = dot(rgbNW, luma); - float lumaNE = dot(rgbNE, luma); - float lumaSW = dot(rgbSW, luma); - float lumaSE = dot(rgbSE, luma); - float lumaM = dot(rgbM, luma); - float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); - float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); - - vec2 dir; - dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); - dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); - - float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * - (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); - - float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); - dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), - max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), - dir * rcpDirMin)) * pixel_size; - - vec3 rgbA = 0.5 * ( - texture2D(source, uv_interp + dir * (1.0 / 3.0 - 0.5)).xyz + - texture2D(source, uv_interp + dir * (2.0 / 3.0 - 0.5)).xyz); - vec3 rgbB = rgbA * 0.5 + 0.25 * ( - texture2D(source, uv_interp + dir * -0.5).xyz + - texture2D(source, uv_interp + dir * 0.5).xyz); - - float lumaB = dot(rgbB, luma); - if ((lumaB < lumaMin) || (lumaB > lumaMax)) - color.rgb = rgbA; - else - color.rgb = rgbB; - } - -#endif - //color.rg=uv_interp; - -#ifdef USE_BCS - - 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 BLUR_V_PASS - - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale); - - color*=(1.0/7.0)*blur_magnitude; - -#endif - -#ifdef BLUR_H_PASS - - - color+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale); - color+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale); - - color*=(1.0/7.0)*blur_magnitude; - -#endif - -#ifdef SHADOW_BLUR_V_PASS - -#ifdef USE_RGBA_DEPTH - -#define VEC42DEPTH(m_vec4) dot(m_vec4,vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1)) - - highp float depth = VEC42DEPTH(color)*0.383; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale))*0.006; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale))*0.061; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale))*0.242; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale))*0.242; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale))*0.061; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale))*0.006; - highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); - comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - color=comp; - -#else - - highp float depth = color.r*0.383; - depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale).r*0.006; - depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale).r*0.061; - depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale).r*0.242; - depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale).r*0.242; - depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale).r*0.061; - depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale).r*0.006; - -#ifdef USE_GLES_OVER_GL - gl_FragDepth = depth; - -#else - gl_FragDepthEXT = depth; -#endif - - return; -#endif - -#endif - -#ifdef SHADOW_BLUR_H_PASS - - -#ifdef USE_RGBA_DEPTH - -#define VEC42DEPTH(m_vec4) dot(m_vec4,vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1)) - - highp float depth = VEC42DEPTH(color)*0.383; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale))*0.006; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale))*0.061; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale))*0.242; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale))*0.242; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale))*0.061; - depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale))*0.006; - highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); - comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - color=comp; -#else - - - highp float depth = color.r*0.383; - depth+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale).r*0.006; - depth+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale).r*0.061; - depth+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale).r*0.242; - depth+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale).r*0.242; - depth+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale).r*0.061; - depth+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale).r*0.006; - -#ifdef USE_GLES_OVER_GL - gl_FragDepth = depth; -#else - gl_FragDepthEXT = depth; -#endif - - return; - -#endif - -#endif - -#ifdef USE_HDR - - highp float white_mult = 1.0; - -#ifdef USE_8BIT_HDR - highp vec4 _mult = vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1); - highp float hdr_lum = dot(texture2D( hdr_source, vec2(0.0) ), _mult ); - color.rgb*=LUM_RANGE; - hdr_lum*=LUM_RANGE; //restore to full range -#else - - highp vec2 lv = texture2D( hdr_source, vec2(0.0) ).rg; - highp float hdr_lum = lv.r; -#ifdef USE_AUTOWHITE - white_mult=lv.g; -#endif - -#endif - -#ifdef USE_REINHARDT_TONEMAPPER - float src_lum = dot(color.rgb,vec3(0.3, 0.58, 0.12)); - float lp = tonemap_exposure/hdr_lum*src_lum; - float white = tonemap_white; -#ifdef USE_AUTOWHITE - white_mult = (white_mult + 1.0 * white_mult); - white_mult*=white_mult; - white*=white_mult; -#endif - lp = ( lp * ( 1.0 + ( lp / ( white) ) ) ) / ( 1.0 + lp ); - color.rgb*=lp; - -#else - -#ifdef USE_LOG_TONEMAPPER - color.rgb = tonemap_exposure * log(color.rgb+1.0)/log(hdr_lum+1.0); -#else - highp float tone_scale = tonemap_exposure / hdr_lum; //only linear supported - color.rgb*=tone_scale; -#endif - -#endif - -#endif - - -#ifdef USE_GLOW_COPY - - highp vec3 glowcol = color.rgb*color.a+step(bloom_threshold,dot(vec3(0.3333,0.3333,0.3333),color.rgb))*bloom*color.rgb; - -#ifdef USE_HDR - highp float collum = max(color.r,max(color.g,color.b)); - glowcol+=color.rgb*max(collum-hdr_glow_threshold,0.0)*hdr_glow_scale; -#endif - color.rgb=glowcol; - color.a=0.0; - -#endif - - -#ifdef USE_GLOW - - vec4 glow = texture2D( glow_source, uv2_interp ); - -#ifdef USE_GLOW_SCREEN - - color.rgb = clamp((color.rgb + glow.rgb) - (color.rgb * glow.rgb), 0.0, 1.0); - -#endif - -#ifdef USE_GLOW_SOFTLIGHT - - { - - glow.rgb = (glow.rgb * 0.5) + 0.5; - color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); - color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); - color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); - } - -#endif - -#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) - color.rgb+=glow.rgb; -#endif - - - -#endif - -#ifdef USE_SRGB - -#if 0 - //this was fast, but was commented out because it looked kind of shitty, might it be fixable? - - { //i have my doubts about how fast this is - - color.rgb = min(color.rgb,vec3(1.0)); //clamp just in case - vec3 S1 = sqrt(color.rgb); - vec3 S2 = sqrt(S1); - vec3 S3 = sqrt(S2); - color.rgb = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.225411470 * color.rgb; - } -#else - - color.r=sRGB_gamma_correct(color.r); - color.g=sRGB_gamma_correct(color.g); - color.b=sRGB_gamma_correct(color.b); - -#endif - -#endif - -#ifdef USE_HDR_COPY - - //highp float lum = dot(color.rgb,highp vec3(1.0/3.0,1.0/3.0,1.0/3.0)); - //highp float lum = max(color.r,max(color.g,color.b)); - highp float lum = dot(color.rgb,vec3(0.3, 0.58, 0.12)); - - //lum=log(lum+0.0001); //everyone does it - -#ifdef USE_8BIT_HDR - highp vec4 comp = fract(lum * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); - comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - color=comp; -#else - color.rgb=vec3(lum); -#endif - - -#endif - -#ifdef USE_HDR_REDUCE - -#ifdef USE_8BIT_HDR - highp vec4 _multcv = vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0, 1.0); - highp float lum_accum = dot(color,_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(-pixel_size.x,-pixel_size.y) ),_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(0.0,-pixel_size.y) ),_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(pixel_size.x,-pixel_size.y) ),_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(-pixel_size.x,0.0) ),_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(pixel_size.x,0.0) ),_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(-pixel_size.x,pixel_size.y) ),_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(0.0,pixel_size.y) ),_multcv ); - lum_accum += dot(texture2D( source, uv_interp+vec2(pixel_size.x,pixel_size.y) ),_multcv ); - lum_accum/=9.0; -#else - - highp float lum_accum = color.r; - highp float lum_max = color.g; - -#define LUM_REDUCE(m_uv) \ - {\ - vec2 val = texture2D( source, uv_interp+m_uv ).rg;\ - lum_accum+=val.x;\ - lum_max=max(val.y,lum_max);\ - } - - LUM_REDUCE( vec2(-pixel_size.x,-pixel_size.y) ); - LUM_REDUCE( vec2(0.0,-pixel_size.y) ); - LUM_REDUCE( vec2(pixel_size.x,-pixel_size.y) ); - LUM_REDUCE( vec2(-pixel_size.x,0.0) ); - LUM_REDUCE( vec2(pixel_size.x,0.0) ); - LUM_REDUCE( vec2(-pixel_size.x,pixel_size.y) ); - LUM_REDUCE( vec2(0.0,pixel_size.y) ); - LUM_REDUCE( vec2(pixel_size.x,pixel_size.y) ); - lum_accum/=9.0; - -#endif - -#ifdef USE_HDR_STORE - - //lum_accum=exp(lum_accum); - -#ifdef USE_8BIT_HDR - - highp float vd_lum = dot(texture2D( source_vd_lum, vec2(0.0) ), _multcv ); - lum_accum = clamp( vd_lum + (lum_accum-vd_lum)*hdr_time_delta*hdr_exp_adj_speed,min_luminance*(1.0/LUM_RANGE),max_luminance*(1.0/LUM_RANGE)); -#else - highp float vd_lum=texture2D( source_vd_lum, vec2(0.0) ).r; - lum_accum = clamp( vd_lum + (lum_accum-vd_lum)*hdr_time_delta*hdr_exp_adj_speed,min_luminance,max_luminance); -#endif - -#endif - -#ifdef USE_8BIT_HDR - highp vec4 comp = fract(lum_accum * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); - comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - color=comp; -#else -#ifdef USE_AUTOWHITE - color.r=lum_accum; - color.g=lum_max; -#else - color.rgb=vec3(lum_accum); -#endif - - -#endif - -#endif - - - -#ifdef USE_RGBE - - color.rgb = pow(color.rgb,color.a*255.0-(8.0+128.0)); -#endif - -#ifdef USE_ENERGY - color.rgb*=energy; -#endif - -#ifdef USE_NO_ALPHA - color.a=1.0; -#endif - -#ifdef USE_CUSTOM_ALPHA - color.a=custom_alpha; -#endif - - - gl_FragColor = color; - -#ifdef USE_DEPTH - gl_FragDepth = texture(source_depth,uv_interp).r; -#endif - -} diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl deleted file mode 100644 index 704a22c5d1..0000000000 --- a/drivers/gles2/shaders/material.glsl +++ /dev/null @@ -1,1326 +0,0 @@ -[vertex] - - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#define roundfix( m_val ) floor( (m_val) + 0.5 ) -#else -precision mediump float; -precision mediump int; -#endif - - - -/* -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 -#ifdef ENABLE_AMBIENT_LIGHTMAP - -#ifdef USE_LIGHTMAP_ON_UV2 - -#ifndef ENABLE_UV2_INTERP -#define ENABLE_UV2_INTERP -#endif - -#else - -#ifndef ENABLE_UV_INTERP -#define ENABLE_UV_INTERP -#endif - -#endif - -#endif - - -/* INPUT ATTRIBS */ - -attribute highp vec4 vertex_attrib; // attrib:0 -attribute vec3 normal_attrib; // attrib:1 -attribute vec4 tangent_attrib; // attrib:2 -attribute vec4 color_attrib; // attrib:3 -attribute vec2 uv_attrib; // attrib:4 -attribute vec2 uv2_attrib; // attrib:5 - -uniform float normal_mult; - -#ifdef USE_SKELETON -attribute vec4 bone_indices; // attrib:6 -attribute vec4 bone_weights; // attrib:7 -uniform highp sampler2D skeleton_matrices; -uniform highp float skeltex_pixel_size; -#endif - -#ifdef USE_ATTRIBUTE_INSTANCING - -attribute highp vec4 instance_row0; // attrib:8 -attribute highp vec4 instance_row1; // attrib:9 -attribute highp vec4 instance_row2; // attrib:10 -attribute highp vec4 instance_row3; // attrib:11 - -#endif - -#ifdef USE_TEXTURE_INSTANCING - -attribute highp vec3 instance_uv; // attrib:6 -uniform highp sampler2D instance_matrices; - -#endif - -uniform highp mat4 world_transform; -uniform highp mat4 camera_inverse_transform; -uniform highp mat4 projection_transform; - -#ifdef USE_UNIFORM_INSTANCING -//shittiest form of instancing (but most compatible) -uniform highp mat4 instance_transform; -#endif - -/* Varyings */ - -varying vec3 vertex_interp; -varying vec3 normal_interp; - -#if defined(ENABLE_COLOR_INTERP) -varying vec4 color_interp; -#endif - -#if defined(ENABLE_UV_INTERP) -varying vec2 uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) -varying vec2 uv2_interp; -#endif - -#if defined(ENABLE_VAR1_INTERP) -varying vec4 var1_interp; -#endif - -#if defined(ENABLE_VAR2_INTERP) -varying vec4 var2_interp; -#endif - -#if defined(ENABLE_TANGENT_INTERP) -varying vec3 tangent_interp; -varying vec3 binormal_interp; -#endif - -#ifdef ENABLE_AMBIENT_OCTREE - -uniform highp mat4 ambient_octree_inverse_transform; -varying highp vec3 ambient_octree_coords; - -#endif - -#ifdef USE_FOG - -varying vec4 fog_interp; -uniform highp vec3 fog_params; -uniform vec3 fog_color_begin; -uniform vec3 fog_color_end; - -#endif - -#ifdef USE_VERTEX_LIGHTING - -uniform vec3 light_pos; -uniform vec3 light_direction; -uniform vec3 light_attenuation; -uniform vec3 light_spot_attenuation; -uniform vec3 light_diffuse; -uniform vec3 light_specular; - - - -#endif - -varying vec4 diffuse_interp; -varying vec3 specular_interp; -//intended for static branching -//pretty much all meaningful platforms support -//static branching - -uniform float time; -uniform float instance_id; - -uniform vec3 ambient_light; - -#if !defined(USE_DEPTH_SHADOWS) && defined(USE_SHADOW_PASS) - -varying vec4 position_interp; - -#endif - -#ifdef LIGHT_USE_SHADOW - -uniform highp mat4 shadow_matrix; -varying highp vec4 shadow_coord; -#ifdef LIGHT_USE_PSSM -uniform highp mat4 shadow_matrix2; -varying highp vec4 shadow_coord2; -#endif -#ifdef LIGHT_USE_PSSM4 -uniform highp mat4 shadow_matrix3; -varying highp vec4 shadow_coord3; -uniform highp mat4 shadow_matrix4; -varying highp vec4 shadow_coord4; -#endif - - -#endif - -#ifdef USE_SHADOW_PASS - -uniform highp float shadow_z_offset; -uniform highp float shadow_z_slope_scale; - -#endif - -#ifdef USE_DUAL_PARABOLOID -uniform highp vec2 dual_paraboloid; -varying float dp_clip; -#endif - - - -VERTEX_SHADER_GLOBALS - - - - -void main() { -#ifdef USE_UNIFORM_INSTANCING - - highp mat4 modelview = (camera_inverse_transform * (world_transform * instance_transform)); -#ifdef ENABLE_AMBIENT_OCTREE - highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * (world_transform * instance_transform)); -#endif - -#else - -#ifdef USE_ATTRIBUTE_INSTANCING - - highp mat4 minst=mat4(instance_row0,instance_row1,instance_row2,instance_row3); - highp mat4 modelview = (camera_inverse_transform * (world_transform * minst)); -#ifdef ENABLE_AMBIENT_OCTREE - highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * (world_transform * minst)); -#endif - -#else - -#ifdef USE_TEXTURE_INSTANCING - - highp vec2 ins_ofs=vec2(instance_uv.z,0.0); - - highp mat4 minst=mat4( - texture2D(instance_matrices,instance_uv.xy), - texture2D(instance_matrices,instance_uv.xy+ins_ofs), - texture2D(instance_matrices,instance_uv.xy+ins_ofs*2.0), - texture2D(instance_matrices,instance_uv.xy+ins_ofs*3.0) - ); - - /*highp mat4 minst=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) - );*/ - - highp mat4 modelview = (camera_inverse_transform * (world_transform * minst)); -#ifdef ENABLE_AMBIENT_OCTREE - highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * (world_transform * minst)); -#endif - -#else - highp mat4 modelview = (camera_inverse_transform * world_transform); -#ifdef ENABLE_AMBIENT_OCTREE - highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * world_transform); -#endif - -#endif - -#endif - -#endif - highp vec4 vertex_in = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); - vec3 normal_in = normal_attrib; - normal_in*=normal_mult; -#if defined(ENABLE_TANGENT_INTERP) - vec3 tangent_in = tangent_attrib.xyz; - tangent_in*=normal_mult; - float binormalf = tangent_attrib.a; -#endif - -#ifdef USE_SKELETON - - { - //skeleton transform - highp mat4 m=mat4(texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.x; - m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.y; - m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.z; - m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.w; - - vertex_in = vertex_in * m; - normal_in = (vec4(normal_in,0.0) * m).xyz; -#if defined(ENABLE_TANGENT_INTERP) - tangent_in = (vec4(tangent_in,0.0) * m).xyz; -#endif - } - -#endif - -#ifdef ENABLE_AMBIENT_OCTREE - - ambient_octree_coords = (ambient_octree_transform * vertex_in).xyz; -#endif - - vertex_interp = (modelview * vertex_in).xyz; - normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz); - -#if defined(ENABLE_COLOR_INTERP) -#ifdef USE_COLOR_ATTRIB_SRGB_TO_LINEAR - - color_interp = vec4( - color_attrib.r<0.04045 ? color_attrib.r * (1.0 / 12.92) : pow((color_attrib.r + 0.055) * (1.0 / (1 + 0.055)), 2.4), - color_attrib.g<0.04045 ? color_attrib.g * (1.0 / 12.92) : pow((color_attrib.g + 0.055) * (1.0 / (1 + 0.055)), 2.4), - color_attrib.b<0.04045 ? color_attrib.b * (1.0 / 12.92) : pow((color_attrib.b + 0.055) * (1.0 / (1 + 0.055)), 2.4), - color_attrib.a - ); -#else - color_interp = color_attrib; -#endif -#endif - -#if defined(ENABLE_TANGENT_INTERP) - tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz); - binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf ); -#endif - -#if defined(ENABLE_UV_INTERP) - uv_interp = uv_attrib; -#endif -#if defined(ENABLE_UV2_INTERP) - uv2_interp = uv2_attrib; -#endif - - float vertex_specular_exp = 40.0; //material_specular.a; - - - -VERTEX_SHADER_CODE - - -#ifdef USE_DUAL_PARABOLOID -//for dual paraboloid shadow mapping - highp vec3 vtx = vertex_interp; - vtx.z*=dual_paraboloid.y; //side to affect - vtx.z+=0.01; - dp_clip=vtx.z; - highp float len=length( vtx ); - vtx=normalize(vtx); - vtx.xy/=1.0+vtx.z; - vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near); - vtx+=normalize(vtx)*0.025; - vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace - vertex_interp=vtx; - - //vertex_interp.w = z_clip; - -#endif - -#ifdef USE_SHADOW_PASS - - float z_ofs = shadow_z_offset; - z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale; - vertex_interp.z-=z_ofs; -#endif - -#ifdef LIGHT_USE_SHADOW - - shadow_coord = shadow_matrix * vec4(vertex_interp,1.0); - shadow_coord.xyz/=shadow_coord.w; - -#ifdef LIGHT_USE_PSSM - shadow_coord.y*=0.5; - shadow_coord.y+=0.5; - shadow_coord2 = shadow_matrix2 * vec4(vertex_interp,1.0); - shadow_coord2.xyz/=shadow_coord2.w; - shadow_coord2.y*=0.5; -#endif -#ifdef LIGHT_USE_PSSM4 - shadow_coord.x*=0.5; - shadow_coord2.x*=0.5; - - shadow_coord3 = shadow_matrix3 * vec4(vertex_interp,1.0); - shadow_coord3.xyz/=shadow_coord3.w; - shadow_coord3.xy*=vec2(0.5); - shadow_coord3.xy+=vec2(0.5); - - shadow_coord4 = shadow_matrix4 * vec4(vertex_interp,1.0); - shadow_coord4.xyz/=shadow_coord4.w; - shadow_coord4.xy*=vec2(0.5); - shadow_coord4.x+=0.5; - -#endif - -#endif - -#ifdef USE_FOG - - fog_interp.a = pow( clamp( (length(vertex_interp)-fog_params.x)/(fog_params.y-fog_params.x), 0.0, 1.0 ), fog_params.z ); - fog_interp.rgb = mix( fog_color_begin, fog_color_end, fog_interp.a ); -#endif - -#ifndef VERTEX_SHADER_WRITE_POSITION -//vertex shader might write a position - gl_Position = projection_transform * vec4(vertex_interp,1.0); -#endif - - - -#if !defined(USE_DEPTH_SHADOWS) && defined(USE_SHADOW_PASS) - - position_interp=gl_Position; - -#endif - - -#ifdef USE_VERTEX_LIGHTING - - vec3 eye_vec = -normalize(vertex_interp); - -#ifdef LIGHT_TYPE_DIRECTIONAL - - vec3 light_dir = -light_direction; - float attenuation = light_attenuation.r; - - -#endif - -#ifdef LIGHT_TYPE_OMNI - vec3 light_dir = light_pos-vertex_interp; - float radius = light_attenuation.g; - float dist = min(length(light_dir),radius); - light_dir=normalize(light_dir); - float attenuation = pow( max(1.0 - dist/radius, 0.0), light_attenuation.b ) * light_attenuation.r; - -#endif - -#ifdef LIGHT_TYPE_SPOT - - vec3 light_dir = light_pos-vertex_interp; - float radius = light_attenuation.g; - float dist = min(length(light_dir),radius); - light_dir=normalize(light_dir); - float attenuation = pow( max(1.0 - dist/radius, 0.0), light_attenuation.b ) * light_attenuation.r; - vec3 spot_dir = light_direction; - float spot_cutoff=light_spot_attenuation.r; - float scos = max(dot(-light_dir, spot_dir),spot_cutoff); - float rim = (1.0 - scos) / (1.0 - spot_cutoff); - attenuation *= 1.0 - pow( rim, light_spot_attenuation.g); - - -#endif - -#if defined(LIGHT_TYPE_DIRECTIONAL) || defined(LIGHT_TYPE_OMNI) || defined(LIGHT_TYPE_SPOT) - - //process_shade(normal_interp,light_dir,eye_vec,vertex_specular_exp,attenuation,diffuse_interp,specular_interp); - { - float NdotL = max(0.0,dot( normal_interp, light_dir )); - vec3 half_vec = normalize(light_dir + eye_vec); - float eye_light = max(dot(normal_interp, half_vec),0.0); - diffuse_interp.rgb=light_diffuse * NdotL * attenuation; - diffuse_interp.a=attenuation; - if (NdotL > 0.0) { - specular_interp=light_specular * pow( eye_light, vertex_specular_exp ) * attenuation; - } else { - specular_interp=vec3(0.0); - } - } - -#else - -#ifdef SHADELESS - - diffuse_interp=vec4(vec3(1.0),0.0); - specular_interp=vec3(0.0); -# else - - diffuse_interp=vec4(0.0); - specular_interp=vec3(0.0); -# endif - -#endif - - - - -#endif - - -} - - -[fragment] - - -#ifdef USE_GLES_OVER_GL -#define mediump -#define highp -#define roundfix( m_val ) floor( (m_val) + 0.5 ) -#else - -precision mediump float; -precision mediump int; - -#endif - - -//hack to use uv if no uv present so it works with lightmap -#ifdef ENABLE_AMBIENT_LIGHTMAP - -#ifdef USE_LIGHTMAP_ON_UV2 - -#ifndef ENABLE_UV2_INTERP -#define ENABLE_UV2_INTERP -#endif - -#else - -#ifndef ENABLE_UV_INTERP -#define ENABLE_UV_INTERP -#endif - -#endif - -#endif - - -/* Varyings */ - -#if defined(ENABLE_COLOR_INTERP) -varying vec4 color_interp; -#endif - -#if defined(ENABLE_UV_INTERP) -varying vec2 uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) -varying vec2 uv2_interp; -#endif - -#if defined(ENABLE_TANGENT_INTERP) -varying vec3 tangent_interp; -varying vec3 binormal_interp; -#endif - -#if defined(ENABLE_VAR1_INTERP) -varying vec4 var1_interp; -#endif - -#if defined(ENABLE_VAR2_INTERP) -varying vec4 var2_interp; -#endif - -#ifdef LIGHT_USE_PSSM -uniform vec3 light_pssm_split; -#endif - -varying vec3 vertex_interp; -varying vec3 normal_interp; - -#ifdef USE_FOG - -varying vec4 fog_interp; - -#endif - -/* Material Uniforms */ - -#ifdef USE_VERTEX_LIGHTING - -varying vec4 diffuse_interp; -varying vec3 specular_interp; - -#endif - -#if !defined(USE_DEPTH_SHADOWS) && defined(USE_SHADOW_PASS) - -varying vec4 position_interp; - -#endif - - - -uniform vec3 light_pos; -uniform vec3 light_direction; -uniform vec3 light_attenuation; -uniform vec3 light_spot_attenuation; -uniform vec3 light_diffuse; -uniform vec3 light_specular; - -uniform vec3 ambient_light; - - -#ifdef USE_FRAGMENT_LIGHTING - - - -# ifdef USE_DEPTH_SHADOWS -# else -# endif - -#endif - -uniform float const_light_mult; -uniform float time; - -#ifdef ENABLE_AMBIENT_OCTREE - -varying highp vec3 ambient_octree_coords; -uniform highp float ambient_octree_lattice_size; -uniform highp vec2 ambient_octree_pix_size; -uniform highp vec2 ambient_octree_light_pix_size; -uniform highp float ambient_octree_lattice_divide; -uniform highp sampler2D ambient_octree_tex; -uniform highp sampler2D ambient_octree_light_tex; -uniform float ambient_octree_multiplier; -uniform int ambient_octree_steps; - -#endif - -#ifdef ENABLE_AMBIENT_LIGHTMAP - -uniform highp sampler2D ambient_lightmap; -uniform float ambient_lightmap_multiplier; - -#endif - -#ifdef ENABLE_AMBIENT_DP_SAMPLER - -uniform highp sampler2D ambient_dp_sampler; -uniform float ambient_dp_sampler_multiplier; - -#endif - -#ifdef ENABLE_AMBIENT_COLOR - -uniform vec3 ambient_color; - -#endif - -FRAGMENT_SHADER_GLOBALS - - - -#ifdef LIGHT_USE_SHADOW - -varying highp vec4 shadow_coord; -#ifdef LIGHT_USE_PSSM -varying highp vec4 shadow_coord2; -#endif -#ifdef LIGHT_USE_PSSM4 -varying highp vec4 shadow_coord3; -varying highp vec4 shadow_coord4; -#endif - -uniform highp sampler2D shadow_texture; -uniform highp vec2 shadow_texel_size; - -uniform float shadow_darkening; - -#ifdef USE_DEPTH_SHADOWS - -#define SHADOW_DEPTH(m_tex,m_uv) (texture2D((m_tex),(m_uv)).z) - -#else - -//#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) -#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) - -#endif - -#ifdef USE_SHADOW_PCF - - -#ifdef USE_SHADOW_PCF_HQ - - -float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) { - - float avg=(SHADOW_DEPTH(shadow_texture,coord) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x,0.0)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,0.0)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x*2.0,0.0)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x*2.0,0.0)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,shadow_texel_size.y*2.0)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,-shadow_texel_size.y*2.0)) < refdepth ? 0.0 : 1.0); - return avg*(1.0/13.0); -} - -#else - -float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) { - - float avg=(SHADOW_DEPTH(shadow_texture,coord) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(shadow_texel_size.x,0.0)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(-shadow_texel_size.x,0.0)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - avg+=(SHADOW_DEPTH(shadow_texture,coord+vec2(0.0,-shadow_texel_size.y)) < refdepth ? 0.0 : 1.0); - return avg*0.2; -} - -#endif - - - - -/* - 16x averaging -float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) { - - vec2 offset = vec2( - lessThan(vec2(0.25),fract(gl_FragCoord.xy * 0.5)) - ); - offset.y += offset.x; // y ^= x in floating point - - if (offset.y > 1.1) - offset.y = 0.0; - float avg = step( refdepth, SHADOW_DEPTH(shadow_texture, coord+ (offset + vec2(-1.5, 0.5))*shadow_texel_size) ); - avg+=step(refdepth, SHADOW_DEPTH(shadow_texture, coord+ (offset + vec2(0.5, 0.5))*shadow_texel_size) ); - avg+=step(refdepth, SHADOW_DEPTH(shadow_texture, coord+ (offset + vec2(-1.5, -1.5))*shadow_texel_size) ); - avg+=step(refdepth, SHADOW_DEPTH(shadow_texture, coord+ (offset + vec2(0.5, -1.5))*shadow_texel_size) ); - return avg * 0.25; -} -*/ - -/* -float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) { - - vec2 offset = vec2( - lessThan(vec2(0.25),fract(gl_FragCoord.xy * 0.5)) - ); - offset.y += offset.x; // y ^= x in floating point - - if (offset.y > 1.1) - offset.y = 0.0; - return step( refdepth, SHADOW_DEPTH(shadow_texture, coord+ offset*shadow_texel_size) ); - -} - -*/ -/* simple pcf4 */ -//#define SAMPLE_SHADOW_TEX(m_coord,m_depth) ((step(m_depth,SHADOW_DEPTH(shadow_texture,m_coord))+step(m_depth,SHADOW_DEPTH(shadow_texture,m_coord+vec2(0.0,shadow_texel_size.y)))+step(m_depth,SHADOW_DEPTH(shadow_texture,m_coord+vec2(shadow_texel_size.x,0.0)))+step(m_depth,SHADOW_DEPTH(shadow_texture,m_coord+shadow_texel_size)))/4.0) - -#endif - -#ifdef USE_SHADOW_ESM - -uniform float esm_multiplier; - -float SAMPLE_SHADOW_TEX(vec2 p_uv,float p_depth) { - -#if defined (USE_DEPTH_SHADOWS) - //these only are used if interpolation exists - highp float occluder = SHADOW_DEPTH(shadow_texture, p_uv); -#else - vec2 unnormalized = p_uv/shadow_texel_size; - vec2 fractional = fract(unnormalized); - unnormalized = floor(unnormalized); - - vec4 exponent; - exponent.x = SHADOW_DEPTH(shadow_texture, (unnormalized + vec2( -0.5, 0.5 )) * shadow_texel_size ); - exponent.y = SHADOW_DEPTH(shadow_texture, (unnormalized + vec2( 0.5, 0.5 )) * shadow_texel_size ); - exponent.z = SHADOW_DEPTH(shadow_texture, (unnormalized + vec2( 0.5, -0.5 )) * shadow_texel_size ); - exponent.w = SHADOW_DEPTH(shadow_texture, (unnormalized + vec2( -0.5, -0.5 )) * shadow_texel_size ); - - highp float occluder = (exponent.w + (exponent.x - exponent.w) * fractional.y); - occluder = occluder + ((exponent.z + (exponent.y - exponent.z) * fractional.y) - occluder)*fractional.x; -#endif - return clamp(exp(esm_multiplier* ( occluder - p_depth )),0.0,1.0); - -} - - -#endif - -#if !defined(USE_SHADOW_PCF) && !defined(USE_SHADOW_ESM) - -#define SAMPLE_SHADOW_TEX(m_coord,m_depth) (SHADOW_DEPTH(shadow_texture,m_coord) < m_depth ? 0.0 : 1.0) - -#endif - - -#endif - -#ifdef USE_DUAL_PARABOLOID - -varying float dp_clip; - -#endif - -uniform highp mat4 camera_inverse_transform; - -#if defined(ENABLE_TEXSCREEN) - -uniform vec2 texscreen_screen_mult; -uniform vec4 texscreen_screen_clamp; -uniform sampler2D texscreen_tex; - -#endif - -#if defined(ENABLE_SCREEN_UV) - -uniform vec2 screen_uv_mult; - -#endif - -void main() { - -#ifdef USE_DUAL_PARABOLOID - if (dp_clip<0.0) - discard; -#endif - - //lay out everything, whathever is unused is optimized away anyway - vec3 vertex = vertex_interp; - vec4 diffuse = vec4(0.9,0.9,0.9,1.0); - vec3 specular = vec3(0.0,0.0,0.0); - vec3 emission = vec3(0.0,0.0,0.0); - float specular_exp=1.0; - float glow=0.0; - float shade_param=0.0; -#ifdef DISABLE_FRONT_FACING - float side=float(1)*2.0-1.0; -#else - float side=float(gl_FrontFacing)*2.0-1.0; -#endif -#if defined(ENABLE_TANGENT_INTERP) - vec3 binormal = normalize(binormal_interp)*side; - vec3 tangent = normalize(tangent_interp)*side; -#endif - //vec3 normal = abs(normalize(normal_interp))*side; - vec3 normal = normalize(normal_interp)*side; -#if defined(ENABLE_SCREEN_UV) - vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; -#endif - -#if defined(ENABLE_UV_INTERP) - vec2 uv = uv_interp; -#endif - -#if defined(ENABLE_UV2_INTERP) - vec2 uv2 = uv2_interp; -#endif - -#if defined(ENABLE_COLOR_INTERP) - vec4 color = color_interp; -#endif - -#if defined(ENABLE_NORMALMAP) - - vec3 normalmap = vec3(0.0); -#endif - - float normaldepth=1.0; - - - -#if defined(ENABLE_DISCARD) - bool discard_=false; -#endif - -{ - - -FRAGMENT_SHADER_CODE - -} - -#if defined(ENABLE_NORMALMAP) - - normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side; - -#endif - -#if defined(ENABLE_DISCARD) - if (discard_) { - //easy to eliminate dead code - discard; - } -#endif - -#ifdef ENABLE_CLIP_ALPHA - if (diffuse.a<0.99) { - //used for doublepass and shadowmapping - discard; - } -#endif - - float shadow_attenuation = 1.0; - -#ifdef ENABLE_AMBIENT_LIGHTMAP - - vec3 ambientmap_color = vec3(0.0,0.0,0.0); - vec2 ambientmap_uv = vec2(0.0,0.0); - -#ifdef USE_LIGHTMAP_ON_UV2 - - ambientmap_uv = uv2_interp; - -#else - - ambientmap_uv = uv_interp; - -#endif - - vec4 amcol = texture2D(ambient_lightmap,ambientmap_uv); - shadow_attenuation=amcol.a; - ambientmap_color = amcol.rgb; - ambientmap_color*=ambient_lightmap_multiplier; - ambientmap_color*=diffuse.rgb; - - - -#endif - - -#ifdef ENABLE_AMBIENT_OCTREE - - vec3 ambientmap_color = vec3(0.0,0.0,0.0); - - - { - - //read position from initial lattice grid - highp vec3 lattice_pos = floor(ambient_octree_coords*ambient_octree_lattice_size); - highp vec2 octant_uv = highp vec2(lattice_pos.x+ambient_octree_lattice_size*lattice_pos.z,lattice_pos.y); - octant_uv=(octant_uv*highp vec2(2.0,4.0)+highp vec2(0.0,4.0)); - highp float ld = 1.0/ambient_octree_lattice_size; - - - //go down the octree - - for(int i=0;i<ambient_octree_steps;i++) { - - - highp vec3 sub=mod(ambient_octree_coords,ld); - ld*=0.5; - highp vec3 s = step(ld,sub); - octant_uv+=s.xy; - octant_uv.y+=s.z*2.0; - octant_uv=(octant_uv+0.5)*ambient_octree_pix_size; - highp vec4 new_uv = texture2D(ambient_octree_tex,octant_uv); - octant_uv=floor(highp vec2( dot(new_uv.xy,highp vec2(65280.0,255.0)), dot(new_uv.zw,highp vec2(65280.0,255.0)) )+0.5);//+ambient_octree_pix_size*0.5; - - } - - //sample color - octant_uv=(octant_uv+0.5)*ambient_octree_light_pix_size; - highp vec3 sub=(mod(ambient_octree_coords,ld)/ld); - octant_uv.xy+=sub.xy*ambient_octree_light_pix_size.xy; - vec3 col_up=texture2D(ambient_octree_light_tex,octant_uv).rgb; - octant_uv.y+=ambient_octree_light_pix_size.y*2.0; - vec3 col_down=texture2D(ambient_octree_light_tex,octant_uv).rgb; - ambientmap_color=mix(col_up,col_down,sub.z)*ambient_octree_multiplier; - - ambientmap_color*=diffuse.rgb; - - } - -#endif - - - -#ifdef ENABLE_AMBIENT_DP_SAMPLER - - vec3 ambientmap_color = vec3(0.0,0.0,0.0); - - { - - vec3 dp_normal = normalize((vec4(normal,0) * camera_inverse_transform).xyz); - vec2 ambient_uv = (dp_normal.xy / (1.0+abs(dp_normal.z)))*0.5+0.5; //dual paraboloid - ambient_uv.y*=0.5; - if (dp_normal.z<0) { - - ambient_uv.y=(0.5-ambient_uv.y)+0.5; - - } - - ambientmap_color = texture2D(ambient_dp_sampler,ambient_uv ).rgb * ambient_dp_sampler_multiplier; - ambientmap_color*=diffuse.rgb; - } - -#endif - - - - -#ifdef LIGHT_USE_SHADOW -#ifdef LIGHT_TYPE_DIRECTIONAL - - float shadow_fade_exponent=5.0; //hardcoded for now - float shadow_fade=pow(length(vertex_interp)/light_attenuation.g,shadow_fade_exponent); - -// optimization - skip shadows outside visible range - if(shadow_fade<1.0){ - -#ifdef LIGHT_USE_PSSM - - - //if (vertex_interp.z > light_pssm_split) { -#if 0 - highp vec3 splane = vec3(0.0,0.0,0.0); - - if (gl_FragCoord.w > light_pssm_split.x) { - - splane = shadow_coord.xyz; - splane.y+=1.0; - } else { - splane = shadow_coord2.xyz; - } - splane.y*=0.5; - shadow_attenuation=SAMPLE_SHADOW_TEX(splane.xy,splane.z); - -#else -/* - float sa_a = SAMPLE_SHADOW_TEX(shadow_coord.xy,shadow_coord.z); - float sa_b = SAMPLE_SHADOW_TEX(shadow_coord2.xy,shadow_coord2.z); - if (gl_FragCoord.w > light_pssm_split.x) { - shadow_attenuation=sa_a; - } else { - shadow_attenuation=sa_b; - } -*/ - - vec2 pssm_coord; - float pssm_z; - -#if defined(LIGHT_USE_PSSM) && defined(USE_SHADOW_ESM) -#define USE_PSSM_BLEND - float pssm_blend; - vec2 pssm_coord_2; - float pssm_z_2; - vec3 light_pssm_split_inv = 1.0/light_pssm_split; - float w_inv = 1.0/gl_FragCoord.w; -#endif - -#ifdef LIGHT_USE_PSSM4 - - - if (gl_FragCoord.w > light_pssm_split.y) { - - if (gl_FragCoord.w > light_pssm_split.x) { - pssm_coord=shadow_coord.xy; - pssm_z=shadow_coord.z; -#if defined(USE_PSSM_BLEND) - pssm_coord_2=shadow_coord2.xy; - pssm_z_2=shadow_coord2.z; - pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv); -#endif - - } else { - pssm_coord=shadow_coord2.xy; - pssm_z=shadow_coord2.z; -#if defined(USE_PSSM_BLEND) - pssm_coord_2=shadow_coord3.xy; - pssm_z_2=shadow_coord3.z; - pssm_blend=smoothstep(light_pssm_split_inv.x,light_pssm_split_inv.y,w_inv); -#endif - - } - } else { - - - if (gl_FragCoord.w > light_pssm_split.z) { - pssm_coord=shadow_coord3.xy; - pssm_z=shadow_coord3.z; -#if defined(USE_PSSM_BLEND) - pssm_coord_2=shadow_coord4.xy; - pssm_z_2=shadow_coord4.z; - pssm_blend=smoothstep(light_pssm_split_inv.y,light_pssm_split_inv.z,w_inv); -#endif - - } else { - pssm_coord=shadow_coord4.xy; - pssm_z=shadow_coord4.z; -#if defined(USE_PSSM_BLEND) - pssm_coord_2=shadow_coord4.xy; - pssm_z_2=shadow_coord4.z; - pssm_blend=0.0; -#endif - - } - } - -#else - - if (gl_FragCoord.w > light_pssm_split.x) { - pssm_coord=shadow_coord.xy; - pssm_z=shadow_coord.z; -#if defined(USE_PSSM_BLEND) - pssm_coord_2=shadow_coord2.xy; - pssm_z_2=shadow_coord2.z; - pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv); -#endif - - } else { - pssm_coord=shadow_coord2.xy; - pssm_z=shadow_coord2.z; -#if defined(USE_PSSM_BLEND) - pssm_coord_2=shadow_coord2.xy; - pssm_z_2=shadow_coord2.z; - pssm_blend=0.0; -#endif - - } - -#endif - - //one one sample - shadow_attenuation=SAMPLE_SHADOW_TEX(pssm_coord,pssm_z); -#if defined(USE_PSSM_BLEND) - shadow_attenuation=mix(shadow_attenuation,SAMPLE_SHADOW_TEX(pssm_coord_2,pssm_z_2),pssm_blend); -#endif - - -#endif - -#else - - shadow_attenuation=SAMPLE_SHADOW_TEX(shadow_coord.xy,shadow_coord.z); -#endif - - shadow_attenuation=mix(shadow_attenuation,1.0,shadow_fade); - }else{ - shadow_attenuation=1.0; - }; - -#endif - -#ifdef LIGHT_TYPE_OMNI - - vec3 splane=shadow_coord.xyz;///shadow_coord.w; - float shadow_len=length(splane); - splane=normalize(splane); - float vofs=0.0; - - if (splane.z>=0.0) { - - splane.z+=1.0; - } else { - - splane.z=1.0 - splane.z; - vofs=0.5; - } - splane.xy/=splane.z; - splane.xy=splane.xy * 0.5 + 0.5; - float lradius = light_attenuation.g; - splane.z = shadow_len / lradius; - splane.y=clamp(splane.y,0.0,1.0)*0.5+vofs; - - shadow_attenuation=SAMPLE_SHADOW_TEX(splane.xy,splane.z); -#endif - -#ifdef LIGHT_TYPE_SPOT - - shadow_attenuation=SAMPLE_SHADOW_TEX(shadow_coord.xy,shadow_coord.z); -#endif - - shadow_attenuation=mix(shadow_attenuation,1.0,shadow_darkening); -#endif - - -#ifdef USE_FRAGMENT_LIGHTING - - vec3 eye_vec = -normalize(vertex); - -#ifdef LIGHT_TYPE_DIRECTIONAL - - vec3 light_dir = -light_direction; - float attenuation = light_attenuation.r; - - -#endif - -#ifdef LIGHT_TYPE_OMNI - - vec3 light_dir = light_pos-vertex; - float radius = light_attenuation.g; - float dist = min(length(light_dir),radius); - light_dir=normalize(light_dir); - float attenuation = pow( max(1.0 - dist/radius, 0.0), light_attenuation.b ) * light_attenuation.r; - -#endif - - -#ifdef LIGHT_TYPE_SPOT - - vec3 light_dir = light_pos-vertex; - float radius = light_attenuation.g; - float dist = min(length(light_dir),radius); - light_dir=normalize(light_dir); - float attenuation = pow( max(1.0 - dist/radius, 0.0), light_attenuation.b ) * light_attenuation.r; - vec3 spot_dir = light_direction; - float spot_cutoff=light_spot_attenuation.r; - float scos = max(dot(-light_dir, spot_dir),spot_cutoff); - float rim = (1.0 - scos) / (1.0 - spot_cutoff); - attenuation *= 1.0 - pow( rim, light_spot_attenuation.g); - -#endif - -# if defined(LIGHT_TYPE_DIRECTIONAL) || defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) - - { - - vec3 mdiffuse = diffuse.rgb; - vec3 light; - -#if defined(USE_OUTPUT_SHADOW_COLOR) - vec3 shadow_color=vec3(0.0,0.0,0.0); -#endif - -#if defined(USE_LIGHT_SHADER_CODE) -//light is written by the light shader -{ - -LIGHT_SHADER_CODE - -} -#else -//traditional lambert + blinn - float NdotL = max(0.0,dot( normal, light_dir )); - vec3 half_vec = normalize(light_dir + eye_vec); - float eye_light = max(dot(normal, half_vec),0.0); - - light = light_diffuse * mdiffuse * NdotL; - if (NdotL > 0.0) { - light+=specular * light_specular * pow( eye_light, specular_exp ); - } -#endif - diffuse.rgb = const_light_mult * ambient_light *diffuse.rgb + light * attenuation * shadow_attenuation; - -#if defined(USE_OUTPUT_SHADOW_COLOR) - diffuse.rgb += light * shadow_color * attenuation * (1.0 - shadow_attenuation); -#endif - -#ifdef USE_FOG - - diffuse.rgb = mix(diffuse.rgb,fog_interp.rgb,fog_interp.a); - -# if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) - diffuse.rgb = mix(mix(vec3(0.0),diffuse.rgb,attenuation),diffuse.rgb,const_light_mult); -# endif - - -#endif - - - } - - -# endif - -# if !defined(LIGHT_TYPE_DIRECTIONAL) && !defined(LIGHT_TYPE_OMNI) && !defined (LIGHT_TYPE_SPOT) -//none -#ifndef SHADELESS - diffuse.rgb=ambient_light *diffuse.rgb; -#endif - -# endif - - diffuse.rgb+=const_light_mult*emission; - -#endif - - - - -#ifdef USE_VERTEX_LIGHTING - - vec3 ambient = const_light_mult*ambient_light*diffuse.rgb; -# if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) - //ambient*=diffuse_interp.a; //attenuation affects ambient too - -# endif - - //diffuse.rgb=(diffuse.rgb * diffuse_interp.rgb + specular * specular_interp)*shadow_attenuation + ambient; - //diffuse.rgb+=emission * const_light_mult; - diffuse.rgb=(diffuse.rgb * diffuse_interp.rgb + specular * specular_interp)*shadow_attenuation + ambient; - diffuse.rgb+=emission * const_light_mult; - -#ifdef USE_FOG - - diffuse.rgb = mix(diffuse.rgb,fog_interp.rgb,fog_interp.a); - -# if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) - diffuse.rgb = mix(mix(vec3(0.0),diffuse.rgb,diffuse_interp.a),diffuse.rgb,const_light_mult); -# endif - -#endif - -#endif - - -#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) || defined(ENABLE_AMBIENT_DP_SAMPLER) -#if defined(ENABLE_AMBIENT_COLOR) - ambientmap_color*=ambient_color; -#endif - diffuse.rgb+=ambientmap_color; -#endif - - -#ifdef USE_SHADOW_PASS - -#ifdef USE_DEPTH_SHADOWS - - //do nothing, depth is just written -#else - // pack depth to rgba - //highp float bias = 0.0005; - highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias; - highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); - comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - gl_FragColor = comp; - -#endif - -#else - - - -#ifdef USE_GLOW - - diffuse.a=glow; -#endif - -#ifdef USE_8BIT_HDR - diffuse.rgb*=0.25; -#endif - - gl_FragColor = diffuse; -#endif -} - - diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index e6ffa39197..09f35f097a 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -574,6 +574,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur 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 (rect->flags & CANVAS_RECT_FLIP_H) { src_rect.size.x *= -1; @@ -584,12 +585,12 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } if (rect->flags & CANVAS_RECT_TRANSPOSE) { - //err.. + 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(rect->rect.position.x, rect->rect.position.y, rect->rect.size.x, rect->rect.size.y)); + 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) ? true : false); @@ -691,6 +692,13 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur 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); +#ifdef GLES_OVER_GL + if (polygon->antialiased) { + glEnable(GL_LINE_SMOOTH); + _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_PARTICLES: { @@ -1207,11 +1215,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons 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.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(); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 26003f543f..bf07b8b08b 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -42,6 +42,7 @@ public: float projection_matrix[16]; float time; + uint8_t padding[12]; }; RasterizerSceneGLES3 *scene_render; @@ -102,6 +103,7 @@ public: float light_height; float light_outside_alpha; float shadow_distance_mult; + uint8_t padding[4]; } ubo_data; GLuint ubo; diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index e025992c0b..d1c8ccfe21 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -247,11 +247,8 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target) { if (p_render_target.is_valid()) { RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); - if (!rt) { - storage->frame.current_rt = NULL; - } - ERR_FAIL_COND(!rt); storage->frame.current_rt = rt; + ERR_FAIL_COND(!rt); storage->frame.clear_request = false; glViewport(0, 0, rt->width, rt->height); diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index 4bc267ec7e..4bfec09bf3 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 30a77c4b39..a492629dae 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -120,7 +120,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) { ERR_FAIL_COND(!shadow_atlas); ERR_FAIL_COND(p_size < 0); - p_size = nearest_power_of_2(p_size); + p_size = next_power_of_2(p_size); if (p_size == shadow_atlas->size) return; @@ -185,7 +185,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas, in ERR_FAIL_INDEX(p_quadrant, 4); ERR_FAIL_INDEX(p_subdivision, 16384); - uint32_t subdiv = nearest_power_of_2(p_subdivision); + uint32_t subdiv = next_power_of_2(p_subdivision); if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer subdiv <<= 1; } @@ -310,7 +310,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in } uint32_t quad_size = shadow_atlas->size >> 1; - int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, nearest_power_of_2(quad_size * p_coverage)); + 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; @@ -479,7 +479,7 @@ 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 = nearest_power_of_2(p_size); + int size = next_power_of_2(p_size); if (size == reflection_atlas->size) return; @@ -554,7 +554,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_subdivision(RID p_ref_atlas, int ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas); ERR_FAIL_COND(!reflection_atlas); - uint32_t subdiv = nearest_power_of_2(p_subdiv); + uint32_t subdiv = next_power_of_2(p_subdiv); if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer subdiv <<= 1; } @@ -1088,11 +1088,12 @@ void RasterizerSceneGLES3::gi_probe_instance_set_bounds(RID p_probe, const Vecto bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_material, 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)); @@ -1857,12 +1858,21 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform } } -void RasterizerSceneGLES3::_set_cull(bool p_front, bool p_reverse_cull) { +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); @@ -1900,7 +1910,9 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ } state.cull_front = false; + state.cull_disabled = false; glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); state.current_depth_test = true; glEnable(GL_DEPTH_TEST); @@ -2101,7 +2113,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ storage->info.render.surface_switch_count++; } - _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, p_reverse_cull); + _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::NORMAL_MULT, e->instance->mirror ? -1.0 : 1.0); state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform); @@ -2174,44 +2186,51 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo while (m->next_pass.is_valid()) { m = storage->material_owner.getornull(m->next_pass); - if (!m) + if (!m || !m->shader || !m->shader->valid) break; _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow); } } -void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *m, bool p_shadow) { +void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow) { - bool has_base_alpha = (m->shader->spatial.uses_alpha && !m->shader->spatial.uses_alpha_scissor) || m->shader->spatial.uses_screen_texture || m->shader->spatial.unshaded; - bool has_blend_alpha = m->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX || m->shader->spatial.ontop; + bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture; + bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX || p_material->shader->spatial.ontop; bool has_alpha = has_base_alpha || has_blend_alpha; bool shadow = false; bool mirror = p_instance->mirror; + bool no_cull = false; - if (m->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) { + 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 (m->shader->spatial.uses_sss) { + if (p_material->shader->spatial.uses_sss) { state.used_sss = true; } - if (m->shader->spatial.uses_screen_texture) { + if (p_material->shader->spatial.uses_screen_texture) { state.used_screen_texture = true; } if (p_shadow) { - if (has_blend_alpha || (has_base_alpha && m->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) + if (has_blend_alpha || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) return; //bye - if (!m->shader->spatial.uses_alpha_scissor && !m->shader->spatial.writes_modelview_or_projection && !m->shader->spatial.uses_vertex && !m->shader->spatial.uses_discard && m->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + 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) - m = storage->material_owner.getptr(default_material_twosided); - else - m = storage->material_owner.getptr(default_material); + if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { + p_material = storage->material_owner.getptr(default_material_twosided); + no_cull = true; + mirror = false; + } else { + p_material = storage->material_owner.getptr(default_material); + } } has_alpha = false; @@ -2223,7 +2242,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G return; e->geometry = p_geometry; - e->material = m; + e->material = p_material; e->instance = p_instance; e->owner = p_owner; e->sort_key = 0; @@ -2250,7 +2269,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G 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_DEPTH_LAYER_SHIFT; - if (!has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + if (!has_blend_alpha && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //if nothing exists, add this element as opaque too RenderList::Element *oe = render_list.add_element(); @@ -2275,17 +2294,31 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G 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 (shadow || m->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { + if (shadow || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { e->sort_key |= SORT_KEY_UNSHADED_FLAG; } - if (!shadow && (m->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) { + if (!shadow && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) { e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG; } + + if (!shadow && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + //depth prepass for alpha + RenderList::Element *eo = render_list.add_element(); + + eo->instance = e->instance; + eo->geometry = e->geometry; + eo->material = e->material; + eo->sort_key = e->sort_key; + } } void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy) { @@ -3226,6 +3259,8 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near()); 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); @@ -3269,6 +3304,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ 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); @@ -3279,9 +3318,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ 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::FOVY, p_cam_projection.get_fov()); + 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)); @@ -3296,14 +3336,13 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ 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); + //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 @@ -4406,9 +4445,10 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } } + 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] * light_instance->shadow_transform[p_pass].bias_scale; - normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[p_pass].bias_scale; + 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; vp_height = directional_shadow.size; @@ -4535,6 +4575,9 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ 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, 0, flip_facing, false, true, false, false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false); @@ -4757,7 +4800,7 @@ void RasterizerSceneGLES3::initialize() { { //directional light shadow directional_shadow.light_count = 0; - directional_shadow.size = nearest_power_of_2(GLOBAL_GET("rendering/quality/directional_shadow/size")); + 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); @@ -4919,6 +4962,7 @@ void RasterizerSceneGLES3::initialize() { 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", true); } @@ -4961,6 +5005,7 @@ void RasterizerSceneGLES3::iteration() { shadow_filter_mode = ShadowFilterMode(int(ProjectSettings::get_singleton()->get("rendering/quality/shadows/filter_mode"))); subsurface_scatter_follow_surface = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/follow_surface"); + subsurface_scatter_weight_samples = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/weight_samples"); subsurface_scatter_quality = SubSurfaceScatterQuality(int(ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/quality"))); subsurface_scatter_size = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/scale"); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index f6509e0041..659408b455 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -66,6 +66,7 @@ public: 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; @@ -107,7 +108,7 @@ public: TonemapShaderGLES3 tonemap_shader; struct SceneDataUBO { - + //this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes float projection_matrix[16]; float camera_inverse_matrix[16]; float camera_matrix[16]; @@ -132,15 +133,16 @@ public: float subsurface_scatter_width; float ambient_occlusion_affect_light; - bool fog_depth_enabled; + uint32_t fog_depth_enabled; float fog_depth_begin; float fog_depth_curve; - bool fog_transmit_enabled; + uint32_t fog_transmit_enabled; float fog_transmit_curve; - bool fog_height_enabled; + uint32_t fog_height_enabled; float fog_height_min; float fog_height_max; float fog_height_curve; + uint8_t padding[8]; } ubo_data; @@ -150,6 +152,7 @@ public: float transform[16]; float ambient_contribution; + uint8_t padding[12]; } env_radiance_data; @@ -185,6 +188,7 @@ public: int reflection_probe_count; bool cull_front; + bool cull_disabled; bool used_sss; bool used_screen_texture; bool using_contact_shadows; @@ -521,8 +525,8 @@ public: 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_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_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_far_amount, VS::EnvironmentDOFBlurQuality p_quality); + 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, 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); @@ -652,6 +656,7 @@ public: SORT_KEY_MATERIAL_INDEX_SHIFT = 40, SORT_KEY_GEOMETRY_INDEX_SHIFT = 20, SORT_KEY_GEOMETRY_TYPE_SHIFT = 15, + SORT_KEY_CULL_DISABLED_FLAG = 4, SORT_KEY_SKELETON_FLAG = 2, SORT_KEY_MIRROR_FLAG = 1 @@ -777,7 +782,7 @@ public: RenderList render_list; - _FORCE_INLINE_ void _set_cull(bool p_front, bool p_reverse_cull); + _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_alpha_pass); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e, const Transform &p_view_transform); @@ -793,7 +798,7 @@ public: void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy); void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform); - void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transformm, bool p_use_shadows); + 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); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8e7f9b2a70..a66a3d020b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -2143,7 +2143,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[0] = v.normal.x; gui[1] = v.normal.y; - gui[2] = v.normal.x; + gui[2] = v.normal.z; gui[3] = v.d; } } break; @@ -2497,7 +2497,13 @@ void RasterizerStorageGLES3::_update_material(Material *material) { //value=E->get().default_value; } else { //zero because it was not provided - _fill_std140_ubo_empty(E->get().type, data); + 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); + } } } @@ -4444,6 +4450,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) { 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; @@ -4453,7 +4460,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) { 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->reverse_cull = false; light->version = 0; return light_owner.make_rid(light); @@ -4532,6 +4539,14 @@ void RasterizerStorageGLES3::light_set_cull_mask(RID p_light, uint32_t p_mask) { light->instance_change_notify(); } +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; +} + void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) { Light *light = light_owner.getornull(p_light); @@ -4842,35 +4857,6 @@ float RasterizerStorageGLES3::reflection_probe_get_origin_max_distance(RID p_pro return reflection_probe->max_distance; } -/* ROOM API */ - -RID RasterizerStorageGLES3::room_create() { - - return RID(); -} -void RasterizerStorageGLES3::room_add_bounds(RID p_room, const PoolVector<Vector2> &p_convex_polygon, float p_height, const Transform &p_transform) { -} -void RasterizerStorageGLES3::room_clear_bounds(RID p_room) { -} - -/* PORTAL API */ - -// portals are only (x/y) points, forming a convex shape, which its clockwise -// order points outside. (z is 0); - -RID RasterizerStorageGLES3::portal_create() { - - return RID(); -} -void RasterizerStorageGLES3::portal_set_shape(RID p_portal, const Vector<Point2> &p_shape) { -} -void RasterizerStorageGLES3::portal_set_enabled(RID p_portal, bool p_enabled) { -} -void RasterizerStorageGLES3::portal_set_disable_distance(RID p_portal, float p_distance) { -} -void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color &p_color) { -} - RID RasterizerStorageGLES3::gi_probe_create() { GIProbe *gip = memnew(GIProbe); @@ -5179,6 +5165,10 @@ void RasterizerStorageGLES3::particles_set_emitting(RID p_particles, bool p_emit Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); + if (p_emitting != particles->emitting) { + // Restart is overriden by set_emitting + particles->restart_request = false; + } particles->emitting = p_emitting; } void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) { @@ -5470,58 +5460,58 @@ RID RasterizerStorageGLES3::particles_get_draw_pass_mesh(RID p_particles, int p_ return particles->draw_passes[p_pass]; } -void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_delta) { +void RasterizerStorageGLES3::_particles_process(Particles *p_particles, float p_delta) { - float new_phase = Math::fmod((float)particles->phase + (p_delta / particles->lifetime) * particles->speed_scale, (float)1.0); + float new_phase = Math::fmod((float)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, (float)1.0); - if (particles->clear) { - particles->cycle_number = 0; - particles->random_seed = Math::rand(); - } else if (new_phase < particles->phase) { - if (particles->one_shot) { - particles->emitting = false; + 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); } - particles->cycle_number++; + p_particles->cycle_number++; } shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE, new_phase); - shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, particles->phase); - particles->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 * particles->speed_scale); - shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, particles->clear); - glUniform1ui(shaders.particles.get_uniform_location(ParticlesShaderGLES3::RANDOM_SEED), particles->random_seed); + 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 (particles->use_local_coords) + if (p_particles->use_local_coords) shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform()); else - shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, particles->emission_transform); + shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, p_particles->emission_transform); - glUniform1ui(shaders.particles.get_uniform(ParticlesShaderGLES3::CYCLE), particles->cycle_number); + glUniform1ui(shaders.particles.get_uniform(ParticlesShaderGLES3::CYCLE), p_particles->cycle_number); - particles->clear = false; + p_particles->clear = false; - glBindVertexArray(particles->particle_vaos[0]); + glBindVertexArray(p_particles->particle_vaos[0]); - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->particle_buffers[1]); + 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, particles->amount); + glDrawArrays(GL_POINTS, 0, p_particles->amount); glEndTransformFeedback(); - SWAP(particles->particle_buffers[0], particles->particle_buffers[1]); - SWAP(particles->particle_vaos[0], particles->particle_vaos[1]); + SWAP(p_particles->particle_buffers[0], p_particles->particle_buffers[1]); + SWAP(p_particles->particle_vaos[0], p_particles->particle_vaos[1]); glBindVertexArray(0); /* //debug particles :D - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); + glBindBuffer(GL_ARRAY_BUFFER, p_particles->particle_buffers[0]); - float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); - for (int i = 0; i < particles->amount; i++) { + 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])); @@ -6237,7 +6227,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { 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 && rt->buffers.active == false && !rt->flags[RENDER_TARGET_NO_3D]) { //will use this one for rendering 3D + if (j == 0 && i == 0) { //use always glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); used_depth = true; } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 5a272f43fb..c74b127b23 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -314,7 +314,7 @@ public: mutable RID_Owner<Texture> texture_owner; - Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_type, bool &r_compressed, bool &srgb); + Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb); virtual RID texture_create(); virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT); @@ -528,8 +528,8 @@ public: mutable SelfList<Material>::List _material_dirty_list; void _material_make_dirty(Material *p_material) const; - void _material_add_geometry(RID p_material, Geometry *p_instantiable); - void _material_remove_geometry(RID p_material, Geometry *p_instantiable); + void _material_add_geometry(RID p_material, Geometry *p_geometry); + void _material_remove_geometry(RID p_material, Geometry *p_geometry); mutable RID_Owner<Material> material_owner; @@ -868,6 +868,7 @@ public: RID projector; bool shadow; bool negative; + bool reverse_cull; uint32_t cull_mask; VS::LightOmniShadowMode omni_shadow_mode; VS::LightOmniShadowDetail omni_shadow_detail; @@ -887,6 +888,7 @@ public: 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_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); @@ -951,23 +953,6 @@ public: virtual float reflection_probe_get_origin_max_distance(RID p_probe) const; virtual bool reflection_probe_renders_shadows(RID p_probe) const; - /* ROOM API */ - - virtual RID room_create(); - virtual void room_add_bounds(RID p_room, const PoolVector<Vector2> &p_convex_polygon, float p_height, const Transform &p_transform); - virtual void room_clear_bounds(RID p_room); - - /* PORTAL API */ - - // portals are only (x/y) points, forming a convex shape, which its clockwise - // order points outside. (z is 0); - - virtual RID portal_create(); - virtual void portal_set_shape(RID p_portal, const Vector<Point2> &p_shape); - virtual void portal_set_enabled(RID p_portal, bool p_enabled); - virtual void portal_set_disable_distance(RID p_portal, float p_distance); - virtual void portal_set_disabled_color(RID p_portal, const Color &p_color); - /* GI PROBE API */ struct GIProbe : public Instantiable { @@ -1168,7 +1153,7 @@ public: virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order); - virtual void particles_set_draw_passes(RID p_particles, int p_count); + 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); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index c014caee8d..c308e9eddb 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -608,6 +608,9 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener } else { code = "return;"; } + } else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) { + + code = "discard;"; } } break; @@ -626,13 +629,11 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_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) { -#if 1 Vector<String> shader = p_code.split("\n"); for (int i = 0; i < shader.size(); i++) { print_line(itos(i) + " " + shader[i]); } -#endif _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; @@ -754,7 +755,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; actions[VS::SHADER_SPATIAL].renames["AO"] = "ao"; actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; - actions[VS::SHADER_SPATIAL].renames["DISCARD"] = "_discard"; //actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index e79fdb3ba3..46bb6b1b9e 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index f1077e2d20..d4ef256a33 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -102,11 +102,11 @@ void ShaderGLES3::bind_uniforms() { uniforms_dirty = false; } -GLint ShaderGLES3::get_uniform_location(int p_idx) const { +GLint ShaderGLES3::get_uniform_location(int p_index) const { ERR_FAIL_COND_V(!version, -1); - return version->uniform_location[p_idx]; + return version->uniform_location[p_index]; } bool ShaderGLES3::bind() { @@ -273,6 +273,11 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { //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 #if 0 if (cc) { @@ -371,6 +376,11 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { //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 #if 0 if (cc) { diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 5a34010a98..3be0e86496 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -306,7 +306,7 @@ public: }; GLint get_uniform_location(const String &p_name) const; - GLint get_uniform_location(int p_uniform) const; + GLint get_uniform_location(int p_index) const; static _FORCE_INLINE_ ShaderGLES3 *get_active() { return active; }; bool bind(); @@ -318,9 +318,9 @@ public: void clear_caches(); uint32_t create_custom_shader(); - void set_custom_shader_code(uint32_t p_id, const String &p_vertex, const String &p_vertex_globals, const String &p_fragment, const String &p_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_id); - void free_custom_shader(uint32_t p_id); + 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) { diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 0c69c8cf74..f1811fa7b5 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -2,7 +2,7 @@ Import('env') -if env['BUILDERS'].has_key('GLES3_GLSL'): +if 'GLES3_GLSL' in env['BUILDERS']: env.GLES3_GLSL('copy.glsl'); env.GLES3_GLSL('resolve.glsl'); env.GLES3_GLSL('canvas.glsl'); diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 1c950c82d9..37187a86cc 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -116,9 +116,12 @@ void main() { #ifdef USE_TEXTURE_RECT - - uv_interp = src_rect.xy + abs(src_rect.zw) * vertex; - highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex,vec2(1.0,1.0)-vertex,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0); + if (dst_rect.z < 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; @@ -532,11 +535,11 @@ FRAGMENT_SHADER_CODE #ifdef USE_RGBA_SHADOWS -#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) +#define SHADOW_DEPTH(m_tex,m_uv) dot(texture((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) #else -#define SHADOW_DEPTH(m_tex,m_uv) (texture2D((m_tex),(m_uv)).r) +#define SHADOW_DEPTH(m_tex,m_uv) (texture((m_tex),(m_uv)).r) #endif @@ -572,13 +575,11 @@ FRAGMENT_SHADER_CODE #ifdef SHADOW_FILTER_PCF5 - 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/=5.0; #endif @@ -635,4 +636,3 @@ FRAGMENT_SHADER_CODE frag_color = color; } - diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 3f0498746b..ef4925895c 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1559,10 +1559,6 @@ void main() { vec2 screen_uv = gl_FragCoord.xy*screen_pixel_size; #endif -#if defined(ENABLE_DISCARD) - bool discard_=false; -#endif - #if defined (ENABLE_SSS) float sss_strength=0.0; #endif @@ -1603,13 +1599,6 @@ FRAGMENT_SHADER_CODE #endif -#if defined(ENABLE_DISCARD) - if (discard_) { - //easy to eliminate dead code - discard; - } -#endif - #ifdef ENABLE_CLIP_ALPHA if (albedo.a<0.99) { //used for doublepass and shadowmapping @@ -1694,6 +1683,7 @@ FRAGMENT_SHADER_CODE if (gl_FragCoord.w > shadow_split_offsets.w) { vec3 pssm_coord; + float pssm_fade=0.0; #ifdef LIGHT_USE_PSSM_BLEND float pssm_blend; @@ -1751,6 +1741,7 @@ FRAGMENT_SHADER_CODE } 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,gl_FragCoord.w); #if defined(LIGHT_USE_PSSM_BLEND) use_blend=false; @@ -1782,6 +1773,7 @@ FRAGMENT_SHADER_CODE } 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,gl_FragCoord.w); #if defined(LIGHT_USE_PSSM_BLEND) use_blend=false; @@ -1818,7 +1810,7 @@ FRAGMENT_SHADER_CODE } #endif - light_attenuation=mix(shadow_color_contact.rgb,vec3(1.0),shadow); + light_attenuation=mix(mix(shadow_color_contact.rgb,vec3(1.0),shadow),vec3(1.0),pssm_fade); } @@ -1966,6 +1958,13 @@ FRAGMENT_SHADER_CODE #ifdef USE_MULTIPLE_RENDER_TARGETS + +#ifdef SHADELESS + diffuse_buffer=vec4(albedo.rgb,0.0); + specular_buffer=vec4(0.0); + +#else + #if defined(ENABLE_AO) float ambient_scale=0.0; // AO is supplied by material @@ -1981,6 +1980,7 @@ FRAGMENT_SHADER_CODE 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); @@ -1988,6 +1988,7 @@ FRAGMENT_SHADER_CODE sss_buffer = sss_strength; #endif + #else //USE_MULTIPLE_RENDER_TARGETS diff --git a/drivers/gles3/shaders/ssao.glsl b/drivers/gles3/shaders/ssao.glsl index d8302bd46e..0e8fc89d6c 100644 --- a/drivers/gles3/shaders/ssao.glsl +++ b/drivers/gles3/shaders/ssao.glsl @@ -11,6 +11,7 @@ void main() { [fragment] +#define TWO_PI 6.283185307179586476925286766559 #define NUM_SAMPLES (15) @@ -205,7 +206,7 @@ void main() { // Hash function used in the HPG12 AlchemyAO paper - float randomPatternRotationAngle = float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10); + 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 @@ -225,7 +226,7 @@ void main() { #ifdef ENABLE_RADIUS2 //go again for radius2 - randomPatternRotationAngle = float((5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11); + 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 diff --git a/drivers/gles3/shaders/ssao_blur.glsl b/drivers/gles3/shaders/ssao_blur.glsl index ce4154f50c..c7c978dc37 100644 --- a/drivers/gles3/shaders/ssao_blur.glsl +++ b/drivers/gles3/shaders/ssao_blur.glsl @@ -56,6 +56,8 @@ 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); @@ -83,6 +85,7 @@ void main() { 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, @@ -90,8 +93,8 @@ void main() { if (r != 0) { ivec2 ppos = ssC + axis * (r * SCALE); - float value = texelFetch(source_ssao, ppos, 0).r; - float temp_depth = texelFetch(source_depth, ssC, 0).r; + float value = texelFetch(source_ssao, clamp(ppos,ivec2(0),clamp_limit), 0).r; + float temp_depth = texelFetch(source_depth, clamp(ssC,ivec2(0),clamp_limit), 0).r; 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)); diff --git a/drivers/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl index 569be6c5fe..8873443727 100644 --- a/drivers/gles3/shaders/subsurf_scattering.glsl +++ b/drivers/gles3/shaders/subsurf_scattering.glsl @@ -17,36 +17,36 @@ void main() { //#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; -QUALIFIER vec4 kernel[25] = vec4[] ( - vec4(0.530605, 0.613514, 0.739601, 0.0), - vec4(0.000973794, 1.11862e-005, 9.43437e-007, -3.0), - vec4(0.00333804, 7.85443e-005, 1.2945e-005, -2.52083), - vec4(0.00500364, 0.00020094, 5.28848e-005, -2.08333), - vec4(0.00700976, 0.00049366, 0.000151938, -1.6875), - vec4(0.0094389, 0.00139119, 0.000416598, -1.33333), - vec4(0.0128496, 0.00356329, 0.00132016, -1.02083), - vec4(0.017924, 0.00711691, 0.00347194, -0.75), - vec4(0.0263642, 0.0119715, 0.00684598, -0.520833), - vec4(0.0410172, 0.0199899, 0.0118481, -0.333333), - vec4(0.0493588, 0.0367726, 0.0219485, -0.1875), - vec4(0.0402784, 0.0657244, 0.04631, -0.0833333), - vec4(0.0211412, 0.0459286, 0.0378196, -0.0208333), - vec4(0.0211412, 0.0459286, 0.0378196, 0.0208333), - vec4(0.0402784, 0.0657244, 0.04631, 0.0833333), - vec4(0.0493588, 0.0367726, 0.0219485, 0.1875), - vec4(0.0410172, 0.0199899, 0.0118481, 0.333333), - vec4(0.0263642, 0.0119715, 0.00684598, 0.520833), - vec4(0.017924, 0.00711691, 0.00347194, 0.75), - vec4(0.0128496, 0.00356329, 0.00132016, 1.02083), - vec4(0.0094389, 0.00139119, 0.000416598, 1.33333), - vec4(0.00700976, 0.00049366, 0.000151938, 1.6875), - vec4(0.00500364, 0.00020094, 5.28848e-005, 2.08333), - vec4(0.00333804, 7.85443e-005, 1.2945e-005, 2.52083), - vec4(0.000973794, 1.11862e-005, 9.43437e-007, 3.0) + +QUALIFIER vec2 kernel[25] = vec2[] ( +vec2(0.099654,0.0), +vec2(0.001133,-3.0), +vec2(0.002316,-2.52083), +vec2(0.00445,-2.08333), +vec2(0.008033,-1.6875), +vec2(0.013627,-1.33333), +vec2(0.021724,-1.02083), +vec2(0.032542,-0.75), +vec2(0.04581,-0.520833), +vec2(0.0606,-0.333333), +vec2(0.075333,-0.1875), +vec2(0.088001,-0.0833333), +vec2(0.096603,-0.0208333), +vec2(0.096603,0.0208333), +vec2(0.088001,0.0833333), +vec2(0.075333,0.1875), +vec2(0.0606,0.333333), +vec2(0.04581,0.520833), +vec2(0.032542,0.75), +vec2(0.021724,1.02083), +vec2(0.013627,1.33333), +vec2(0.008033,1.6875), +vec2(0.00445,2.08333), +vec2(0.002316,2.52), +vec2(0.001133,3.0) ); #endif //USE_25_SAMPLES @@ -55,24 +55,24 @@ QUALIFIER vec4 kernel[25] = vec4[] ( const int kernel_size=17; -QUALIFIER vec4 kernel[17] = vec4[]( - vec4(0.536343, 0.624624, 0.748867, 0.0), - vec4(0.00317394, 0.000134823, 3.77269e-005, -2.0), - vec4(0.0100386, 0.000914679, 0.000275702, -1.53125), - vec4(0.0144609, 0.00317269, 0.00106399, -1.125), - vec4(0.0216301, 0.00794618, 0.00376991, -0.78125), - vec4(0.0347317, 0.0151085, 0.00871983, -0.5), - vec4(0.0571056, 0.0287432, 0.0172844, -0.28125), - vec4(0.0582416, 0.0659959, 0.0411329, -0.125), - vec4(0.0324462, 0.0656718, 0.0532821, -0.03125), - vec4(0.0324462, 0.0656718, 0.0532821, 0.03125), - vec4(0.0582416, 0.0659959, 0.0411329, 0.125), - vec4(0.0571056, 0.0287432, 0.0172844, 0.28125), - vec4(0.0347317, 0.0151085, 0.00871983, 0.5), - vec4(0.0216301, 0.00794618, 0.00376991, 0.78125), - vec4(0.0144609, 0.00317269, 0.00106399, 1.125), - vec4(0.0100386, 0.000914679, 0.000275702, 1.53125), - vec4(0.00317394, 0.000134823, 3.77269e-005, 2.0) +QUALIFIER vec2 kernel[17] = vec2[]( +vec2(0.197417,0.0), +vec2(0.000078,-2.0), +vec2(0.000489,-1.53125), +vec2(0.002403,-1.125), +vec2(0.009245,-0.78125), +vec2(0.027835,-0.5), +vec2(0.065592,-0.28125), +vec2(0.12098,-0.125), +vec2(0.17467,-0.03125), +vec2(0.17467,0.03125), +vec2(0.12098,0.125), +vec2(0.065592,0.28125), +vec2(0.027835,0.5), +vec2(0.009245,0.78125), +vec2(0.002403,1.125), +vec2(0.000489,1.53125), +vec2(0.000078,2.0) ); #endif //USE_17_SAMPLES @@ -82,27 +82,27 @@ QUALIFIER vec4 kernel[17] = vec4[]( const int kernel_size=11; -QUALIFIER vec4 kernel[11] = vec4[]( - vec4(0.560479, 0.669086, 0.784728, 0.0), - vec4(0.00471691, 0.000184771, 5.07566e-005, -2.0), - vec4(0.0192831, 0.00282018, 0.00084214, -1.28), - vec4(0.03639, 0.0130999, 0.00643685, -0.72), - vec4(0.0821904, 0.0358608, 0.0209261, -0.32), - vec4(0.0771802, 0.113491, 0.0793803, -0.08), - vec4(0.0771802, 0.113491, 0.0793803, 0.08), - vec4(0.0821904, 0.0358608, 0.0209261, 0.32), - vec4(0.03639, 0.0130999, 0.00643685, 0.72), - vec4(0.0192831, 0.00282018, 0.00084214, 1.28), - vec4(0.00471691, 0.000184771, 5.07565e-005, 2.0) +QUALIFIER vec2 kernel[kernel_size] = vec2[]( +vec2(0.198596,0.0), +vec2(0.0093,-2.0), +vec2(0.028002,-1.28), +vec2(0.065984,-0.72), +vec2(0.121703,-0.32), +vec2(0.175713,-0.08), +vec2(0.175713,0.08), +vec2(0.121703,0.32), +vec2(0.065984,0.72), +vec2(0.028002,1.28), +vec2(0.0093,2.0) ); #endif //USE_11_SAMPLES uniform float max_radius; -uniform float fovy; uniform float camera_z_far; uniform float camera_z_near; +uniform float unit_size; uniform vec2 dir; in vec2 uv_interp; @@ -120,19 +120,17 @@ void main() { // 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; depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); - depth=-depth; - // Calculate the radius scale (1.0 for a unit plane sitting on the - // projection window): - float distance = 1.0 / tan(0.5 * fovy); - float scale = distance / -depth; //remember depth is negative by default in OpenGL + + float scale = unit_size / depth; //remember depth is negative by default in OpenGL // Calculate the final step to fetch the surrounding pixels: vec2 step = max_radius * scale * dir; @@ -141,19 +139,21 @@ void main() { // Accumulate the center sample: vec3 color_accum = base_color.rgb; - color_accum *= kernel[0].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].a * step; + 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; depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near)); - depth_cmp=-depth_cmp; float s = clamp(300.0f * distance * max_radius * abs(depth - depth_cmp),0.0,1.0); @@ -161,9 +161,20 @@ void main() { #endif // Accumulate: - color_accum += kernel[i].rgb * color; + 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 index 988e31d1ea..73dec4f90c 100644 --- a/drivers/gles3/shaders/tonemap.glsl +++ b/drivers/gles3/shaders/tonemap.glsl @@ -170,7 +170,7 @@ vec3 tonemap_aces(vec3 color) { return color = clamp((color*(a*color+b))/(color*(c*color+d)+e),vec3(0.0),vec3(1.0)); } -vec3 tonemap_reindhart(vec3 color,vec3 white) { +vec3 tonemap_reindhart(vec3 color,float white) { return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color ); } diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index 33d271248c..46c9442ffc 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -201,7 +201,7 @@ Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_i return OK; } -Error ImageLoaderPNG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear) { +Error ImageLoaderPNG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { Error err = _load_image(f, _read_png_data, p_image); f->close(); diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index f0a525a9eb..fe14108194 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -43,7 +43,7 @@ class ImageLoaderPNG : public ImageFormatLoader { public: static Error _load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_image); - virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear); + virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderPNG(); }; diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index 4f1f318aee..98a3f21245 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -187,7 +187,7 @@ bool ResourceSaverPNG::recognize(const RES &p_resource) const { } void ResourceSaverPNG::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (p_resource->cast_to<Texture>()) { + if (Object::cast_to<Texture>(*p_resource)) { p_extensions->push_back("png"); } } diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index 31ec35c192..a9ff6db86a 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index fb04ef0088..356b1ad958 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -54,7 +54,7 @@ Error AudioDriverPulseAudio::init() { spec.rate = mix_rate; int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = closest_power_of_2(latency * mix_rate / 1000); pa_buffer_attr attr; // set to appropriate buffer size from global settings diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 3ce031e616..2f56726617 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index ca2f03c75a..ffe7d77a4a 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/register_driver_types.h b/drivers/register_driver_types.h index 63c50f6720..f02db428ce 100644 --- a/drivers/register_driver_types.h +++ b/drivers/register_driver_types.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp index 3de25c32ad..7de3ff192e 100644 --- a/drivers/rtaudio/audio_driver_rtaudio.cpp +++ b/drivers/rtaudio/audio_driver_rtaudio.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -104,21 +104,14 @@ Error AudioDriverRtAudio::init() { RtAudio::StreamOptions options; // set the desired numberOfBuffers - unsigned int target_number_of_buffers = 4; - options.numberOfBuffers = target_number_of_buffers; - - //options. - //RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE). */// - //unsigned int numberOfBuffers; /*!< Number of stream buffers. */ - //std::string streamName; /*!< A stream name (currently used only in Jack). */ - //int priority; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */ + options.numberOfBuffers = 4; parameters.firstChannel = 0; mix_rate = GLOBAL_DEF("audio/mix_rate", 44100); int latency = GLOBAL_DEF("audio/output_latency", 25); - // calculate desired buffer_size, taking the desired numberOfBuffers into account (latency depends on numberOfBuffers*buffer_size) - unsigned int buffer_size = nearest_power_of_2(latency * mix_rate / 1000 / target_number_of_buffers); + // calculate desired buffer_size + unsigned int buffer_size = closest_power_of_2(latency * mix_rate / 1000); if (OS::get_singleton()->is_stdout_verbose()) { print_line("audio buffer size: " + itos(buffer_size)); @@ -126,56 +119,28 @@ Error AudioDriverRtAudio::init() { short int tries = 2; - while (true) { - while (true) { - switch (speaker_mode) { - case SPEAKER_MODE_STEREO: parameters.nChannels = 2; break; - case SPEAKER_SURROUND_51: parameters.nChannels = 6; break; - case SPEAKER_SURROUND_71: parameters.nChannels = 8; break; - }; - - try { - dac->openStream(¶meters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_size, &callback, this, &options); - active = true; - - break; - } catch (RtAudioError &e) { - // try with less channels - ERR_PRINT("Unable to open audio, retrying with fewer channels.."); - - switch (speaker_mode) { - case SPEAKER_MODE_STEREO: speaker_mode = SPEAKER_MODE_STEREO; break; - case SPEAKER_SURROUND_51: speaker_mode = SPEAKER_SURROUND_51; break; - case SPEAKER_SURROUND_71: speaker_mode = SPEAKER_SURROUND_71; break; - }; - } - } + while (tries >= 0) { + switch (speaker_mode) { + case SPEAKER_MODE_STEREO: parameters.nChannels = 2; break; + case SPEAKER_SURROUND_51: parameters.nChannels = 6; break; + case SPEAKER_SURROUND_71: parameters.nChannels = 8; break; + }; - // compare actual numberOfBuffers with the desired one. If not equal, close and reopen the stream with adjusted buffer size, so the desired output_latency is still correct - if (target_number_of_buffers != options.numberOfBuffers) { - if (tries <= 0) { - ERR_EXPLAIN("RtAudio: Unable to set correct number of buffers."); - ERR_FAIL_V(ERR_UNAVAILABLE); - break; - } + try { + dac->openStream(¶meters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_size, &callback, this, &options); + active = true; - try { - dac->closeStream(); - active = false; - } catch (RtAudioError &e) { - ERR_PRINT(e.what()); - ERR_FAIL_V(ERR_UNAVAILABLE); - break; + break; + } catch (RtAudioError &e) { + // try with less channels + ERR_PRINT("Unable to open audio, retrying with fewer channels.."); + + switch (speaker_mode) { + case SPEAKER_SURROUND_51: speaker_mode = SPEAKER_MODE_STEREO; break; + case SPEAKER_SURROUND_71: speaker_mode = SPEAKER_SURROUND_51; break; } - if (OS::get_singleton()->is_stdout_verbose()) - print_line("RtAudio: Desired number of buffers (" + itos(target_number_of_buffers) + ") not available. Using " + itos(options.numberOfBuffers) + " instead. Reopening stream with adjusted buffer_size."); - // new buffer size dependent on the ratio between set and actual numberOfBuffers - buffer_size = buffer_size / (options.numberOfBuffers / target_number_of_buffers); - target_number_of_buffers = options.numberOfBuffers; tries--; - } else { - break; } } @@ -231,6 +196,7 @@ void AudioDriverRtAudio::finish() { AudioDriverRtAudio::AudioDriverRtAudio() { + active = false; mutex = NULL; dac = NULL; mix_rate = 44100; diff --git a/drivers/rtaudio/audio_driver_rtaudio.h b/drivers/rtaudio/audio_driver_rtaudio.h index c2a18b2731..858a51eb73 100644 --- a/drivers/rtaudio/audio_driver_rtaudio.h +++ b/drivers/rtaudio/audio_driver_rtaudio.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub index 96efc91b7a..5ced44dfda 100644 --- a/drivers/unix/SCsub +++ b/drivers/unix/SCsub @@ -8,7 +8,7 @@ g_set_p += 'String OS_Unix::get_global_settings_path() const {\n' g_set_p += '\treturn "' + env["unix_global_settings_path"] + '";\n' g_set_p += '}\n' g_set_p += '#endif' -f = open("os_unix_global_settings_path.gen.cpp", "wb") +f = open("os_unix_global_settings_path.gen.cpp", "w") f.write(g_set_p) f.close() diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index cf54f3fea0..ddc3b2ed33 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -194,21 +194,9 @@ Error DirAccessUnix::make_dir(String p_dir) { p_dir = fix_path(p_dir); -#if 1 - - bool success = (mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0); - int err = errno; - -#else - char real_current_dir_name[2048]; - getcwd(real_current_dir_name, 2048); - chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants - bool success = (mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0); int err = errno; - chdir(real_current_dir_name); -#endif if (success) { return OK; }; diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index 5a35cdf2e9..ea0df2fa3f 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -75,8 +75,8 @@ public: virtual uint64_t get_modified_time(String p_file); - virtual Error rename(String p_from, String p_to); - virtual Error remove(String p_name); + virtual Error rename(String p_path, String p_new_path); + virtual Error remove(String p_path); virtual size_t get_space_left(); diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index e2f04aec63..d5a66d9a1c 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 3c4b9c0c25..6e5110431f 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 30d2377a04..77c942c673 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -100,6 +100,7 @@ IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) { hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; }; + hints.ai_flags &= !AI_NUMERICHOST; int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result); if (s != 0) { diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index 952d3a8771..1f3b885635 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/mutex_posix.cpp b/drivers/unix/mutex_posix.cpp index 94cfcf78e3..c8fe9e0749 100644 --- a/drivers/unix/mutex_posix.cpp +++ b/drivers/unix/mutex_posix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/mutex_posix.h b/drivers/unix/mutex_posix.h index b3c0cbe051..20d546c72a 100644 --- a/drivers/unix/mutex_posix.h +++ b/drivers/unix/mutex_posix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 0f4e8f757c..75c8a153f6 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -315,7 +315,9 @@ OS::TimeZoneInfo OS_Unix::get_time_zone_info() const { void OS_Unix::delay_usec(uint32_t p_usec) const { - usleep(p_usec); + struct timespec rem = { p_usec / 1000000, (p_usec % 1000000) * 1000 }; + while (nanosleep(&rem, &rem) == EINTR) { + } } uint64_t OS_Unix::get_ticks_usec() const { diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 6cd0016bb0..19e79728fb 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -69,7 +69,7 @@ public: virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); virtual void print(const char *p_format, ...); - virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false); + virtual void vprint(const char *p_format, va_list p_list, bool p_stder = false); virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); virtual String get_stdin_string(bool p_block); diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 74ceb3946a..b743990b92 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -127,7 +127,7 @@ int PacketPeerUDPPosix::get_max_packet_size() const { return 512; // uhm maybe not } -Error PacketPeerUDPPosix::listen(int p_port, IP_Address p_bind_address, int p_recv_buffer_size) { +Error PacketPeerUDPPosix::listen(int p_port, const IP_Address &p_bind_address, int p_recv_buffer_size) { ERR_FAIL_COND_V(sockfd != -1, ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); @@ -172,13 +172,13 @@ Error PacketPeerUDPPosix::wait() { return _poll(true); } -Error PacketPeerUDPPosix::_poll(bool p_wait) { +Error PacketPeerUDPPosix::_poll(bool p_block) { if (sockfd == -1) { return FAILED; } - _set_sock_blocking(p_wait); + _set_sock_blocking(p_block); struct sockaddr_storage from = { 0 }; socklen_t len = sizeof(struct sockaddr_storage); @@ -216,7 +216,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { len = sizeof(struct sockaddr_storage); ++queue_count; - if (p_wait) + if (p_block) break; }; diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h index a52b8b8e95..e580d336b2 100644 --- a/drivers/unix/packet_peer_udp_posix.h +++ b/drivers/unix/packet_peer_udp_posix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -67,7 +67,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port, IP_Address p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536); + virtual Error listen(int p_port, const IP_Address &p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/drivers/unix/rw_lock_posix.cpp b/drivers/unix/rw_lock_posix.cpp index 25bc8f0bd3..ab2d6495bd 100644 --- a/drivers/unix/rw_lock_posix.cpp +++ b/drivers/unix/rw_lock_posix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/rw_lock_posix.h b/drivers/unix/rw_lock_posix.h index f8199aeb54..40b41ce171 100644 --- a/drivers/unix/rw_lock_posix.h +++ b/drivers/unix/rw_lock_posix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/semaphore_posix.cpp b/drivers/unix/semaphore_posix.cpp index 8b553194db..093c6b663a 100644 --- a/drivers/unix/semaphore_posix.cpp +++ b/drivers/unix/semaphore_posix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/semaphore_posix.h b/drivers/unix/semaphore_posix.h index c7a7f9bd87..e33de78545 100644 --- a/drivers/unix/semaphore_posix.h +++ b/drivers/unix/semaphore_posix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index 5fa727a9b9..3fc0144294 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 30843e4947..3bc2397e6f 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index 3f28f82b50..4c3504714c 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 865e9aa1d6..f3f9ab82f1 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -69,7 +69,7 @@ void TCPServerPosix::make_default() { TCP_Server::_create = TCPServerPosix::_create; }; -Error TCPServerPosix::listen(uint16_t p_port, const IP_Address p_bind_address) { +Error TCPServerPosix::listen(uint16_t p_port, const IP_Address &p_bind_address) { ERR_FAIL_COND_V(listen_sockfd != -1, ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index 659b389fe2..a10bafcafe 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -41,7 +41,7 @@ class TCPServerPosix : public TCP_Server { static TCP_Server *_create(); public: - virtual Error listen(uint16_t p_port, IP_Address p_bind_address = IP_Address("*")); + virtual Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); virtual bool is_connection_available() const; virtual Ref<StreamPeerTCP> take_connection(); diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp index 3b895ff9c1..5908246929 100644 --- a/drivers/unix/thread_posix.cpp +++ b/drivers/unix/thread_posix.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -36,8 +36,18 @@ #include <pthread_np.h> #endif +#include "core/safe_refcount.h" #include "os/memory.h" +static pthread_key_t _create_thread_id_key() { + pthread_key_t key; + pthread_key_create(&key, NULL); + return key; +} + +pthread_key_t ThreadPosix::thread_id_key = _create_thread_id_key(); +Thread::ID ThreadPosix::next_thread_id = 0; + Thread::ID ThreadPosix::get_id() const { return id; @@ -51,7 +61,8 @@ Thread *ThreadPosix::create_thread_posix() { void *ThreadPosix::thread_callback(void *userdata) { ThreadPosix *t = reinterpret_cast<ThreadPosix *>(userdata); - t->id = (ID)pthread_self(); + t->id = atomic_increment(&next_thread_id); + pthread_setspecific(thread_id_key, (void *)t->id); ScriptServer::thread_enter(); //scripts may need to attach a stack @@ -77,7 +88,7 @@ Thread *ThreadPosix::create_func_posix(ThreadCreateCallback p_callback, void *p_ } Thread::ID ThreadPosix::get_thread_id_func_posix() { - return (ID)pthread_self(); + return (ID)pthread_getspecific(thread_id_key); } void ThreadPosix::wait_to_finish_func_posix(Thread *p_thread) { diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h index 21e1d290a9..d6a41ed119 100644 --- a/drivers/unix/thread_posix.h +++ b/drivers/unix/thread_posix.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -42,6 +42,9 @@ class ThreadPosix : public Thread { + static pthread_key_t thread_id_key; + static ID next_thread_id; + pthread_t pthread; pthread_attr_t pthread_attr; ThreadCreateCallback callback; diff --git a/drivers/gles2/SCsub b/drivers/wasapi/SCsub index dedd794dba..233593b0f9 100644 --- a/drivers/gles2/SCsub +++ b/drivers/wasapi/SCsub @@ -2,8 +2,7 @@ Import('env') +# Driver source files env.add_source_files(env.drivers_sources, "*.cpp") -SConscript("shaders/SCsub") - Export('env') diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp new file mode 100644 index 0000000000..6e01b5f524 --- /dev/null +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -0,0 +1,351 @@ +/*************************************************************************/ +/* audio_driver_wasapi.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 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. */ +/*************************************************************************/ +#ifdef WASAPI_ENABLED + +#include "audio_driver_wasapi.h" + +#include "os/os.h" +#include "project_settings.h" + +const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); +const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); +const IID IID_IAudioClient = __uuidof(IAudioClient); +const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); + +Error AudioDriverWASAPI::init_device() { + + WAVEFORMATEX *pwfex; + IMMDeviceEnumerator *enumerator = NULL; + IMMDevice *device = NULL; + + CoInitialize(NULL); + + HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audio_client); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + hr = audio_client->GetMixFormat(&pwfex); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + // Since we're using WASAPI Shared Mode we can't control any of these, we just tag along + channels = pwfex->nChannels; + mix_rate = pwfex->nSamplesPerSec; + format_tag = pwfex->wFormatTag; + bits_per_sample = pwfex->wBitsPerSample; + + if (format_tag == WAVE_FORMAT_EXTENSIBLE) { + WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex; + + if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) { + format_tag = WAVE_FORMAT_PCM; + } else if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) { + format_tag = WAVE_FORMAT_IEEE_FLOAT; + } else { + ERR_PRINT("WASAPI: Format not supported"); + ERR_FAIL_V(ERR_CANT_OPEN); + } + } else { + if (format_tag != WAVE_FORMAT_PCM && format_tag != WAVE_FORMAT_IEEE_FLOAT) { + ERR_PRINT("WASAPI: Format not supported"); + ERR_FAIL_V(ERR_CANT_OPEN); + } + } + + int latency = GLOBAL_DEF("audio/output_latency", 25); + buffer_size = closest_power_of_2(latency * mix_rate / 1000); + + if (OS::get_singleton()->is_stdout_verbose()) { + print_line("audio buffer size: " + itos(buffer_size)); + } + + hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 0, 0, pwfex, NULL); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + event = CreateEvent(NULL, FALSE, FALSE, NULL); + ERR_FAIL_COND_V(event == NULL, ERR_CANT_OPEN); + + hr = audio_client->SetEventHandle(event); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + hr = audio_client->GetService(IID_IAudioRenderClient, (void **)&render_client); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + hr = audio_client->GetBufferSize(&max_frames); + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + + samples_in.resize(buffer_size); + buffer_frames = buffer_size / channels; + + return OK; +} + +Error AudioDriverWASAPI::finish_device() { + + if (audio_client) { + if (active) { + audio_client->Stop(); + active = false; + } + } + + if (render_client) { + render_client->Release(); + render_client = NULL; + } + + if (audio_client) { + audio_client->Release(); + audio_client = NULL; + } + + return OK; +} + +Error AudioDriverWASAPI::init() { + + Error err = init_device(); + ERR_FAIL_COND_V(err != OK, err); + + active = false; + exit_thread = false; + thread_exited = false; + + mutex = Mutex::create(true); + thread = Thread::create(thread_func, this); + + return OK; +} + +Error AudioDriverWASAPI::reopen() { + Error err = finish_device(); + if (err != OK) { + ERR_PRINT("WASAPI: finish_device error"); + } else { + err = init_device(); + if (err != OK) { + ERR_PRINT("WASAPI: init_device error"); + } else { + start(); + } + } + + return err; +} + +int AudioDriverWASAPI::get_mix_rate() const { + + return mix_rate; +} + +AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const { + + return SPEAKER_MODE_STEREO; +} + +void AudioDriverWASAPI::thread_func(void *p_udata) { + + AudioDriverWASAPI *ad = (AudioDriverWASAPI *)p_udata; + + while (!ad->exit_thread) { + if (ad->active) { + ad->lock(); + + ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptr()); + + ad->unlock(); + } else { + for (unsigned int i = 0; i < ad->buffer_size; i++) { + ad->samples_in[i] = 0; + } + } + + unsigned int left_frames = ad->buffer_frames; + unsigned int buffer_idx = 0; + while (left_frames > 0) { + WaitForSingleObject(ad->event, 1000); + + UINT32 cur_frames; + HRESULT hr = ad->audio_client->GetCurrentPadding(&cur_frames); + if (hr == S_OK) { + // Check how much frames are available on the WASAPI buffer + UINT32 avail_frames = ad->max_frames - cur_frames; + UINT32 write_frames = avail_frames > left_frames ? left_frames : avail_frames; + + BYTE *buffer = NULL; + hr = ad->render_client->GetBuffer(write_frames, &buffer); + if (hr == S_OK) { + // We're using WASAPI Shared Mode so we must convert the buffer + + if (ad->format_tag == WAVE_FORMAT_PCM) { + switch (ad->bits_per_sample) { + case 8: + for (unsigned int i = 0; i < write_frames * ad->channels; i++) { + ((int8_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 24; + } + break; + + case 16: + for (unsigned int i = 0; i < write_frames * ad->channels; i++) { + ((int16_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 16; + } + break; + + case 24: + for (unsigned int i = 0; i < write_frames * ad->channels; i++) { + int32_t sample = ad->samples_in[buffer_idx++]; + ((int8_t *)buffer)[i * 3 + 2] = sample >> 24; + ((int8_t *)buffer)[i * 3 + 1] = sample >> 16; + ((int8_t *)buffer)[i * 3 + 0] = sample >> 8; + } + break; + + case 32: + for (unsigned int i = 0; i < write_frames * ad->channels; i++) { + ((int32_t *)buffer)[i] = ad->samples_in[buffer_idx++]; + } + break; + } + } else if (ad->format_tag == WAVE_FORMAT_IEEE_FLOAT) { + for (unsigned int i = 0; i < write_frames * ad->channels; i++) { + ((float *)buffer)[i] = (ad->samples_in[buffer_idx++] >> 16) / 32768.f; + } + } else { + ERR_PRINT("WASAPI: Unknown format tag"); + ad->exit_thread = true; + } + + hr = ad->render_client->ReleaseBuffer(write_frames, 0); + if (hr != S_OK) { + ERR_PRINT("WASAPI: Release buffer error"); + } + + left_frames -= write_frames; + } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { + // Device is not valid anymore, reopen it + + Error err = ad->reopen(); + if (err != OK) { + ad->exit_thread = true; + } else { + // We reopened the device and samples_in may have resized, so invalidate the current left_frames + left_frames = 0; + } + } else { + ERR_PRINT("WASAPI: Get buffer error"); + ad->exit_thread = true; + } + } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { + // Device is not valid anymore, reopen it + + Error err = ad->reopen(); + if (err != OK) { + ad->exit_thread = true; + } else { + // We reopened the device and samples_in may have resized, so invalidate the current left_frames + left_frames = 0; + } + } else { + ERR_PRINT("WASAPI: GetCurrentPadding error"); + } + } + } + + ad->thread_exited = true; +} + +void AudioDriverWASAPI::start() { + + HRESULT hr = audio_client->Start(); + if (hr != S_OK) { + ERR_PRINT("WASAPI: Start failed"); + } else { + active = true; + } +} + +void AudioDriverWASAPI::lock() { + + if (mutex) + mutex->lock(); +} + +void AudioDriverWASAPI::unlock() { + + if (mutex) + mutex->unlock(); +} + +void AudioDriverWASAPI::finish() { + + if (thread) { + exit_thread = true; + Thread::wait_to_finish(thread); + + memdelete(thread); + thread = NULL; + } + + finish_device(); + + if (mutex) { + memdelete(mutex); + mutex = NULL; + } +} + +AudioDriverWASAPI::AudioDriverWASAPI() { + + audio_client = NULL; + render_client = NULL; + mutex = NULL; + thread = NULL; + + max_frames = 0; + format_tag = 0; + bits_per_sample = 0; + + samples_in.clear(); + + buffer_size = 0; + channels = 0; + mix_rate = 0; + buffer_frames = 0; + + thread_exited = false; + exit_thread = false; + active = false; +} + +#endif diff --git a/drivers/gles2/rasterizer_instance_gles2.h b/drivers/wasapi/audio_driver_wasapi.h index 09e9716b50..b91751f87e 100644 --- a/drivers/gles2/rasterizer_instance_gles2.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* rasterizer_instance_gles2.h */ +/* audio_driver_wasapi.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -27,15 +27,63 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_INSTANCE_GLES2_H -#define RASTERIZER_INSTANCE_GLES2_H +#ifndef AUDIO_DRIVER_WASAPI_H +#define AUDIO_DRIVER_WASAPI_H -#include "servers/visual/rasterizer.h" +#ifdef WASAPI_ENABLED -#ifdef GLES2_ENABLED +#include "core/os/mutex.h" +#include "core/os/thread.h" +#include "servers/audio_server.h" -Rasterizer *instance_RasterizerGLES2(); +#include <audioclient.h> +#include <mmdeviceapi.h> +#include <windows.h> -#endif +class AudioDriverWASAPI : public AudioDriver { + + HANDLE event; + IAudioClient *audio_client; + IAudioRenderClient *render_client; + Mutex *mutex; + Thread *thread; + + UINT32 max_frames; + WORD format_tag; + WORD bits_per_sample; + + Vector<int32_t> samples_in; + + unsigned int buffer_size; + unsigned int channels; + int mix_rate; + int buffer_frames; + + bool thread_exited; + mutable bool exit_thread; + bool active; -#endif // RASTERIZER_INSTANCE_gles2_H + static void thread_func(void *p_udata); + + Error init_device(); + Error finish_device(); + Error reopen(); + +public: + virtual const char *get_name() const { + return "WASAPI"; + } + + virtual Error init(); + virtual void start(); + virtual int get_mix_rate() const; + virtual SpeakerMode get_speaker_mode() const; + virtual void lock(); + virtual void unlock(); + virtual void finish(); + + AudioDriverWASAPI(); +}; + +#endif // AUDIO_DRIVER_WASAPI_H +#endif diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 76665f0203..6d6a6027d9 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index f7553f50c2..cb0fffdd47 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -75,8 +75,8 @@ public: virtual Error make_dir(String p_dir); - virtual Error rename(String p_from, String p_to); - virtual Error remove(String p_name); + virtual Error rename(String p_path, String p_new_path); + virtual Error remove(String p_path); //virtual FileType get_file_type() const; size_t get_space_left(); diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index c66da2da29..30c8332fa3 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -53,9 +53,9 @@ void FileAccessWindows::check_errors() const { } } -Error FileAccessWindows::_open(const String &p_filename, int p_mode_flags) { +Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { - String filename = fix_path(p_filename); + String filename = fix_path(p_path); if (f) close(); diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index de5fc2bc09..6956e7855a 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/mutex_windows.cpp b/drivers/windows/mutex_windows.cpp index 7d9bc22e51..d862d528e3 100644 --- a/drivers/windows/mutex_windows.cpp +++ b/drivers/windows/mutex_windows.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/mutex_windows.h b/drivers/windows/mutex_windows.h index 2e000a43f5..2f436b5754 100644 --- a/drivers/windows/mutex_windows.h +++ b/drivers/windows/mutex_windows.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/rw_lock_windows.cpp b/drivers/windows/rw_lock_windows.cpp index e2213be9c1..5cbedeba2f 100644 --- a/drivers/windows/rw_lock_windows.cpp +++ b/drivers/windows/rw_lock_windows.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/rw_lock_windows.h b/drivers/windows/rw_lock_windows.h index eb030d6029..15911c21e7 100644 --- a/drivers/windows/rw_lock_windows.h +++ b/drivers/windows/rw_lock_windows.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/semaphore_windows.cpp b/drivers/windows/semaphore_windows.cpp index 3a5c0b054c..c88329d56c 100644 --- a/drivers/windows/semaphore_windows.cpp +++ b/drivers/windows/semaphore_windows.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/semaphore_windows.h b/drivers/windows/semaphore_windows.h index 90aacc7e26..8e242ae148 100644 --- a/drivers/windows/semaphore_windows.h +++ b/drivers/windows/semaphore_windows.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/shell_windows.cpp b/drivers/windows/shell_windows.cpp index 17ff9fe962..139a8756fb 100644 --- a/drivers/windows/shell_windows.cpp +++ b/drivers/windows/shell_windows.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/shell_windows.h b/drivers/windows/shell_windows.h index d94c5812d1..de4fdc4d73 100644 --- a/drivers/windows/shell_windows.h +++ b/drivers/windows/shell_windows.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp index 01ddf42649..2ff4715b1c 100644 --- a/drivers/windows/thread_windows.cpp +++ b/drivers/windows/thread_windows.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/windows/thread_windows.h b/drivers/windows/thread_windows.h index 143825039c..2c3a325f88 100644 --- a/drivers/windows/thread_windows.h +++ b/drivers/windows/thread_windows.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp index a1ca2c678e..1bd338ead9 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.cpp +++ b/drivers/xaudio2/audio_driver_xaudio2.cpp @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ @@ -50,7 +50,7 @@ Error AudioDriverXAudio2::init() { channels = 2; int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = closest_power_of_2(latency * mix_rate / 1000); samples_in = memnew_arr(int32_t, buffer_size * channels); for (int i = 0; i < AUDIO_BUFFERS; i++) { diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h index 7c1d31b57c..27ef2ebcb8 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.h +++ b/drivers/xaudio2/audio_driver_xaudio2.h @@ -3,7 +3,7 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ |