2017-03-05 15:47:28 +01:00
/*************************************************************************/
/* rasterizer_storage_gles3.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2017-03-05 15:47:28 +01:00
/*************************************************************************/
2020-01-01 11:16:22 +01:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
2017-03-05 15:47:28 +01:00
/* */
/* 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. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2016-10-03 21:33:42 +02:00
# include "rasterizer_storage_gles3.h"
2018-09-11 18:13:45 +02:00
# include "core/engine.h"
# include "core/project_settings.h"
2016-10-10 23:31:01 +02:00
# include "rasterizer_canvas_gles3.h"
2016-10-19 16:14:41 +02:00
# include "rasterizer_scene_gles3.h"
2016-10-03 21:33:42 +02:00
/* TEXTURE API */
2017-03-05 16:44:50 +01:00
# 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
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
# 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
2016-10-03 21:33:42 +02:00
# define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
# define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
# define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
2017-03-05 16:44:50 +01:00
# 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
2016-10-03 21:33:42 +02:00
# 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
2017-03-05 16:44:50 +01:00
# define _EXT_ETC1_RGB8_OES 0x8D64
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
# 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
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
# 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
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
# define _EXT_ATC_RGB_AMD 0x8C92
# define _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
# define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
# define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
# define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
# define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
2016-10-03 21:33:42 +02:00
2016-11-23 00:51:56 +01:00
# define _EXT_COMPRESSED_R11_EAC 0x9270
# define _EXT_COMPRESSED_SIGNED_R11_EAC 0x9271
# define _EXT_COMPRESSED_RG11_EAC 0x9272
# define _EXT_COMPRESSED_SIGNED_RG11_EAC 0x9273
# define _EXT_COMPRESSED_RGB8_ETC2 0x9274
# define _EXT_COMPRESSED_SRGB8_ETC2 0x9275
# define _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
# define _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
# define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278
# define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
# define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
# define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
# define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
# define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
2016-10-03 21:33:42 +02:00
2019-02-13 11:58:52 +01:00
# ifndef GLES_OVER_GL
# define glClearDepth glClearDepthf
# endif
2018-10-29 20:39:18 +01:00
# ifdef __EMSCRIPTEN__
# include <emscripten/emscripten.h>
void glGetBufferSubData ( GLenum target , GLintptr offset , GLsizeiptr size , GLvoid * data ) {
/* clang-format off */
EM_ASM ( {
GLctx . getBufferSubData ( $ 0 , $ 1 , HEAPU8 , $ 2 , $ 3 ) ;
} , target , offset , data , size ) ;
/* clang-format on */
}
# endif
2017-07-22 19:07:38 +02:00
void glTexStorage2DCustom ( GLenum target , GLsizei levels , GLenum internalformat , GLsizei width , GLsizei height , GLenum format , GLenum type ) {
# ifdef GLES_OVER_GL
for ( int i = 0 ; i < levels ; i + + ) {
glTexImage2D ( target , i , internalformat , width , height , 0 , format , type , NULL ) ;
width = MAX ( 1 , ( width / 2 ) ) ;
height = MAX ( 1 , ( height / 2 ) ) ;
}
# else
glTexStorage2D ( target , levels , internalformat , width , height ) ;
# endif
}
2017-01-07 09:33:11 +01:00
GLuint RasterizerStorageGLES3 : : system_fbo = 0 ;
2019-10-25 12:24:17 +02:00
Ref < Image > RasterizerStorageGLES3 : : _get_gl_image_and_format ( const Ref < Image > & p_image , Image : : Format p_format , uint32_t p_flags , Image : : Format & r_real_format , GLenum & r_gl_format , GLenum & r_gl_internal_format , GLenum & r_gl_type , bool & r_compressed , bool & r_srgb , bool p_force_decompress ) const {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
r_compressed = false ;
r_gl_format = 0 ;
2018-08-22 04:56:04 +02:00
r_real_format = p_format ;
2017-05-17 12:36:47 +02:00
Ref < Image > image = p_image ;
2019-10-25 12:24:17 +02:00
r_srgb = false ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
bool need_decompress = false ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
switch ( p_format ) {
2016-10-03 21:33:42 +02:00
case Image : : FORMAT_L8 : {
2017-02-22 23:14:21 +01:00
# ifdef GLES_OVER_GL
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_R8 ;
r_gl_format = GL_RED ;
r_gl_type = GL_UNSIGNED_BYTE ;
2017-02-22 23:14:21 +01:00
# else
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_LUMINANCE ;
r_gl_format = GL_LUMINANCE ;
r_gl_type = GL_UNSIGNED_BYTE ;
2017-02-22 23:14:21 +01:00
# endif
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_LA8 : {
2017-02-22 23:14:21 +01:00
# ifdef GLES_OVER_GL
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RG8 ;
r_gl_format = GL_RG ;
r_gl_type = GL_UNSIGNED_BYTE ;
2017-02-22 23:14:21 +01:00
# else
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_LUMINANCE_ALPHA ;
r_gl_format = GL_LUMINANCE_ALPHA ;
r_gl_type = GL_UNSIGNED_BYTE ;
2017-02-22 23:14:21 +01:00
# endif
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_R8 : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_R8 ;
r_gl_format = GL_RED ;
r_gl_type = GL_UNSIGNED_BYTE ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RG8 : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RG8 ;
r_gl_format = GL_RG ;
r_gl_type = GL_UNSIGNED_BYTE ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGB8 : {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? GL_SRGB8 : GL_RGB8 ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGB ;
r_gl_type = GL_UNSIGNED_BYTE ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGBA8 : {
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? GL_SRGB8_ALPHA8 : GL_RGBA8 ;
2017-03-05 16:44:50 +01:00
r_gl_type = GL_UNSIGNED_BYTE ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGBA4444 : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RGBA4 ;
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4 ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGBA5551 : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RGB5_A1 ;
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1 ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RF : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_R32F ;
r_gl_format = GL_RED ;
r_gl_type = GL_FLOAT ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGF : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RG32F ;
r_gl_format = GL_RG ;
r_gl_type = GL_FLOAT ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGBF : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RGB32F ;
r_gl_format = GL_RGB ;
r_gl_type = GL_FLOAT ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGBAF : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RGBA32F ;
r_gl_format = GL_RGBA ;
r_gl_type = GL_FLOAT ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RH : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_R32F ;
r_gl_format = GL_RED ;
r_gl_type = GL_HALF_FLOAT ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGH : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RG32F ;
r_gl_format = GL_RG ;
r_gl_type = GL_HALF_FLOAT ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGBH : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RGB32F ;
r_gl_format = GL_RGB ;
r_gl_type = GL_HALF_FLOAT ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_RGBAH : {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = GL_RGBA32F ;
r_gl_format = GL_RGBA ;
r_gl_type = GL_HALF_FLOAT ;
2016-10-03 21:33:42 +02:00
2017-05-27 02:49:49 +02:00
} break ;
case Image : : FORMAT_RGBE9995 : {
r_gl_internal_format = GL_RGB9_E5 ;
r_gl_format = GL_RGB ;
r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV ;
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_DXT1 : {
if ( config . s3tc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_DXT3 : {
if ( config . s3tc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_DXT5 : {
if ( config . s3tc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
2017-05-27 02:49:49 +02:00
} break ;
case Image : : FORMAT_RGTC_R : {
if ( config . rgtc_supported ) {
r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT ;
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
} else {
need_decompress = true ;
}
} break ;
case Image : : FORMAT_RGTC_RG : {
if ( config . rgtc_supported ) {
r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT ;
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
} else {
need_decompress = true ;
}
2016-10-03 21:33:42 +02:00
} break ;
case Image : : FORMAT_BPTC_RGBA : {
if ( config . bptc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : _EXT_COMPRESSED_RGBA_BPTC_UNORM ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_BPTC_RGBF : {
if ( config . bptc_supported ) {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT ;
r_gl_format = GL_RGB ;
r_gl_type = GL_FLOAT ;
r_compressed = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_BPTC_RGBFU : {
if ( config . bptc_supported ) {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT ;
r_gl_format = GL_RGB ;
r_gl_type = GL_FLOAT ;
r_compressed = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_PVRTC2 : {
if ( config . pvrtc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_PVRTC2A : {
if ( config . pvrtc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_PVRTC4 : {
if ( config . pvrtc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_PVRTC4A : {
if ( config . pvrtc_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC : {
if ( config . etc_supported ) {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = _EXT_ETC1_RGB8_OES ;
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC2_R11 : {
if ( config . etc2_supported ) {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = _EXT_COMPRESSED_R11_EAC ;
r_gl_format = GL_RED ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC2_R11S : {
if ( config . etc2_supported ) {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC ;
r_gl_format = GL_RED ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC2_RG11 : {
if ( config . etc2_supported ) {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC ;
r_gl_format = GL_RG ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC2_RG11S : {
if ( config . etc2_supported ) {
2017-03-05 16:44:50 +01:00
r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC ;
r_gl_format = GL_RG ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC2_RGB8 : {
if ( config . etc2_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB8_ETC2 : _EXT_COMPRESSED_RGB8_ETC2 ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGB ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC2_RGBA8 : {
if ( config . etc2_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : _EXT_COMPRESSED_RGBA8_ETC2_EAC ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
case Image : : FORMAT_ETC2_RGB8A1 : {
if ( config . etc2_supported ) {
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ;
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = true ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
need_decompress = true ;
2016-10-03 21:33:42 +02:00
}
} break ;
default : {
2017-05-17 12:36:47 +02:00
ERR_FAIL_V ( Ref < Image > ( ) ) ;
2016-10-03 21:33:42 +02:00
}
}
2019-10-25 12:24:17 +02:00
if ( need_decompress | | p_force_decompress ) {
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
if ( ! image . is_null ( ) ) {
image = image - > duplicate ( ) ;
image - > decompress ( ) ;
ERR_FAIL_COND_V ( image - > is_compressed ( ) , image ) ;
image - > convert ( Image : : FORMAT_RGBA8 ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
r_gl_format = GL_RGBA ;
2017-09-07 21:48:50 +02:00
r_gl_internal_format = ( config . srgb_decode_supported | | ( p_flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) ? GL_SRGB8_ALPHA8 : GL_RGBA8 ;
2017-03-05 16:44:50 +01:00
r_gl_type = GL_UNSIGNED_BYTE ;
r_compressed = false ;
2018-08-22 04:56:04 +02:00
r_real_format = Image : : FORMAT_RGBA8 ;
2019-10-25 12:24:17 +02:00
r_srgb = true ;
2016-10-03 21:33:42 +02:00
return image ;
}
return image ;
}
2017-03-05 16:44:50 +01:00
static const GLenum _cube_side_enum [ 6 ] = {
2016-10-03 21:33:42 +02:00
GL_TEXTURE_CUBE_MAP_NEGATIVE_X ,
GL_TEXTURE_CUBE_MAP_POSITIVE_X ,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y ,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z ,
} ;
RID RasterizerStorageGLES3 : : texture_create ( ) {
Texture * texture = memnew ( Texture ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! texture , RID ( ) ) ;
2016-10-03 21:33:42 +02:00
glGenTextures ( 1 , & texture - > tex_id ) ;
2017-03-05 16:44:50 +01:00
texture - > active = false ;
texture - > total_data_size = 0 ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
return texture_owner . make_rid ( texture ) ;
2016-10-03 21:33:42 +02:00
}
2018-06-26 13:59:26 +02:00
void RasterizerStorageGLES3 : : texture_allocate ( RID p_texture , int p_width , int p_height , int p_depth_3d , Image : : Format p_format , VisualServer : : TextureType p_type , uint32_t p_flags ) {
2016-10-03 21:33:42 +02:00
GLenum format ;
GLenum internal_format ;
GLenum type ;
bool compressed ;
bool srgb ;
2017-03-05 16:44:50 +01:00
if ( p_flags & VS : : TEXTURE_FLAG_USED_FOR_STREAMING ) {
p_flags & = ~ VS : : TEXTURE_FLAG_MIPMAPS ; // no mipies for video
2016-10-03 21:33:42 +02:00
}
2018-12-24 07:47:41 +01:00
# ifndef GLES_OVER_GL
switch ( p_format ) {
2019-01-17 20:29:01 +01:00
case Image : : FORMAT_RF :
case Image : : FORMAT_RGF :
case Image : : FORMAT_RGBF :
case Image : : FORMAT_RGBAF :
case Image : : FORMAT_RH :
case Image : : FORMAT_RGH :
case Image : : FORMAT_RGBH :
case Image : : FORMAT_RGBAH : {
2018-12-24 07:47:41 +01:00
if ( ! config . texture_float_linear_supported ) {
// disable linear texture filtering when not supported for float format on some devices (issue #24295)
p_flags & = ~ VS : : TEXTURE_FLAG_FILTER ;
}
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2018-12-24 07:47:41 +01:00
}
# endif
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! texture ) ;
2017-03-05 16:44:50 +01:00
texture - > width = p_width ;
texture - > height = p_height ;
2018-06-26 13:59:26 +02:00
texture - > depth = p_depth_3d ;
2017-03-05 16:44:50 +01:00
texture - > format = p_format ;
texture - > flags = p_flags ;
texture - > stored_cube_sides = 0 ;
2018-06-26 13:59:26 +02:00
texture - > type = p_type ;
switch ( p_type ) {
case VS : : TEXTURE_TYPE_2D : {
texture - > target = GL_TEXTURE_2D ;
2018-08-06 19:56:06 +02:00
texture - > images . resize ( 1 ) ;
2018-06-26 13:59:26 +02:00
} break ;
case VS : : TEXTURE_TYPE_CUBEMAP : {
texture - > target = GL_TEXTURE_CUBE_MAP ;
2018-08-06 19:56:06 +02:00
texture - > images . resize ( 6 ) ;
2018-06-26 13:59:26 +02:00
} break ;
case VS : : TEXTURE_TYPE_2D_ARRAY : {
texture - > target = GL_TEXTURE_2D_ARRAY ;
2018-08-06 19:56:06 +02:00
texture - > images . resize ( p_depth_3d ) ;
2018-06-26 13:59:26 +02:00
} break ;
case VS : : TEXTURE_TYPE_3D : {
texture - > target = GL_TEXTURE_3D ;
2018-08-06 19:56:06 +02:00
texture - > images . resize ( p_depth_3d ) ;
2018-06-26 13:59:26 +02:00
} break ;
}
2016-10-03 21:33:42 +02:00
2019-10-25 12:24:17 +02:00
texture - > is_npot_repeat_mipmap = false ;
# ifdef JAVASCRIPT_ENABLED
// WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT)
// textures with repeat/mipmaps, even though NPOT textures should be supported as per the spec.
// Force decompressing them to work it around on WebGL 2.0 at a performance cost (GH-33058).
int po2_width = next_power_of_2 ( p_width ) ;
int po2_height = next_power_of_2 ( p_height ) ;
bool is_po2 = p_width = = po2_width & & p_height = = po2_height ;
if ( ! is_po2 & & ( p_flags & VS : : TEXTURE_FLAG_REPEAT | | p_flags & VS : : TEXTURE_FLAG_MIPMAPS ) ) {
texture - > is_npot_repeat_mipmap = true ;
}
# endif // JAVASCRIPT_ENABLED
2018-08-22 04:56:04 +02:00
Image : : Format real_format ;
2019-10-25 12:24:17 +02:00
_get_gl_image_and_format ( Ref < Image > ( ) , texture - > format , texture - > flags , real_format , format , internal_format , type , compressed , srgb , texture - > is_npot_repeat_mipmap ) ;
2016-10-03 21:33:42 +02:00
texture - > alloc_width = texture - > width ;
texture - > alloc_height = texture - > height ;
2018-06-26 13:59:26 +02:00
texture - > alloc_depth = texture - > depth ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
texture - > gl_format_cache = format ;
texture - > gl_type_cache = type ;
texture - > gl_internal_format_cache = internal_format ;
texture - > compressed = compressed ;
texture - > srgb = srgb ;
texture - > data_size = 0 ;
texture - > mipmaps = 1 ;
2016-10-03 21:33:42 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
2018-06-26 13:59:26 +02:00
if ( p_type = = VS : : TEXTURE_TYPE_3D | | p_type = = VS : : TEXTURE_TYPE_2D_ARRAY ) {
int width = p_width ;
int height = p_height ;
int depth = p_depth_3d ;
int mipmaps = 0 ;
2019-03-03 16:38:29 +01:00
while ( width > 0 | | height > 0 | | ( p_type = = VS : : TEXTURE_TYPE_3D & & depth > 0 ) ) {
width = MAX ( 1 , width ) ;
height = MAX ( 1 , height ) ;
depth = MAX ( 1 , depth ) ;
2018-06-26 13:59:26 +02:00
2019-03-03 16:38:29 +01:00
glTexImage3D ( texture - > target , mipmaps , internal_format , width , height , depth , 0 , format , type , NULL ) ;
width / = 2 ;
height / = 2 ;
2018-06-26 13:59:26 +02:00
if ( p_type = = VS : : TEXTURE_TYPE_3D ) {
2019-03-03 16:38:29 +01:00
depth / = 2 ;
2018-06-26 13:59:26 +02:00
}
mipmaps + + ;
if ( ! ( p_flags & VS : : TEXTURE_FLAG_MIPMAPS ) )
break ;
}
glTexParameteri ( texture - > target , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_MAX_LEVEL , mipmaps - 1 ) ;
} else if ( p_flags & VS : : TEXTURE_FLAG_USED_FOR_STREAMING ) {
2016-10-03 21:33:42 +02:00
//prealloc if video
2017-03-05 16:44:50 +01:00
glTexImage2D ( texture - > target , 0 , internal_format , p_width , p_height , 0 , format , type , NULL ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
texture - > active = true ;
2016-10-03 21:33:42 +02:00
}
2018-06-26 13:59:26 +02:00
void RasterizerStorageGLES3 : : texture_set_data ( RID p_texture , const Ref < Image > & p_image , int p_layer ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! texture ) ;
ERR_FAIL_COND ( ! texture - > active ) ;
ERR_FAIL_COND ( texture - > render_target ) ;
2017-05-17 12:36:47 +02:00
ERR_FAIL_COND ( texture - > format ! = p_image - > get_format ( ) ) ;
ERR_FAIL_COND ( p_image . is_null ( ) ) ;
2016-10-03 21:33:42 +02:00
GLenum type ;
GLenum format ;
GLenum internal_format ;
bool compressed ;
bool srgb ;
2017-03-05 16:44:50 +01:00
if ( config . keep_original_textures & & ! ( texture - > flags & VS : : TEXTURE_FLAG_USED_FOR_STREAMING ) ) {
2018-08-06 19:56:06 +02:00
texture - > images . write [ p_layer ] = p_image ;
2016-12-23 04:37:38 +01:00
}
2019-10-25 12:24:17 +02:00
2018-08-22 04:56:04 +02:00
Image : : Format real_format ;
2019-10-25 12:24:17 +02:00
Ref < Image > img = _get_gl_image_and_format ( p_image , p_image - > get_format ( ) , texture - > flags , real_format , format , internal_format , type , compressed , srgb , texture - > is_npot_repeat_mipmap ) ;
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
if ( config . shrink_textures_x2 & & ( p_image - > has_mipmaps ( ) | | ! p_image - > is_compressed ( ) ) & & ! ( texture - > flags & VS : : TEXTURE_FLAG_USED_FOR_STREAMING ) ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
texture - > alloc_height = MAX ( 1 , texture - > alloc_height / 2 ) ;
texture - > alloc_width = MAX ( 1 , texture - > alloc_width / 2 ) ;
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
if ( texture - > alloc_width = = img - > get_width ( ) / 2 & & texture - > alloc_height = = img - > get_height ( ) / 2 ) {
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
img - > shrink_x2 ( ) ;
2017-05-27 02:49:49 +02:00
} else if ( img - > get_format ( ) < = Image : : FORMAT_RGBA8 ) {
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
img - > resize ( texture - > alloc_width , texture - > alloc_height , Image : : INTERPOLATE_BILINEAR ) ;
2016-10-03 21:33:42 +02:00
}
} ;
2018-10-04 18:54:20 +02:00
GLenum blit_target = GL_TEXTURE_2D ;
2018-06-26 13:59:26 +02:00
switch ( texture - > type ) {
case VS : : TEXTURE_TYPE_2D : {
blit_target = GL_TEXTURE_2D ;
} break ;
case VS : : TEXTURE_TYPE_CUBEMAP : {
ERR_FAIL_INDEX ( p_layer , 6 ) ;
blit_target = _cube_side_enum [ p_layer ] ;
} break ;
case VS : : TEXTURE_TYPE_2D_ARRAY : {
blit_target = GL_TEXTURE_2D_ARRAY ;
} break ;
case VS : : TEXTURE_TYPE_3D : {
blit_target = GL_TEXTURE_3D ;
} break ;
}
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
texture - > data_size = img - > get_data ( ) . size ( ) ;
PoolVector < uint8_t > : : Read read = img - > get_data ( ) . read ( ) ;
2019-10-28 08:07:29 +01:00
ERR_FAIL_COND ( ! read . ptr ( ) ) ;
2016-10-03 21:33:42 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
2017-05-17 12:36:47 +02:00
texture - > ignore_mipmaps = compressed & & ! img - > has_mipmaps ( ) ;
2016-10-03 21:33:42 +02:00
2017-09-07 21:48:50 +02:00
if ( ( texture - > flags & VS : : TEXTURE_FLAG_MIPMAPS ) & & ! texture - > ignore_mipmaps )
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MIN_FILTER , config . use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR ) ;
2016-10-03 21:33:42 +02:00
else {
2017-03-05 16:44:50 +01:00
if ( texture - > flags & VS : : TEXTURE_FLAG_FILTER ) {
glTexParameteri ( texture - > target , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
2016-10-03 21:33:42 +02:00
}
}
if ( config . srgb_decode_supported & & srgb ) {
2017-03-05 16:44:50 +01:00
if ( texture - > flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , _TEXTURE_SRGB_DECODE_EXT , _DECODE_EXT ) ;
texture - > using_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , _TEXTURE_SRGB_DECODE_EXT , _SKIP_DECODE_EXT ) ;
texture - > using_srgb = false ;
2016-10-03 21:33:42 +02:00
}
}
2017-03-05 16:44:50 +01:00
if ( texture - > flags & VS : : TEXTURE_FLAG_FILTER ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ; // Linear Filtering
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ; // raw Filtering
2016-10-03 21:33:42 +02:00
}
2017-09-07 21:48:50 +02:00
if ( ( ( texture - > flags & VS : : TEXTURE_FLAG_REPEAT ) | | ( texture - > flags & VS : : TEXTURE_FLAG_MIRRORED_REPEAT ) ) & & texture - > target ! = GL_TEXTURE_CUBE_MAP ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
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 ) ;
2016-10-03 21:33:42 +02:00
}
} else {
//glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
2017-03-05 16:44:50 +01:00
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
//set swizle for older format compatibility
2017-02-22 23:14:21 +01:00
# ifdef GLES_OVER_GL
2017-03-05 16:44:50 +01:00
switch ( texture - > format ) {
2016-11-23 00:51:56 +01:00
case Image : : FORMAT_L8 : {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_R , GL_RED ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_G , GL_RED ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_B , GL_RED ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_A , GL_ONE ) ;
2016-11-23 00:51:56 +01:00
} break ;
case Image : : FORMAT_LA8 : {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_R , GL_RED ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_G , GL_RED ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_B , GL_RED ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_A , GL_GREEN ) ;
2016-11-23 00:51:56 +01:00
} break ;
default : {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_R , GL_RED ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_G , GL_GREEN ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_B , GL_BLUE ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_SWIZZLE_A , GL_ALPHA ) ;
2016-11-23 00:51:56 +01:00
} break ;
}
2017-02-22 23:14:21 +01:00
# endif
2016-10-03 21:33:42 +02:00
if ( config . use_anisotropic_filter ) {
2017-03-05 16:44:50 +01:00
if ( texture - > flags & VS : : TEXTURE_FLAG_ANISOTROPIC_FILTER ) {
2016-10-03 21:33:42 +02:00
glTexParameterf ( texture - > target , _GL_TEXTURE_MAX_ANISOTROPY_EXT , config . anisotropic_level ) ;
} else {
glTexParameterf ( texture - > target , _GL_TEXTURE_MAX_ANISOTROPY_EXT , 1 ) ;
}
}
2017-09-07 21:48:50 +02:00
int mipmaps = ( ( texture - > flags & VS : : TEXTURE_FLAG_MIPMAPS ) & & img - > has_mipmaps ( ) ) ? img - > get_mipmap_count ( ) + 1 : 1 ;
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
int w = img - > get_width ( ) ;
int h = img - > get_height ( ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
int tsize = 0 ;
2017-05-27 02:49:49 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < mipmaps ; i + + ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
int size , ofs ;
2017-05-17 12:36:47 +02:00
img - > get_mipmap_offset_and_size ( i , ofs , size ) ;
2016-10-03 21:33:42 +02:00
2018-06-26 13:59:26 +02:00
if ( texture - > type = = VS : : TEXTURE_TYPE_2D | | texture - > type = = VS : : TEXTURE_TYPE_CUBEMAP ) {
if ( texture - > compressed ) {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 4 ) ;
2017-05-27 02:49:49 +02:00
2018-06-26 13:59:26 +02:00
int bw = w ;
int bh = h ;
2017-05-27 02:49:49 +02:00
2018-06-26 13:59:26 +02:00
glCompressedTexImage2D ( blit_target , i , internal_format , bw , bh , 0 , size , & read [ ofs ] ) ;
2016-10-03 21:33:42 +02:00
2018-06-26 13:59:26 +02:00
} else {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
if ( texture - > flags & VS : : TEXTURE_FLAG_USED_FOR_STREAMING ) {
glTexSubImage2D ( blit_target , i , 0 , 0 , w , h , format , type , & read [ ofs ] ) ;
} else {
glTexImage2D ( blit_target , i , internal_format , w , h , 0 , format , type , & read [ ofs ] ) ;
}
}
2016-10-03 21:33:42 +02:00
} else {
2018-06-26 13:59:26 +02:00
if ( texture - > compressed ) {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 4 ) ;
int bw = w ;
int bh = h ;
glCompressedTexSubImage3D ( blit_target , i , 0 , 0 , p_layer , bw , bh , 1 , internal_format , size , & read [ ofs ] ) ;
2016-10-03 21:33:42 +02:00
} else {
2018-06-26 13:59:26 +02:00
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
glTexSubImage3D ( blit_target , i , 0 , 0 , p_layer , w , h , 1 , format , type , & read [ ofs ] ) ;
2016-10-03 21:33:42 +02:00
}
}
2017-03-05 16:44:50 +01:00
tsize + = size ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
w = MAX ( 1 , w > > 1 ) ;
h = MAX ( 1 , h > > 1 ) ;
2016-10-03 21:33:42 +02:00
}
2019-03-03 16:38:29 +01:00
// Handle array and 3D textures, as those set their data per layer.
tsize * = MAX ( texture - > alloc_depth , 1 ) ;
2017-03-05 16:44:50 +01:00
info . texture_mem - = texture - > total_data_size ;
texture - > total_data_size = tsize ;
info . texture_mem + = texture - > total_data_size ;
2016-10-03 21:33:42 +02:00
//printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem);
2018-06-26 13:59:26 +02:00
texture - > stored_cube_sides | = ( 1 < < p_layer ) ;
2016-10-03 21:33:42 +02:00
2018-06-26 13:59:26 +02:00
if ( ( texture - > type = = VS : : TEXTURE_TYPE_2D | | texture - > type = = VS : : TEXTURE_TYPE_CUBEMAP ) & & ( texture - > flags & VS : : TEXTURE_FLAG_MIPMAPS ) & & mipmaps = = 1 & & ! texture - > ignore_mipmaps & & ( texture - > type ! = VS : : TEXTURE_TYPE_CUBEMAP | | texture - > stored_cube_sides = = ( 1 < < 6 ) - 1 ) ) {
2016-10-03 21:33:42 +02:00
//generate mipmaps if they were requested and the image does not contain them
glGenerateMipmap ( texture - > target ) ;
2017-03-05 16:44:50 +01:00
} else if ( mipmaps > 1 ) {
2017-02-06 04:38:39 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_BASE_LEVEL , 0 ) ;
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MAX_LEVEL , mipmaps - 1 ) ;
2018-06-26 13:59:26 +02:00
} else {
glTexParameteri ( texture - > target , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( texture - > target , GL_TEXTURE_MAX_LEVEL , 0 ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
texture - > mipmaps = mipmaps ;
2016-10-03 21:33:42 +02:00
//texture_set_flags(p_texture,texture->flags);
}
2018-04-29 01:23:55 +02:00
// Uploads pixel data to a sub-region of a texture, for the specified mipmap.
// The texture pixels must have been allocated before, because most features seen in texture_set_data() make no sense in a partial update.
// TODO If we want this to be usable without pre-filling pixels with a full image, we have to call glTexImage2D() with null data.
2018-06-26 13:59:26 +02:00
void RasterizerStorageGLES3 : : texture_set_data_partial ( RID p_texture , const Ref < Image > & p_image , int src_x , int src_y , int src_w , int src_h , int dst_x , int dst_y , int p_dst_mip , int p_layer ) {
2018-04-29 01:23:55 +02:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2018-04-29 01:23:55 +02:00
ERR_FAIL_COND ( ! texture ) ;
ERR_FAIL_COND ( ! texture - > active ) ;
ERR_FAIL_COND ( texture - > render_target ) ;
ERR_FAIL_COND ( texture - > format ! = p_image - > get_format ( ) ) ;
ERR_FAIL_COND ( p_image . is_null ( ) ) ;
ERR_FAIL_COND ( src_w < = 0 | | src_h < = 0 ) ;
ERR_FAIL_COND ( src_x < 0 | | src_y < 0 | | src_x + src_w > p_image - > get_width ( ) | | src_y + src_h > p_image - > get_height ( ) ) ;
ERR_FAIL_COND ( dst_x < 0 | | dst_y < 0 | | dst_x + src_w > texture - > alloc_width | | dst_y + src_h > texture - > alloc_height ) ;
ERR_FAIL_COND ( p_dst_mip < 0 | | p_dst_mip > = texture - > mipmaps ) ;
GLenum type ;
GLenum format ;
GLenum internal_format ;
bool compressed ;
bool srgb ;
// Because OpenGL wants data as a dense array, we have to extract the sub-image if the source rect isn't the full image
Ref < Image > p_sub_img = p_image ;
if ( src_x > 0 | | src_y > 0 | | src_w ! = p_image - > get_width ( ) | | src_h ! = p_image - > get_height ( ) ) {
p_sub_img = p_image - > get_rect ( Rect2 ( src_x , src_y , src_w , src_h ) ) ;
}
2018-08-22 04:56:04 +02:00
Image : : Format real_format ;
2019-10-25 12:24:17 +02:00
Ref < Image > img = _get_gl_image_and_format ( p_sub_img , p_sub_img - > get_format ( ) , texture - > flags , real_format , format , internal_format , type , compressed , srgb , texture - > is_npot_repeat_mipmap ) ;
2018-04-29 01:23:55 +02:00
2018-10-04 18:54:20 +02:00
GLenum blit_target = GL_TEXTURE_2D ;
2018-06-26 13:59:26 +02:00
switch ( texture - > type ) {
case VS : : TEXTURE_TYPE_2D : {
blit_target = GL_TEXTURE_2D ;
} break ;
case VS : : TEXTURE_TYPE_CUBEMAP : {
ERR_FAIL_INDEX ( p_layer , 6 ) ;
blit_target = _cube_side_enum [ p_layer ] ;
} break ;
case VS : : TEXTURE_TYPE_2D_ARRAY : {
blit_target = GL_TEXTURE_2D_ARRAY ;
} break ;
case VS : : TEXTURE_TYPE_3D : {
blit_target = GL_TEXTURE_3D ;
} break ;
}
2018-04-29 01:23:55 +02:00
PoolVector < uint8_t > : : Read read = img - > get_data ( ) . read ( ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
int src_data_size = img - > get_data ( ) . size ( ) ;
int src_ofs = 0 ;
2018-06-26 13:59:26 +02:00
if ( texture - > type = = VS : : TEXTURE_TYPE_2D | | texture - > type = = VS : : TEXTURE_TYPE_CUBEMAP ) {
if ( texture - > compressed ) {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 4 ) ;
glCompressedTexSubImage2D ( blit_target , p_dst_mip , dst_x , dst_y , src_w , src_h , internal_format , src_data_size , & read [ src_ofs ] ) ;
2018-04-29 01:23:55 +02:00
2018-06-26 13:59:26 +02:00
} else {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
// `format` has to match the internal_format used when the texture was created
glTexSubImage2D ( blit_target , p_dst_mip , dst_x , dst_y , src_w , src_h , format , type , & read [ src_ofs ] ) ;
}
2018-04-29 01:23:55 +02:00
} else {
2018-06-26 13:59:26 +02:00
if ( texture - > compressed ) {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 4 ) ;
glCompressedTexSubImage3D ( blit_target , p_dst_mip , dst_x , dst_y , p_layer , src_w , src_h , 1 , format , src_data_size , & read [ src_ofs ] ) ;
} else {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
// `format` has to match the internal_format used when the texture was created
glTexSubImage3D ( blit_target , p_dst_mip , dst_x , dst_y , p_layer , src_w , src_h , 1 , format , type , & read [ src_ofs ] ) ;
}
}
if ( texture - > flags & VS : : TEXTURE_FLAG_FILTER ) {
glTexParameteri ( texture - > target , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ; // Linear Filtering
} else {
glTexParameteri ( texture - > target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ; // raw Filtering
2018-04-29 01:23:55 +02:00
}
}
2018-06-26 13:59:26 +02:00
Ref < Image > RasterizerStorageGLES3 : : texture_get_data ( RID p_texture , int p_layer ) const {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
ERR_FAIL_COND_V ( ! texture , Ref < Image > ( ) ) ;
ERR_FAIL_COND_V ( ! texture - > active , Ref < Image > ( ) ) ;
2017-06-09 05:23:50 +02:00
ERR_FAIL_COND_V ( texture - > data_size = = 0 & & ! texture - > render_target , Ref < Image > ( ) ) ;
2016-10-03 21:33:42 +02:00
2018-06-26 13:59:26 +02:00
if ( texture - > type = = VS : : TEXTURE_TYPE_CUBEMAP & & p_layer < 6 & & ! texture - > images [ p_layer ] . is_null ( ) ) {
return texture - > images [ p_layer ] ;
2017-03-24 00:14:12 +01:00
}
2016-12-23 04:37:38 +01:00
2019-01-23 14:17:42 +01:00
// 3D textures and 2D texture arrays need special treatment, as the glGetTexImage reads **the whole**
// texture to host-memory. 3D textures and 2D texture arrays are potentially very big, so reading
// everything just to throw everything but one layer away is A Bad Idea.
//
// Unfortunately, to solve this, the copy shader has to read the data out via a shader and store it
// in a temporary framebuffer. The data from the framebuffer can then be read using glReadPixels.
if ( texture - > type = = VS : : TEXTURE_TYPE_2D_ARRAY | | texture - > type = = VS : : TEXTURE_TYPE_3D ) {
// can't read a layer that doesn't exist
ERR_FAIL_INDEX_V ( p_layer , texture - > alloc_depth , Ref < Image > ( ) ) ;
// get some information about the texture
Image : : Format real_format ;
GLenum gl_format ;
GLenum gl_internal_format ;
GLenum gl_type ;
bool compressed ;
bool srgb ;
_get_gl_image_and_format (
Ref < Image > ( ) ,
texture - > format ,
texture - > flags ,
real_format ,
gl_format ,
gl_internal_format ,
gl_type ,
compressed ,
2019-10-25 12:24:17 +02:00
srgb ,
texture - > is_npot_repeat_mipmap ) ;
2019-01-23 14:17:42 +01:00
PoolVector < uint8_t > data ;
// TODO need to decide between RgbaUnorm and RgbaFloat32 for output
int data_size = Image : : get_image_data_size ( texture - > alloc_width , texture - > alloc_height , Image : : FORMAT_RGBA8 , false ) ;
data . resize ( data_size * 2 ) ; // add some more memory at the end, just in case for buggy drivers
PoolVector < uint8_t > : : Write wb = data . write ( ) ;
// generate temporary resources
GLuint tmp_fbo ;
glGenFramebuffers ( 1 , & tmp_fbo ) ;
GLuint tmp_color_attachment ;
glGenTextures ( 1 , & tmp_color_attachment ) ;
// now bring the OpenGL context into the correct state
{
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fbo ) ;
// back color attachment with memory, then set properties
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , tmp_color_attachment ) ;
// TODO support HDR properly
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , texture - > alloc_width , texture - > alloc_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , NULL ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
// use the color texture as color attachment for this render pass
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , tmp_color_attachment , 0 ) ;
// more GL state, wheeeey
glDepthMask ( GL_FALSE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_CULL_FACE ) ;
glDisable ( GL_BLEND ) ;
glDepthFunc ( GL_LEQUAL ) ;
glColorMask ( 1 , 1 , 1 , 1 ) ;
// use volume tex for reading
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
glViewport ( 0 , 0 , texture - > alloc_width , texture - > alloc_height ) ;
// set up copy shader for proper use
shaders . copy . set_conditional ( CopyShaderGLES3 : : LINEAR_TO_SRGB , ! srgb ) ;
shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_TEXTURE3D , texture - > type = = VS : : TEXTURE_TYPE_3D ) ;
shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_TEXTURE2DARRAY , texture - > type = = VS : : TEXTURE_TYPE_2D_ARRAY ) ;
shaders . copy . bind ( ) ;
2019-07-10 14:16:28 +02:00
float layer ;
if ( texture - > type = = VS : : TEXTURE_TYPE_2D_ARRAY )
layer = ( float ) p_layer ;
else
// calculate the normalized z coordinate for the layer
layer = ( float ) p_layer / ( float ) texture - > alloc_depth ;
2019-01-23 14:17:42 +01:00
shaders . copy . set_uniform ( CopyShaderGLES3 : : LAYER , layer ) ;
glBindVertexArray ( resources . quadie_array ) ;
}
// clear color attachment, then perform copy
glClearColor ( 0.0 , 0.0 , 0.0 , 0.0 ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
// read the image into the host buffer
glReadPixels ( 0 , 0 , texture - > alloc_width , texture - > alloc_height , GL_RGBA , GL_UNSIGNED_BYTE , & wb [ 0 ] ) ;
// remove temp resources and unset some GL state
{
shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_TEXTURE3D , false ) ;
shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_TEXTURE2DARRAY , false ) ;
shaders . copy . set_conditional ( CopyShaderGLES3 : : LINEAR_TO_SRGB , false ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
glDeleteTextures ( 1 , & tmp_color_attachment ) ;
glDeleteFramebuffers ( 1 , & tmp_fbo ) ;
}
2019-07-05 19:08:43 +02:00
wb . release ( ) ;
2019-01-23 14:17:42 +01:00
data . resize ( data_size ) ;
Image * img = memnew ( Image ( texture - > alloc_width , texture - > alloc_height , false , Image : : FORMAT_RGBA8 , data ) ) ;
if ( ! texture - > compressed ) {
img - > convert ( real_format ) ;
}
return Ref < Image > ( img ) ;
}
2016-11-23 00:51:56 +01:00
# ifdef GLES_OVER_GL
2016-10-03 21:33:42 +02:00
2018-08-22 04:56:04 +02:00
Image : : Format real_format ;
GLenum gl_format ;
GLenum gl_internal_format ;
GLenum gl_type ;
bool compressed ;
bool srgb ;
2019-10-25 12:24:17 +02:00
_get_gl_image_and_format ( Ref < Image > ( ) , texture - > format , texture - > flags , real_format , gl_format , gl_internal_format , gl_type , compressed , srgb , false ) ;
2018-08-22 04:56:04 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > data ;
2016-10-03 21:33:42 +02:00
2018-09-29 01:32:40 +02:00
int data_size = Image : : get_image_data_size ( texture - > alloc_width , texture - > alloc_height , real_format , texture - > mipmaps > 1 ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
data . resize ( data_size * 2 ) ; //add some memory at the end, just in case for buggy drivers
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Write wb = data . write ( ) ;
2016-10-03 21:33:42 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( texture - > target , texture - > tex_id ) ;
2016-10-03 21:33:42 +02:00
2016-12-21 18:20:35 +01:00
glBindBuffer ( GL_PIXEL_PACK_BUFFER , 0 ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < texture - > mipmaps ; i + + ) {
2016-10-03 21:33:42 +02:00
2019-05-08 17:20:42 +02:00
int ofs = Image : : get_image_mipmap_offset ( texture - > alloc_width , texture - > alloc_height , real_format , i ) ;
2016-10-03 21:33:42 +02:00
if ( texture - > compressed ) {
glPixelStorei ( GL_PACK_ALIGNMENT , 4 ) ;
2017-03-05 16:44:50 +01:00
glGetCompressedTexImage ( texture - > target , i , & wb [ ofs ] ) ;
2016-10-03 21:33:42 +02:00
} else {
2016-12-21 18:20:35 +01:00
2016-10-03 21:33:42 +02:00
glPixelStorei ( GL_PACK_ALIGNMENT , 1 ) ;
2016-12-21 18:20:35 +01:00
2017-03-05 16:44:50 +01:00
glGetTexImage ( texture - > target , i , texture - > gl_format_cache , texture - > gl_type_cache , & wb [ ofs ] ) ;
2016-10-03 21:33:42 +02:00
}
}
2018-01-18 16:59:25 +01:00
Image : : Format img_format ;
//convert special case RGB10_A2 to RGBA8 because it's not a supported image format
if ( texture - > gl_internal_format_cache = = GL_RGB10_A2 ) {
img_format = Image : : FORMAT_RGBA8 ;
uint32_t * ptr = ( uint32_t * ) wb . ptr ( ) ;
uint32_t num_pixels = data_size / 4 ;
2018-09-26 17:38:02 +02:00
for ( uint32_t ofs = 0 ; ofs < num_pixels ; ofs + + ) {
2018-01-18 16:59:25 +01:00
uint32_t px = ptr [ ofs ] ;
uint32_t a = px > > 30 & 0xFF ;
ptr [ ofs ] = ( px > > 2 & 0xFF ) |
( px > > 12 & 0xFF ) < < 8 |
( px > > 22 & 0xFF ) < < 16 |
( a | a < < 2 | a < < 4 | a < < 6 ) < < 24 ;
}
} else {
2018-08-22 04:56:04 +02:00
img_format = real_format ;
2018-01-18 16:59:25 +01:00
}
2019-07-05 19:08:43 +02:00
wb . release ( ) ;
2016-10-03 21:33:42 +02:00
2018-08-27 15:12:07 +02:00
data . resize ( data_size ) ;
2016-12-21 18:20:35 +01:00
2019-06-26 15:08:25 +02:00
Image * img = memnew ( Image ( texture - > alloc_width , texture - > alloc_height , texture - > mipmaps > 1 , img_format , data ) ) ;
2016-10-03 21:33:42 +02:00
2017-05-17 12:36:47 +02:00
return Ref < Image > ( img ) ;
2016-10-03 21:33:42 +02:00
# else
2018-10-18 11:52:08 +02:00
Image : : Format real_format ;
GLenum gl_format ;
GLenum gl_internal_format ;
GLenum gl_type ;
bool compressed ;
bool srgb ;
2019-10-25 12:24:17 +02:00
_get_gl_image_and_format ( Ref < Image > ( ) , texture - > format , texture - > flags , real_format , gl_format , gl_internal_format , gl_type , compressed , srgb , texture - > is_npot_repeat_mipmap ) ;
2018-10-18 11:52:08 +02:00
PoolVector < uint8_t > data ;
int data_size = Image : : get_image_data_size ( texture - > alloc_width , texture - > alloc_height , Image : : FORMAT_RGBA8 , false ) ;
data . resize ( data_size * 2 ) ; //add some memory at the end, just in case for buggy drivers
PoolVector < uint8_t > : : Write wb = data . write ( ) ;
GLuint temp_framebuffer ;
glGenFramebuffers ( 1 , & temp_framebuffer ) ;
GLuint temp_color_texture ;
glGenTextures ( 1 , & temp_color_texture ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , temp_framebuffer ) ;
glBindTexture ( GL_TEXTURE_2D , temp_color_texture ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , texture - > alloc_width , texture - > alloc_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , NULL ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , temp_color_texture , 0 ) ;
glDepthMask ( GL_FALSE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_CULL_FACE ) ;
glDisable ( GL_BLEND ) ;
glDepthFunc ( GL_LEQUAL ) ;
glColorMask ( 1 , 1 , 1 , 1 ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , texture - > tex_id ) ;
glViewport ( 0 , 0 , texture - > alloc_width , texture - > alloc_height ) ;
shaders . copy . set_conditional ( CopyShaderGLES3 : : LINEAR_TO_SRGB , ! srgb ) ;
2019-01-23 14:17:42 +01:00
shaders . copy . bind ( ) ;
2018-10-18 11:52:08 +02:00
glClearColor ( 0.0 , 0.0 , 0.0 , 0.0 ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
glBindVertexArray ( resources . quadie_array ) ;
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
glBindVertexArray ( 0 ) ;
glReadPixels ( 0 , 0 , texture - > alloc_width , texture - > alloc_height , GL_RGBA , GL_UNSIGNED_BYTE , & wb [ 0 ] ) ;
shaders . copy . set_conditional ( CopyShaderGLES3 : : LINEAR_TO_SRGB , false ) ;
glDeleteTextures ( 1 , & temp_color_texture ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
glDeleteFramebuffers ( 1 , & temp_framebuffer ) ;
2019-07-05 19:08:43 +02:00
wb . release ( ) ;
2018-10-18 11:52:08 +02:00
data . resize ( data_size ) ;
Image * img = memnew ( Image ( texture - > alloc_width , texture - > alloc_height , false , Image : : FORMAT_RGBA8 , data ) ) ;
if ( ! texture - > compressed ) {
img - > convert ( real_format ) ;
}
return Ref < Image > ( img ) ;
2016-10-03 21:33:42 +02:00
# endif
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : texture_set_flags ( RID p_texture , uint32_t p_flags ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! texture ) ;
if ( texture - > render_target ) {
2017-03-05 16:44:50 +01:00
p_flags & = VS : : TEXTURE_FLAG_FILTER ; //can change only filter
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
bool had_mipmaps = texture - > flags & VS : : TEXTURE_FLAG_MIPMAPS ;
2016-10-03 21:33:42 +02:00
2018-06-26 13:59:26 +02:00
texture - > flags = p_flags ;
2016-10-03 21:33:42 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
2017-09-07 21:48:50 +02:00
if ( ( ( texture - > flags & VS : : TEXTURE_FLAG_REPEAT ) | | ( texture - > flags & VS : : TEXTURE_FLAG_MIRRORED_REPEAT ) ) & & texture - > target ! = GL_TEXTURE_CUBE_MAP ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
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 ) ;
2016-10-03 21:33:42 +02:00
}
} else {
//glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
2017-03-05 16:44:50 +01:00
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2016-10-03 21:33:42 +02:00
}
if ( config . use_anisotropic_filter ) {
2017-03-05 16:44:50 +01:00
if ( texture - > flags & VS : : TEXTURE_FLAG_ANISOTROPIC_FILTER ) {
2016-10-03 21:33:42 +02:00
glTexParameterf ( texture - > target , _GL_TEXTURE_MAX_ANISOTROPY_EXT , config . anisotropic_level ) ;
} else {
glTexParameterf ( texture - > target , _GL_TEXTURE_MAX_ANISOTROPY_EXT , 1 ) ;
}
}
2017-09-07 21:48:50 +02:00
if ( ( texture - > flags & VS : : TEXTURE_FLAG_MIPMAPS ) & & ! texture - > ignore_mipmaps ) {
2017-03-05 16:44:50 +01:00
if ( ! had_mipmaps & & texture - > mipmaps = = 1 ) {
2016-10-03 21:33:42 +02:00
glGenerateMipmap ( texture - > target ) ;
}
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MIN_FILTER , config . use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
} else {
if ( texture - > flags & VS : : TEXTURE_FLAG_FILTER ) {
glTexParameteri ( texture - > target , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
2016-10-03 21:33:42 +02:00
}
}
if ( config . srgb_decode_supported & & texture - > srgb ) {
2017-03-05 16:44:50 +01:00
if ( texture - > flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , _TEXTURE_SRGB_DECODE_EXT , _DECODE_EXT ) ;
texture - > using_srgb = true ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , _TEXTURE_SRGB_DECODE_EXT , _SKIP_DECODE_EXT ) ;
texture - > using_srgb = false ;
2016-10-03 21:33:42 +02:00
}
}
2017-03-05 16:44:50 +01:00
if ( texture - > flags & VS : : TEXTURE_FLAG_FILTER ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ; // Linear Filtering
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ; // raw Filtering
2016-10-03 21:33:42 +02:00
}
}
uint32_t RasterizerStorageGLES3 : : texture_get_flags ( RID p_texture ) const {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! texture , 0 ) ;
2016-10-03 21:33:42 +02:00
return texture - > flags ;
}
Image : : Format RasterizerStorageGLES3 : : texture_get_format ( RID p_texture ) const {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! texture , Image : : FORMAT_L8 ) ;
2016-10-03 21:33:42 +02:00
return texture - > format ;
}
2018-06-26 13:59:26 +02:00
VisualServer : : TextureType RasterizerStorageGLES3 : : texture_get_type ( RID p_texture ) const {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2018-06-26 13:59:26 +02:00
ERR_FAIL_COND_V ( ! texture , VS : : TEXTURE_TYPE_2D ) ;
return texture - > type ;
}
2017-05-20 02:09:36 +02:00
uint32_t RasterizerStorageGLES3 : : texture_get_texid ( RID p_texture ) const {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2017-05-20 02:09:36 +02:00
ERR_FAIL_COND_V ( ! texture , 0 ) ;
return texture - > tex_id ;
}
2017-08-20 16:17:24 +02:00
void RasterizerStorageGLES3 : : texture_bind ( RID p_texture , uint32_t p_texture_no ) {
Texture * texture = texture_owner . getornull ( p_texture ) ;
ERR_FAIL_COND ( ! texture ) ;
glActiveTexture ( GL_TEXTURE0 + p_texture_no ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
}
2016-10-03 21:33:42 +02:00
uint32_t RasterizerStorageGLES3 : : texture_get_width ( RID p_texture ) const {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! texture , 0 ) ;
2016-10-03 21:33:42 +02:00
return texture - > width ;
}
uint32_t RasterizerStorageGLES3 : : texture_get_height ( RID p_texture ) const {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! texture , 0 ) ;
2016-10-03 21:33:42 +02:00
return texture - > height ;
}
2018-06-26 13:59:26 +02:00
uint32_t RasterizerStorageGLES3 : : texture_get_depth ( RID p_texture ) const {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2018-06-26 13:59:26 +02:00
ERR_FAIL_COND_V ( ! texture , 0 ) ;
return texture - > depth ;
}
void RasterizerStorageGLES3 : : texture_set_size_override ( RID p_texture , int p_width , int p_height , int p_depth ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! texture ) ;
ERR_FAIL_COND ( texture - > render_target ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_width < = 0 | | p_width > 16384 ) ;
ERR_FAIL_COND ( p_height < = 0 | | p_height > 16384 ) ;
2016-10-03 21:33:42 +02:00
//real texture size is in alloc width and height
2017-03-05 16:44:50 +01:00
texture - > width = p_width ;
texture - > height = p_height ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : texture_set_path ( RID p_texture , const String & p_path ) {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! texture ) ;
2017-03-05 16:44:50 +01:00
texture - > path = p_path ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
String RasterizerStorageGLES3 : : texture_get_path ( RID p_texture ) const {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! texture , String ( ) ) ;
2016-10-03 21:33:42 +02:00
return texture - > path ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : texture_debug_usage ( List < VS : : TextureInfo > * r_info ) {
2016-10-03 21:33:42 +02:00
List < RID > textures ;
texture_owner . get_owned_list ( & textures ) ;
2017-03-05 16:44:50 +01:00
for ( List < RID > : : Element * E = textures . front ( ) ; E ; E = E - > next ( ) ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Texture * t = texture_owner . getornull ( E - > get ( ) ) ;
2016-10-03 21:33:42 +02:00
if ( ! t )
continue ;
VS : : TextureInfo tinfo ;
2017-03-05 16:44:50 +01:00
tinfo . path = t - > path ;
tinfo . format = t - > format ;
2018-06-26 13:59:26 +02:00
tinfo . width = t - > alloc_width ;
tinfo . height = t - > alloc_height ;
2019-03-03 16:38:29 +01:00
tinfo . depth = t - > alloc_depth ;
2017-03-05 16:44:50 +01:00
tinfo . bytes = t - > total_data_size ;
2016-10-03 21:33:42 +02:00
r_info - > push_back ( tinfo ) ;
}
}
void RasterizerStorageGLES3 : : texture_set_shrink_all_x2_on_set_data ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
config . shrink_textures_x2 = p_enable ;
2016-10-03 21:33:42 +02:00
}
2016-12-23 04:37:38 +01:00
void RasterizerStorageGLES3 : : textures_keep_original ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
config . keep_original_textures = p_enable ;
2016-12-23 04:37:38 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : texture_set_detect_3d_callback ( RID p_texture , VisualServer : : TextureDetectCallback p_callback , void * p_userdata ) {
2017-02-06 04:38:39 +01:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2017-02-06 04:38:39 +01:00
ERR_FAIL_COND ( ! texture ) ;
2017-03-05 16:44:50 +01:00
texture - > detect_3d = p_callback ;
texture - > detect_3d_ud = p_userdata ;
2017-02-06 04:38:39 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : texture_set_detect_srgb_callback ( RID p_texture , VisualServer : : TextureDetectCallback p_callback , void * p_userdata ) {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2017-02-06 04:38:39 +01:00
ERR_FAIL_COND ( ! texture ) ;
2017-03-05 16:44:50 +01:00
texture - > detect_srgb = p_callback ;
texture - > detect_srgb_ud = p_userdata ;
2017-02-06 04:38:39 +01:00
}
2017-06-17 02:47:28 +02:00
void RasterizerStorageGLES3 : : texture_set_detect_normal_callback ( RID p_texture , VisualServer : : TextureDetectCallback p_callback , void * p_userdata ) {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2017-06-17 02:47:28 +02:00
ERR_FAIL_COND ( ! texture ) ;
texture - > detect_normal = p_callback ;
texture - > detect_normal_ud = p_userdata ;
}
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : texture_create_radiance_cubemap ( RID p_source , int p_resolution ) const {
2017-02-06 04:38:39 +01:00
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_source ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! texture , RID ( ) ) ;
2018-06-26 13:59:26 +02:00
ERR_FAIL_COND_V ( texture - > type ! = VS : : TEXTURE_TYPE_CUBEMAP , RID ( ) ) ;
2017-02-06 04:38:39 +01:00
2019-02-13 11:13:49 +01:00
bool use_float = config . framebuffer_half_float_supported ;
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
if ( p_resolution < 0 ) {
p_resolution = texture - > width ;
2016-10-21 12:27:13 +02:00
}
glBindVertexArray ( 0 ) ;
glDisable ( GL_CULL_FACE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_SCISSOR_TEST ) ;
glDisable ( GL_BLEND ) ;
2016-10-27 16:50:26 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2016-10-21 12:27:13 +02:00
glBindTexture ( texture - > target , texture - > tex_id ) ;
2016-10-30 01:48:09 +02:00
if ( config . srgb_decode_supported & & texture - > srgb & & ! texture - > using_srgb ) {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , _TEXTURE_SRGB_DECODE_EXT , _DECODE_EXT ) ;
texture - > using_srgb = true ;
2016-10-30 01:48:09 +02:00
# ifdef TOOLS_ENABLED
2017-03-05 16:44:50 +01:00
if ( ! ( texture - > flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) {
texture - > flags | = VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ;
2016-10-30 01:48:09 +02:00
//notify that texture must be set to linear beforehand, so it works in other platforms when exported
}
# endif
}
2016-10-27 16:50:26 +02:00
glActiveTexture ( GL_TEXTURE1 ) ;
2016-10-21 12:27:13 +02:00
GLuint new_cubemap ;
glGenTextures ( 1 , & new_cubemap ) ;
2016-10-27 16:50:26 +02:00
glBindTexture ( GL_TEXTURE_CUBE_MAP , new_cubemap ) ;
2016-10-21 12:27:13 +02:00
GLuint tmp_fb ;
glGenFramebuffers ( 1 , & tmp_fb ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb ) ;
2016-10-27 16:50:26 +02:00
int size = p_resolution ;
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
int lod = 0 ;
2016-10-21 12:27:13 +02:00
shaders . cubemap_filter . bind ( ) ;
2017-03-05 16:44:50 +01:00
int mipmaps = 6 ;
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
int mm_level = mipmaps ;
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2 ;
2016-10-27 16:50:26 +02:00
GLenum format = GL_RGBA ;
2017-03-05 16:44:50 +01:00
GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV ;
2016-10-27 16:50:26 +02:00
2017-03-05 16:44:50 +01:00
while ( mm_level ) {
2016-10-27 16:50:26 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 6 ; i + + ) {
glTexImage2D ( _cube_side_enum [ i ] , lod , internal_format , size , size , 0 , format , type , NULL ) ;
2016-10-27 16:50:26 +02:00
}
lod + + ;
mm_level - - ;
2017-03-05 16:44:50 +01:00
if ( size > 1 )
size > > = 1 ;
2016-10-27 16:50:26 +02:00
}
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_BASE_LEVEL , 0 ) ;
2017-03-05 16:44:50 +01:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MAX_LEVEL , lod - 1 ) ;
2016-10-27 16:50:26 +02:00
2017-03-05 16:44:50 +01:00
lod = 0 ;
mm_level = mipmaps ;
2016-10-27 16:50:26 +02:00
size = p_resolution ;
2017-03-05 16:44:50 +01:00
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , false ) ;
2016-11-19 17:23:37 +01:00
2017-03-05 16:44:50 +01:00
while ( mm_level ) {
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 6 ; i + + ) {
2016-10-27 16:50:26 +02:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , _cube_side_enum [ i ] , new_cubemap , lod ) ;
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
glViewport ( 0 , 0 , size , size ) ;
2016-10-21 12:27:13 +02:00
glBindVertexArray ( resources . quadie_array ) ;
2017-03-05 16:44:50 +01:00
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : FACE_ID , i ) ;
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : ROUGHNESS , lod / float ( mipmaps - 1 ) ) ;
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
2016-10-21 12:27:13 +02:00
glBindVertexArray ( 0 ) ;
# ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
2016-10-21 12:27:13 +02:00
# endif
}
2017-03-05 16:44:50 +01:00
if ( size > 1 )
size > > = 1 ;
2016-10-21 12:27:13 +02:00
lod + + ;
mm_level - - ;
}
2016-10-27 16:50:26 +02:00
//restore ranges
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_BASE_LEVEL , 0 ) ;
2017-03-05 16:44:50 +01:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MAX_LEVEL , lod - 1 ) ;
2016-10-21 12:27:13 +02:00
2016-10-27 16:50:26 +02:00
glTexParameterf ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
2016-10-21 12:27:13 +02:00
2017-01-07 09:33:11 +01:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
2016-10-21 12:27:13 +02:00
glDeleteFramebuffers ( 1 , & tmp_fb ) ;
2017-03-05 16:44:50 +01:00
Texture * ctex = memnew ( Texture ) ;
2018-06-26 13:59:26 +02:00
ctex - > type = VS : : TEXTURE_TYPE_CUBEMAP ;
ctex - > flags = VS : : TEXTURE_FLAG_MIPMAPS | VS : : TEXTURE_FLAG_FILTER ;
2017-03-05 16:44:50 +01:00
ctex - > width = p_resolution ;
ctex - > height = p_resolution ;
ctex - > alloc_width = p_resolution ;
ctex - > alloc_height = p_resolution ;
ctex - > format = use_float ? Image : : FORMAT_RGBAH : Image : : FORMAT_RGBA8 ;
ctex - > target = GL_TEXTURE_CUBE_MAP ;
ctex - > gl_format_cache = format ;
ctex - > gl_internal_format_cache = internal_format ;
ctex - > gl_type_cache = type ;
ctex - > data_size = 0 ;
ctex - > compressed = false ;
ctex - > srgb = false ;
ctex - > total_data_size = 0 ;
ctex - > ignore_mipmaps = false ;
ctex - > mipmaps = mipmaps ;
ctex - > active = true ;
ctex - > tex_id = new_cubemap ;
ctex - > stored_cube_sides = ( 1 < < 6 ) - 1 ;
ctex - > render_target = NULL ;
2016-10-27 16:50:26 +02:00
return texture_owner . make_rid ( ctex ) ;
2016-10-21 12:27:13 +02:00
}
2016-10-03 21:33:42 +02:00
2019-01-27 20:57:05 +01:00
Size2 RasterizerStorageGLES3 : : texture_size_with_proxy ( RID p_texture ) const {
const Texture * texture = texture_owner . getornull ( p_texture ) ;
ERR_FAIL_COND_V ( ! texture , Size2 ( ) ) ;
if ( texture - > proxy ) {
return Size2 ( texture - > proxy - > width , texture - > proxy - > height ) ;
} else {
return Size2 ( texture - > width , texture - > height ) ;
}
}
2017-12-04 19:55:20 +01:00
void RasterizerStorageGLES3 : : texture_set_proxy ( RID p_texture , RID p_proxy ) {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2017-12-04 19:55:20 +01:00
ERR_FAIL_COND ( ! texture ) ;
if ( texture - > proxy ) {
texture - > proxy - > proxy_owners . erase ( texture ) ;
texture - > proxy = NULL ;
}
if ( p_proxy . is_valid ( ) ) {
2019-06-10 17:38:51 +02:00
Texture * proxy = texture_owner . getornull ( p_proxy ) ;
2017-12-04 19:55:20 +01:00
ERR_FAIL_COND ( ! proxy ) ;
ERR_FAIL_COND ( proxy = = texture ) ;
proxy - > proxy_owners . insert ( texture ) ;
texture - > proxy = proxy ;
}
}
2018-07-16 16:43:26 +02:00
void RasterizerStorageGLES3 : : texture_set_force_redraw_if_visible ( RID p_texture , bool p_enable ) {
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_texture ) ;
2018-07-16 16:43:26 +02:00
ERR_FAIL_COND ( ! texture ) ;
texture - > redraw_if_visible = p_enable ;
}
2017-05-25 18:53:59 +02:00
RID RasterizerStorageGLES3 : : sky_create ( ) {
2016-11-19 17:23:37 +01:00
2017-05-25 18:53:59 +02:00
Sky * sky = memnew ( Sky ) ;
sky - > radiance = 0 ;
2019-11-17 01:56:34 +01:00
sky - > irradiance = 0 ;
2017-05-25 18:53:59 +02:00
return sky_owner . make_rid ( sky ) ;
2016-11-19 17:23:37 +01:00
}
2017-05-25 18:53:59 +02:00
void RasterizerStorageGLES3 : : sky_set_texture ( RID p_sky , RID p_panorama , int p_radiance_size ) {
2016-11-19 17:23:37 +01:00
2017-05-25 18:53:59 +02:00
Sky * sky = sky_owner . getornull ( p_sky ) ;
ERR_FAIL_COND ( ! sky ) ;
2016-11-19 17:23:37 +01:00
2017-05-25 18:53:59 +02:00
if ( sky - > panorama . is_valid ( ) ) {
sky - > panorama = RID ( ) ;
glDeleteTextures ( 1 , & sky - > radiance ) ;
2019-11-17 01:56:34 +01:00
glDeleteTextures ( 1 , & sky - > irradiance ) ;
2017-05-25 18:53:59 +02:00
sky - > radiance = 0 ;
2019-11-17 01:56:34 +01:00
sky - > irradiance = 0 ;
2016-11-19 17:23:37 +01:00
}
2017-05-25 18:53:59 +02:00
sky - > panorama = p_panorama ;
if ( ! sky - > panorama . is_valid ( ) )
2016-11-19 17:23:37 +01:00
return ; //cleared
2017-05-25 18:53:59 +02:00
Texture * texture = texture_owner . getornull ( sky - > panorama ) ;
if ( ! texture ) {
sky - > panorama = RID ( ) ;
ERR_FAIL_COND ( ! texture ) ;
2016-11-19 17:23:37 +01:00
}
2018-05-19 04:37:26 +02:00
texture = texture - > get_ptr ( ) ; //resolve for proxies
2016-11-19 17:23:37 +01:00
glBindVertexArray ( 0 ) ;
glDisable ( GL_CULL_FACE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_SCISSOR_TEST ) ;
glDisable ( GL_BLEND ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
2019-11-28 07:12:19 +01:00
glTexParameteri ( texture - > target , GL_TEXTURE_BASE_LEVEL , 0 ) ;
# ifdef GLES_OVER_GL
glTexParameteri ( texture - > target , GL_TEXTURE_MAX_LEVEL , int ( Math : : floor ( Math : : log ( float ( texture - > width ) ) / Math : : log ( 2.0f ) ) ) ) ;
2019-11-17 01:56:34 +01:00
glGenerateMipmap ( texture - > target ) ;
2019-11-28 07:12:19 +01:00
# else
glTexParameteri ( texture - > target , GL_TEXTURE_MAX_LEVEL , 0 ) ;
# endif
// Need Mipmaps regardless of whether they are set in import by user
2019-11-17 01:56:34 +01:00
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
2019-11-28 07:12:19 +01:00
# ifdef GLES_OVER_GL
2019-11-17 01:56:34 +01:00
glTexParameterf ( texture - > target , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
2019-11-28 07:12:19 +01:00
# else
glTexParameterf ( texture - > target , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
# endif
2019-11-21 07:54:44 +01:00
glTexParameterf ( texture - > target , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2016-11-19 17:23:37 +01:00
if ( config . srgb_decode_supported & & texture - > srgb & & ! texture - > using_srgb ) {
2017-03-05 16:44:50 +01:00
glTexParameteri ( texture - > target , _TEXTURE_SRGB_DECODE_EXT , _DECODE_EXT ) ;
texture - > using_srgb = true ;
2016-11-19 17:23:37 +01:00
# ifdef TOOLS_ENABLED
2017-03-05 16:44:50 +01:00
if ( ! ( texture - > flags & VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ) ) {
texture - > flags | = VS : : TEXTURE_FLAG_CONVERT_TO_LINEAR ;
2016-11-19 17:23:37 +01:00
//notify that texture must be set to linear beforehand, so it works in other platforms when exported
}
# endif
}
2019-11-17 01:56:34 +01:00
{
//Irradiance map
glActiveTexture ( GL_TEXTURE1 ) ;
glGenTextures ( 1 , & sky - > irradiance ) ;
glBindTexture ( GL_TEXTURE_2D , sky - > irradiance ) ;
GLuint tmp_fb ;
glGenFramebuffers ( 1 , & tmp_fb ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb ) ;
2020-01-19 01:38:20 +01:00
int size = 32 ;
2019-11-17 01:56:34 +01:00
bool use_float = config . framebuffer_half_float_supported ;
GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2 ;
GLenum format = GL_RGBA ;
GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV ;
glTexImage2D ( GL_TEXTURE_2D , 0 , internal_format , size , size * 2 , 0 , format , type , NULL ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , 0 ) ;
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( texture - > target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , sky - > irradiance , 0 ) ;
2020-01-25 20:50:05 +01:00
int irradiance_size = GLOBAL_GET ( " rendering/quality/reflections/irradiance_max_size " ) ;
int upscale_size = MIN ( int ( previous_power_of_2 ( irradiance_size ) ) , p_radiance_size ) ;
2020-01-19 01:38:20 +01:00
GLuint tmp_fb2 ;
GLuint tmp_tex ;
{
//generate another one for rendering, as can't read and write from a single texarray it seems
glGenFramebuffers ( 1 , & tmp_fb2 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb2 ) ;
glGenTextures ( 1 , & tmp_tex ) ;
glBindTexture ( GL_TEXTURE_2D , tmp_tex ) ;
2020-01-25 20:50:05 +01:00
glTexImage2D ( GL_TEXTURE_2D , 0 , internal_format , upscale_size , 2.0 * upscale_size , 0 , format , type , NULL ) ;
2020-01-19 01:38:20 +01:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , tmp_tex , 0 ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
2020-01-22 15:18:53 +01:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2020-01-19 01:38:20 +01:00
# ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
# endif
}
2019-11-17 01:56:34 +01:00
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : COMPUTE_IRRADIANCE , true ) ;
shaders . cubemap_filter . bind ( ) ;
// Very large Panoramas require way too much effort to compute irradiance so use a mipmap
// level that corresponds to a panorama of 1024x512
2019-11-21 16:44:09 +01:00
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : SOURCE_MIP_LEVEL , MAX ( Math : : floor ( Math : : log ( float ( texture - > width ) ) / Math : : log ( 2.0f ) ) - 10.0f , 0.0f ) ) ;
2019-11-17 01:56:34 +01:00
2020-01-19 01:38:20 +01:00
// Compute Irradiance for a large texture, specified by radiance size and then pull out a low mipmap corresponding to 32x32
2019-11-17 01:56:34 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
2020-01-25 20:50:05 +01:00
glViewport ( 0 , i * upscale_size , upscale_size , upscale_size ) ;
2019-11-17 01:56:34 +01:00
glBindVertexArray ( resources . quadie_array ) ;
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : Z_FLIP , i > 0 ) ;
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
glBindVertexArray ( 0 ) ;
}
2020-01-19 01:38:20 +01:00
glGenerateMipmap ( GL_TEXTURE_2D ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , tmp_tex ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb ) ;
2019-11-17 01:56:34 +01:00
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , false ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , false ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : COMPUTE_IRRADIANCE , false ) ;
2020-01-19 01:38:20 +01:00
shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_LOD , true ) ;
shaders . copy . bind ( ) ;
2020-01-25 20:50:05 +01:00
shaders . copy . set_uniform ( CopyShaderGLES3 : : MIP_LEVEL , MAX ( Math : : floor ( Math : : log ( float ( upscale_size ) ) / Math : : log ( 2.0f ) ) - 5.0f , 0.0f ) ) ; // Mip level that corresponds to a 32x32 texture
2020-01-19 01:38:20 +01:00
glViewport ( 0 , 0 , size , size * 2.0 ) ;
glBindVertexArray ( resources . quadie_array ) ;
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
glBindVertexArray ( 0 ) ;
shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_LOD , false ) ;
2019-11-17 01:56:34 +01:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
2020-01-19 01:38:20 +01:00
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
2019-11-17 01:56:34 +01:00
glDeleteFramebuffers ( 1 , & tmp_fb ) ;
2020-01-19 01:38:20 +01:00
glDeleteFramebuffers ( 1 , & tmp_fb2 ) ;
glDeleteTextures ( 1 , & tmp_tex ) ;
2019-11-17 01:56:34 +01:00
}
// Now compute radiance
2016-11-19 17:23:37 +01:00
glActiveTexture ( GL_TEXTURE1 ) ;
2017-05-25 18:53:59 +02:00
glGenTextures ( 1 , & sky - > radiance ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
if ( config . use_texture_array_environment ) {
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
//texture3D
glBindTexture ( GL_TEXTURE_2D_ARRAY , sky - > radiance ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
GLuint tmp_fb ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
glGenFramebuffers ( 1 , & tmp_fb ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
int size = p_radiance_size ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
int array_level = 6 ;
2016-11-19 17:23:37 +01:00
2019-02-13 11:13:49 +01:00
bool use_float = config . framebuffer_half_float_supported ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2 ;
GLenum format = GL_RGBA ;
GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
glTexImage3D ( GL_TEXTURE_2D_ARRAY , 0 , internal_format , size , size * 2 , array_level , 0 , format , type , NULL ) ;
2016-11-19 17:23:37 +01:00
2019-11-17 01:56:34 +01:00
glTexParameterf ( GL_TEXTURE_2D_ARRAY , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D_ARRAY , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
GLuint tmp_fb2 ;
GLuint tmp_tex ;
{
//generate another one for rendering, as can't read and write from a single texarray it seems
glGenFramebuffers ( 1 , & tmp_fb2 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb2 ) ;
glGenTextures ( 1 , & tmp_tex ) ;
glBindTexture ( GL_TEXTURE_2D , tmp_tex ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , internal_format , size , size * 2 , 0 , format , type , NULL ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , tmp_tex , 0 ) ;
2019-11-17 01:56:34 +01:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
2017-07-05 04:52:23 +02:00
# ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
# endif
}
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
for ( int j = 0 ; j < array_level ; j + + ) {
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb2 ) ;
2016-11-19 17:23:37 +01:00
2019-11-28 07:12:19 +01:00
# ifdef GLES_OVER_GL
2019-11-17 01:56:34 +01:00
if ( j < 3 ) {
2019-11-28 07:12:19 +01:00
# else
if ( j = = 0 ) {
# endif
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_DUAL_PARABOLOID_ARRAY , false ) ;
shaders . cubemap_filter . bind ( ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
2019-11-17 01:56:34 +01:00
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : SOURCE_RESOLUTION , float ( texture - > width / 4 ) ) ;
2017-07-05 04:52:23 +02:00
} else {
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , false ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_DUAL_PARABOLOID_ARRAY , true ) ;
shaders . cubemap_filter . bind ( ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D_ARRAY , sky - > radiance ) ;
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : SOURCE_ARRAY_INDEX , j - 1 ) ; //read from previous to ensure better blur
}
for ( int i = 0 ; i < 2 ; i + + ) {
glViewport ( 0 , i * size , size , size ) ;
glBindVertexArray ( resources . quadie_array ) ;
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : Z_FLIP , i > 0 ) ;
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : ROUGHNESS , j / float ( array_level - 1 ) ) ;
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
glBindVertexArray ( 0 ) ;
}
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , tmp_fb ) ;
glFramebufferTextureLayer ( GL_DRAW_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , sky - > radiance , 0 , j ) ;
glBindFramebuffer ( GL_READ_FRAMEBUFFER , tmp_fb2 ) ;
glReadBuffer ( GL_COLOR_ATTACHMENT0 ) ;
glBlitFramebuffer ( 0 , 0 , size , size * 2 , 0 , 0 , size , size * 2 , GL_COLOR_BUFFER_BIT , GL_NEAREST ) ;
glBindFramebuffer ( GL_READ_FRAMEBUFFER , 0 ) ;
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , 0 ) ;
}
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , false ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , false ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_DUAL_PARABOLOID_ARRAY , false ) ;
//restore ranges
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D_ARRAY , sky - > radiance ) ;
glGenerateMipmap ( GL_TEXTURE_2D_ARRAY ) ;
glTexParameterf ( GL_TEXTURE_2D_ARRAY , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D_ARRAY , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2017-07-06 00:36:56 +02:00
glTexParameterf ( GL_TEXTURE_2D_ARRAY , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D_ARRAY , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2017-07-05 04:52:23 +02:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
glDeleteFramebuffers ( 1 , & tmp_fb ) ;
glDeleteFramebuffers ( 1 , & tmp_fb2 ) ;
glDeleteTextures ( 1 , & tmp_tex ) ;
} else {
//regular single texture with mipmaps
glBindTexture ( GL_TEXTURE_2D , sky - > radiance ) ;
GLuint tmp_fb ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
glGenFramebuffers ( 1 , & tmp_fb ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb ) ;
int size = p_radiance_size ;
int lod = 0 ;
int mipmaps = 6 ;
int mm_level = mipmaps ;
2019-02-13 11:13:49 +01:00
bool use_float = config . framebuffer_half_float_supported ;
2017-07-05 04:52:23 +02:00
GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2 ;
GLenum format = GL_RGBA ;
GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV ;
2017-07-22 19:07:38 +02:00
glTexStorage2DCustom ( GL_TEXTURE_2D , mipmaps , internal_format , size , size * 2.0 , format , type ) ;
2017-07-05 04:52:23 +02:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
2017-07-22 19:07:38 +02:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , mipmaps - 1 ) ;
2019-11-17 01:56:34 +01:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
GLuint tmp_fb2 ;
GLuint tmp_tex ;
{
// Need a temporary framebuffer for rendering so we can read from previous iterations
glGenFramebuffers ( 1 , & tmp_fb2 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb2 ) ;
glGenTextures ( 1 , & tmp_tex ) ;
glBindTexture ( GL_TEXTURE_2D , tmp_tex ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , internal_format , size , size * 2 , 0 , format , type , NULL ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , tmp_tex , 0 ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
# ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
# endif
}
2017-07-05 04:52:23 +02:00
lod = 0 ;
mm_level = mipmaps ;
size = p_radiance_size ;
while ( mm_level ) {
2019-11-17 01:56:34 +01:00
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb ) ;
2017-07-05 04:52:23 +02:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , sky - > radiance , lod ) ;
2019-11-17 01:56:34 +01:00
2016-11-19 17:23:37 +01:00
# ifdef DEBUG_ENABLED
2017-07-05 04:52:23 +02:00
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
ERR_CONTINUE ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
2016-11-19 17:23:37 +01:00
# endif
2019-11-17 01:56:34 +01:00
glBindTexture ( GL_TEXTURE_2D , tmp_tex ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , internal_format , size , size * 2 , 0 , format , type , NULL ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , tmp_fb2 ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , tmp_tex , 0 ) ;
2019-11-28 07:12:19 +01:00
# ifdef GLES_OVER_GL
2019-11-17 01:56:34 +01:00
if ( lod < 3 ) {
2019-11-28 07:12:19 +01:00
# else
if ( lod = = 0 ) {
# endif
2019-11-17 01:56:34 +01:00
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_DUAL_PARABOLOID , false ) ;
shaders . cubemap_filter . bind ( ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( texture - > target , texture - > tex_id ) ;
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : SOURCE_RESOLUTION , float ( texture - > width / 4 ) ) ;
} else {
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , true ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , false ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_DUAL_PARABOLOID , true ) ;
shaders . cubemap_filter . bind ( ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , sky - > radiance ) ;
2019-11-21 07:54:44 +01:00
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : SOURCE_MIP_LEVEL , float ( lod - 1 ) ) ; //read from previous to ensure better blur
2019-11-17 01:56:34 +01:00
}
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
for ( int i = 0 ; i < 2 ; i + + ) {
glViewport ( 0 , i * size , size , size ) ;
glBindVertexArray ( resources . quadie_array ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : Z_FLIP , i > 0 ) ;
shaders . cubemap_filter . set_uniform ( CubemapFilterShaderGLES3 : : ROUGHNESS , lod / float ( mipmaps - 1 ) ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
glBindVertexArray ( 0 ) ;
}
2016-11-19 17:23:37 +01:00
2019-11-17 01:56:34 +01:00
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , tmp_fb ) ;
glFramebufferTextureLayer ( GL_DRAW_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , sky - > radiance , 0 , lod ) ;
glBindFramebuffer ( GL_READ_FRAMEBUFFER , tmp_fb2 ) ;
glReadBuffer ( GL_COLOR_ATTACHMENT0 ) ;
glBlitFramebuffer ( 0 , 0 , size , size * 2 , 0 , 0 , size , size * 2 , GL_COLOR_BUFFER_BIT , GL_NEAREST ) ;
glBindFramebuffer ( GL_READ_FRAMEBUFFER , 0 ) ;
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , 0 ) ;
2017-07-05 04:52:23 +02:00
if ( size > 1 )
size > > = 1 ;
lod + + ;
mm_level - - ;
}
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_DUAL_PARABOLOID , false ) ;
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : USE_SOURCE_PANORAMA , false ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
//restore ranges
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , lod - 1 ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2016-11-19 17:23:37 +01:00
2017-07-05 04:52:23 +02:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
glDeleteFramebuffers ( 1 , & tmp_fb ) ;
2019-11-17 01:56:34 +01:00
glDeleteFramebuffers ( 1 , & tmp_fb2 ) ;
glDeleteTextures ( 1 , & tmp_tex ) ;
2017-07-05 04:52:23 +02:00
}
2016-11-19 17:23:37 +01:00
}
2016-10-03 21:33:42 +02:00
/* SHADER API */
2017-04-07 04:36:37 +02:00
RID RasterizerStorageGLES3 : : shader_create ( ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Shader * shader = memnew ( Shader ) ;
2017-04-07 04:36:37 +02:00
shader - > mode = VS : : SHADER_SPATIAL ;
shader - > shader = & scene - > state . scene_shader ;
2016-10-10 23:31:01 +02:00
RID rid = shader_owner . make_rid ( shader ) ;
_shader_make_dirty ( shader ) ;
2017-03-05 16:44:50 +01:00
shader - > self = rid ;
2016-10-10 23:31:01 +02:00
return rid ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : _shader_make_dirty ( Shader * p_shader ) {
2016-10-10 23:31:01 +02:00
if ( p_shader - > dirty_list . in_list ( ) )
return ;
_shader_dirty_list . add ( & p_shader - > dirty_list ) ;
2016-10-03 21:33:42 +02:00
}
2017-04-07 04:36:37 +02:00
void RasterizerStorageGLES3 : : shader_set_code ( RID p_shader , const String & p_code ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Shader * shader = shader_owner . getornull ( p_shader ) ;
2016-10-10 23:31:01 +02:00
ERR_FAIL_COND ( ! shader ) ;
2017-04-07 04:36:37 +02:00
shader - > code = p_code ;
String mode_string = ShaderLanguage : : get_shader_type ( p_code ) ;
VS : : ShaderMode mode ;
2016-10-10 23:31:01 +02:00
2017-04-07 04:36:37 +02:00
if ( mode_string = = " canvas_item " )
mode = VS : : SHADER_CANVAS_ITEM ;
else if ( mode_string = = " particles " )
mode = VS : : SHADER_PARTICLES ;
else
mode = VS : : SHADER_SPATIAL ;
if ( shader - > custom_code_id & & mode ! = shader - > mode ) {
2016-10-10 23:31:01 +02:00
shader - > shader - > free_custom_shader ( shader - > custom_code_id ) ;
2017-03-05 16:44:50 +01:00
shader - > custom_code_id = 0 ;
2016-10-10 23:31:01 +02:00
}
2017-04-07 04:36:37 +02:00
shader - > mode = mode ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
ShaderGLES3 * shaders [ VS : : SHADER_MAX ] = {
2016-10-19 16:14:41 +02:00
& scene - > state . scene_shader ,
2016-10-10 23:31:01 +02:00
& canvas - > state . canvas_shader ,
2017-01-02 02:16:52 +01:00
& this - > shaders . particles ,
2016-10-10 23:31:01 +02:00
} ;
2017-04-07 04:36:37 +02:00
shader - > shader = shaders [ mode ] ;
2016-10-03 21:33:42 +02:00
2017-04-07 04:36:37 +02:00
if ( shader - > custom_code_id = = 0 ) {
shader - > custom_code_id = shader - > shader - > create_custom_shader ( ) ;
}
2016-10-03 21:33:42 +02:00
2016-10-10 23:31:01 +02:00
_shader_make_dirty ( shader ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
String RasterizerStorageGLES3 : : shader_get_code ( RID p_shader ) const {
2016-10-10 23:31:01 +02:00
2019-06-10 17:38:51 +02:00
const Shader * shader = shader_owner . getornull ( p_shader ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! shader , String ( ) ) ;
2016-10-10 23:31:01 +02:00
return shader - > code ;
2016-10-03 21:33:42 +02:00
}
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : _update_shader ( Shader * p_shader ) const {
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
_shader_dirty_list . remove ( & p_shader - > dirty_list ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
p_shader - > valid = false ;
2017-06-13 00:23:37 +02:00
p_shader - > ubo_size = 0 ;
2016-10-10 23:31:01 +02:00
p_shader - > uniforms . clear ( ) ;
2018-11-14 14:57:43 +01:00
if ( p_shader - > code = = String ( ) ) {
return ; //just invalid, but no error
}
2016-10-10 23:31:01 +02:00
ShaderCompilerGLES3 : : GeneratedCode gen_code ;
2017-03-05 16:44:50 +01:00
ShaderCompilerGLES3 : : IdentifierActions * actions = NULL ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
switch ( p_shader - > mode ) {
2016-10-10 23:31:01 +02:00
case VS : : SHADER_CANVAS_ITEM : {
2017-03-05 16:44:50 +01:00
p_shader - > canvas_item . light_mode = Shader : : CanvasItem : : LIGHT_MODE_NORMAL ;
p_shader - > canvas_item . blend_mode = Shader : : CanvasItem : : BLEND_MODE_MIX ;
2017-06-27 03:58:03 +02:00
p_shader - > canvas_item . uses_screen_texture = false ;
p_shader - > canvas_item . uses_screen_uv = false ;
2017-09-23 22:27:29 +02:00
p_shader - > canvas_item . uses_time = false ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
shaders . actions_canvas . render_mode_values [ " blend_add " ] = Pair < int * , int > ( & p_shader - > canvas_item . blend_mode , Shader : : CanvasItem : : BLEND_MODE_ADD ) ;
shaders . actions_canvas . render_mode_values [ " blend_mix " ] = Pair < int * , int > ( & p_shader - > canvas_item . blend_mode , Shader : : CanvasItem : : BLEND_MODE_MIX ) ;
shaders . actions_canvas . render_mode_values [ " blend_sub " ] = Pair < int * , int > ( & p_shader - > canvas_item . blend_mode , Shader : : CanvasItem : : BLEND_MODE_SUB ) ;
shaders . actions_canvas . render_mode_values [ " blend_mul " ] = Pair < int * , int > ( & p_shader - > canvas_item . blend_mode , Shader : : CanvasItem : : BLEND_MODE_MUL ) ;
shaders . actions_canvas . render_mode_values [ " blend_premul_alpha " ] = Pair < int * , int > ( & p_shader - > canvas_item . blend_mode , Shader : : CanvasItem : : BLEND_MODE_PMALPHA ) ;
2018-05-07 13:24:29 +02:00
shaders . actions_canvas . render_mode_values [ " blend_disabled " ] = Pair < int * , int > ( & p_shader - > canvas_item . blend_mode , Shader : : CanvasItem : : BLEND_MODE_DISABLED ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
shaders . actions_canvas . render_mode_values [ " unshaded " ] = Pair < int * , int > ( & p_shader - > canvas_item . light_mode , Shader : : CanvasItem : : LIGHT_MODE_UNSHADED ) ;
shaders . actions_canvas . render_mode_values [ " light_only " ] = Pair < int * , int > ( & p_shader - > canvas_item . light_mode , Shader : : CanvasItem : : LIGHT_MODE_LIGHT_ONLY ) ;
2016-10-10 23:31:01 +02:00
2017-06-27 03:58:03 +02:00
shaders . actions_canvas . usage_flag_pointers [ " SCREEN_UV " ] = & p_shader - > canvas_item . uses_screen_uv ;
shaders . actions_canvas . usage_flag_pointers [ " SCREEN_PIXEL_SIZE " ] = & p_shader - > canvas_item . uses_screen_uv ;
shaders . actions_canvas . usage_flag_pointers [ " SCREEN_TEXTURE " ] = & p_shader - > canvas_item . uses_screen_texture ;
2017-09-05 05:30:39 +02:00
shaders . actions_canvas . usage_flag_pointers [ " TIME " ] = & p_shader - > canvas_item . uses_time ;
2017-06-27 03:58:03 +02:00
2017-03-05 16:44:50 +01:00
actions = & shaders . actions_canvas ;
actions - > uniforms = & p_shader - > uniforms ;
2016-10-10 23:31:01 +02:00
} break ;
2016-10-19 16:14:41 +02:00
case VS : : SHADER_SPATIAL : {
2017-03-05 16:44:50 +01:00
p_shader - > spatial . blend_mode = Shader : : Spatial : : BLEND_MODE_MIX ;
p_shader - > spatial . depth_draw_mode = Shader : : Spatial : : DEPTH_DRAW_OPAQUE ;
p_shader - > spatial . cull_mode = Shader : : Spatial : : CULL_MODE_BACK ;
p_shader - > spatial . uses_alpha = false ;
2017-08-08 22:23:44 +02:00
p_shader - > spatial . uses_alpha_scissor = false ;
2017-03-05 16:44:50 +01:00
p_shader - > spatial . uses_discard = false ;
p_shader - > spatial . unshaded = false ;
2017-09-01 17:56:52 +02:00
p_shader - > spatial . no_depth_test = false ;
2017-03-05 16:44:50 +01:00
p_shader - > spatial . uses_sss = false ;
2017-09-23 22:27:29 +02:00
p_shader - > spatial . uses_time = false ;
2017-07-22 19:07:38 +02:00
p_shader - > spatial . uses_vertex_lighting = false ;
2017-06-06 03:33:01 +02:00
p_shader - > spatial . uses_screen_texture = false ;
2018-01-06 21:38:39 +01:00
p_shader - > spatial . uses_depth_texture = false ;
2017-03-05 16:44:50 +01:00
p_shader - > spatial . uses_vertex = false ;
2017-04-07 04:36:37 +02:00
p_shader - > spatial . writes_modelview_or_projection = false ;
2017-12-01 12:42:57 +01:00
p_shader - > spatial . uses_world_coordinates = false ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
shaders . actions_scene . render_mode_values [ " blend_add " ] = Pair < int * , int > ( & p_shader - > spatial . blend_mode , Shader : : Spatial : : BLEND_MODE_ADD ) ;
shaders . actions_scene . render_mode_values [ " blend_mix " ] = Pair < int * , int > ( & p_shader - > spatial . blend_mode , Shader : : Spatial : : BLEND_MODE_MIX ) ;
shaders . actions_scene . render_mode_values [ " blend_sub " ] = Pair < int * , int > ( & p_shader - > spatial . blend_mode , Shader : : Spatial : : BLEND_MODE_SUB ) ;
shaders . actions_scene . render_mode_values [ " blend_mul " ] = Pair < int * , int > ( & p_shader - > spatial . blend_mode , Shader : : Spatial : : BLEND_MODE_MUL ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
shaders . actions_scene . render_mode_values [ " depth_draw_opaque " ] = Pair < int * , int > ( & p_shader - > spatial . depth_draw_mode , Shader : : Spatial : : DEPTH_DRAW_OPAQUE ) ;
shaders . actions_scene . render_mode_values [ " depth_draw_always " ] = Pair < int * , int > ( & p_shader - > spatial . depth_draw_mode , Shader : : Spatial : : DEPTH_DRAW_ALWAYS ) ;
shaders . actions_scene . render_mode_values [ " depth_draw_never " ] = Pair < int * , int > ( & p_shader - > spatial . depth_draw_mode , Shader : : Spatial : : DEPTH_DRAW_NEVER ) ;
shaders . actions_scene . render_mode_values [ " depth_draw_alpha_prepass " ] = Pair < int * , int > ( & p_shader - > spatial . depth_draw_mode , Shader : : Spatial : : DEPTH_DRAW_ALPHA_PREPASS ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
shaders . actions_scene . render_mode_values [ " cull_front " ] = Pair < int * , int > ( & p_shader - > spatial . cull_mode , Shader : : Spatial : : CULL_MODE_FRONT ) ;
shaders . actions_scene . render_mode_values [ " cull_back " ] = Pair < int * , int > ( & p_shader - > spatial . cull_mode , Shader : : Spatial : : CULL_MODE_BACK ) ;
shaders . actions_scene . render_mode_values [ " cull_disabled " ] = Pair < int * , int > ( & p_shader - > spatial . cull_mode , Shader : : Spatial : : CULL_MODE_DISABLED ) ;
2016-10-27 16:50:26 +02:00
2017-03-05 16:44:50 +01:00
shaders . actions_scene . render_mode_flags [ " unshaded " ] = & p_shader - > spatial . unshaded ;
2017-09-01 17:56:52 +02:00
shaders . actions_scene . render_mode_flags [ " depth_test_disable " ] = & p_shader - > spatial . no_depth_test ;
2016-10-27 16:50:26 +02:00
2017-07-22 19:07:38 +02:00
shaders . actions_scene . render_mode_flags [ " vertex_lighting " ] = & p_shader - > spatial . uses_vertex_lighting ;
2017-12-01 12:42:57 +01:00
shaders . actions_scene . render_mode_flags [ " world_vertex_coords " ] = & p_shader - > spatial . uses_world_coordinates ;
2017-03-05 16:44:50 +01:00
shaders . actions_scene . usage_flag_pointers [ " ALPHA " ] = & p_shader - > spatial . uses_alpha ;
2017-08-08 22:23:44 +02:00
shaders . actions_scene . usage_flag_pointers [ " ALPHA_SCISSOR " ] = & p_shader - > spatial . uses_alpha_scissor ;
2016-12-03 02:23:16 +01:00
2017-03-05 16:44:50 +01:00
shaders . actions_scene . usage_flag_pointers [ " SSS_STRENGTH " ] = & p_shader - > spatial . uses_sss ;
shaders . actions_scene . usage_flag_pointers [ " DISCARD " ] = & p_shader - > spatial . uses_discard ;
2017-06-06 03:33:01 +02:00
shaders . actions_scene . usage_flag_pointers [ " SCREEN_TEXTURE " ] = & p_shader - > spatial . uses_screen_texture ;
2018-01-06 21:38:39 +01:00
shaders . actions_scene . usage_flag_pointers [ " DEPTH_TEXTURE " ] = & p_shader - > spatial . uses_depth_texture ;
2017-09-05 05:30:39 +02:00
shaders . actions_scene . usage_flag_pointers [ " TIME " ] = & p_shader - > spatial . uses_time ;
2016-10-19 16:14:41 +02:00
2017-04-07 04:36:37 +02:00
shaders . actions_scene . write_flag_pointers [ " MODELVIEW_MATRIX " ] = & p_shader - > spatial . writes_modelview_or_projection ;
shaders . actions_scene . write_flag_pointers [ " PROJECTION_MATRIX " ] = & p_shader - > spatial . writes_modelview_or_projection ;
2017-12-01 12:42:57 +01:00
shaders . actions_scene . write_flag_pointers [ " VERTEX " ] = & p_shader - > spatial . uses_vertex ;
2017-04-07 04:36:37 +02:00
2017-03-05 16:44:50 +01:00
actions = & shaders . actions_scene ;
actions - > uniforms = & p_shader - > uniforms ;
2016-10-19 16:14:41 +02:00
2017-02-06 04:38:39 +01:00
} break ;
2017-01-02 02:16:52 +01:00
case VS : : SHADER_PARTICLES : {
2017-03-05 16:44:50 +01:00
actions = & shaders . actions_particles ;
actions - > uniforms = & p_shader - > uniforms ;
2017-02-06 04:38:39 +01:00
} break ;
2018-12-29 13:16:04 +01:00
case VS : : SHADER_MAX :
break ; // Can't happen, but silences warning
2016-10-10 23:31:01 +02:00
}
2017-03-05 16:44:50 +01:00
Error err = shaders . compiler . compile ( p_shader - > mode , p_shader - > code , actions , p_shader - > path , gen_code ) ;
2019-10-02 09:50:22 +02:00
if ( err ! = OK ) {
return ;
}
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
p_shader - > shader - > set_custom_shader_code ( p_shader - > custom_code_id , gen_code . vertex , gen_code . vertex_global , gen_code . fragment , gen_code . light , gen_code . fragment_global , gen_code . uniforms , gen_code . texture_uniforms , gen_code . defines ) ;
2016-10-27 16:50:26 +02:00
2017-03-05 16:44:50 +01:00
p_shader - > ubo_size = gen_code . uniform_total_size ;
p_shader - > ubo_offsets = gen_code . uniform_offsets ;
p_shader - > texture_count = gen_code . texture_uniforms . size ( ) ;
p_shader - > texture_hints = gen_code . texture_hints ;
2018-06-26 13:59:26 +02:00
p_shader - > texture_types = gen_code . texture_types ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
p_shader - > uses_vertex_time = gen_code . uses_vertex_time ;
p_shader - > uses_fragment_time = gen_code . uses_fragment_time ;
2016-11-10 03:55:06 +01:00
2016-10-10 23:31:01 +02:00
//all materials using this shader will have to be invalidated, unfortunately
2017-03-05 16:44:50 +01:00
for ( SelfList < Material > * E = p_shader - > materials . first ( ) ; E ; E = E - > next ( ) ) {
2016-10-10 23:31:01 +02:00
_material_make_dirty ( E - > self ( ) ) ;
}
2017-03-05 16:44:50 +01:00
p_shader - > valid = true ;
2016-10-10 23:31:01 +02:00
p_shader - > version + + ;
}
void RasterizerStorageGLES3 : : update_dirty_shaders ( ) {
2017-03-05 16:44:50 +01:00
while ( _shader_dirty_list . first ( ) ) {
_update_shader ( _shader_dirty_list . first ( ) - > self ( ) ) ;
2016-10-10 23:31:01 +02:00
}
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : shader_get_param_list ( RID p_shader , List < PropertyInfo > * p_param_list ) const {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Shader * shader = shader_owner . getornull ( p_shader ) ;
2016-10-10 23:31:01 +02:00
ERR_FAIL_COND ( ! shader ) ;
if ( shader - > dirty_list . in_list ( ) )
_update_shader ( shader ) ; // ok should be not anymore dirty
2017-03-05 16:44:50 +01:00
Map < int , StringName > order ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( Map < StringName , ShaderLanguage : : ShaderNode : : Uniform > : : Element * E = shader - > uniforms . front ( ) ; E ; E = E - > next ( ) ) {
2016-10-10 23:31:01 +02:00
2017-06-17 16:03:48 +02:00
if ( E - > get ( ) . texture_order > = 0 ) {
order [ E - > get ( ) . texture_order + 100000 ] = E - > key ( ) ;
} else {
order [ E - > get ( ) . order ] = E - > key ( ) ;
}
2016-10-10 23:31:01 +02:00
}
2017-03-05 16:44:50 +01:00
for ( Map < int , StringName > : : Element * E = order . front ( ) ; E ; E = E - > next ( ) ) {
2016-10-10 23:31:01 +02:00
PropertyInfo pi ;
2017-03-05 16:44:50 +01:00
ShaderLanguage : : ShaderNode : : Uniform & u = shader - > uniforms [ E - > get ( ) ] ;
pi . name = E - > get ( ) ;
switch ( u . type ) {
case ShaderLanguage : : TYPE_VOID : pi . type = Variant : : NIL ; break ;
case ShaderLanguage : : TYPE_BOOL : pi . type = Variant : : BOOL ; break ;
case ShaderLanguage : : TYPE_BVEC2 :
pi . type = Variant : : INT ;
pi . hint = PROPERTY_HINT_FLAGS ;
pi . hint_string = " x,y " ;
break ;
case ShaderLanguage : : TYPE_BVEC3 :
pi . type = Variant : : INT ;
pi . hint = PROPERTY_HINT_FLAGS ;
pi . hint_string = " x,y,z " ;
break ;
case ShaderLanguage : : TYPE_BVEC4 :
pi . type = Variant : : INT ;
pi . hint = PROPERTY_HINT_FLAGS ;
pi . hint_string = " x,y,z,w " ;
break ;
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_UINT :
case ShaderLanguage : : TYPE_INT : {
2017-03-05 16:44:50 +01:00
pi . type = Variant : : INT ;
if ( u . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_RANGE ) {
pi . hint = PROPERTY_HINT_RANGE ;
2019-08-25 14:11:04 +02:00
pi . hint_string = rtos ( u . hint_range [ 0 ] ) + " , " + rtos ( u . hint_range [ 1 ] ) + " , " + rtos ( u . hint_range [ 2 ] ) ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_IVEC2 :
case ShaderLanguage : : TYPE_IVEC3 :
case ShaderLanguage : : TYPE_IVEC4 :
case ShaderLanguage : : TYPE_UVEC2 :
case ShaderLanguage : : TYPE_UVEC3 :
case ShaderLanguage : : TYPE_UVEC4 : {
2017-03-05 16:44:50 +01:00
pi . type = Variant : : POOL_INT_ARRAY ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_FLOAT : {
2017-03-05 16:44:50 +01:00
pi . type = Variant : : REAL ;
if ( u . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_RANGE ) {
pi . hint = PROPERTY_HINT_RANGE ;
pi . hint_string = rtos ( u . hint_range [ 0 ] ) + " , " + rtos ( u . hint_range [ 1 ] ) + " , " + rtos ( u . hint_range [ 2 ] ) ;
2016-10-10 23:31:01 +02:00
}
} break ;
2017-03-05 16:44:50 +01:00
case ShaderLanguage : : TYPE_VEC2 : pi . type = Variant : : VECTOR2 ; break ;
case ShaderLanguage : : TYPE_VEC3 : pi . type = Variant : : VECTOR3 ; break ;
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_VEC4 : {
2017-03-05 16:44:50 +01:00
if ( u . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_COLOR ) {
pi . type = Variant : : COLOR ;
2016-10-10 23:31:01 +02:00
} else {
2017-03-05 16:44:50 +01:00
pi . type = Variant : : PLANE ;
2016-10-10 23:31:01 +02:00
}
} break ;
2017-03-05 16:44:50 +01:00
case ShaderLanguage : : TYPE_MAT2 : pi . type = Variant : : TRANSFORM2D ; break ;
case ShaderLanguage : : TYPE_MAT3 : pi . type = Variant : : BASIS ; break ;
case ShaderLanguage : : TYPE_MAT4 : pi . type = Variant : : TRANSFORM ; break ;
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_SAMPLER2D :
case ShaderLanguage : : TYPE_ISAMPLER2D :
case ShaderLanguage : : TYPE_USAMPLER2D : {
2017-03-05 16:44:50 +01:00
pi . type = Variant : : OBJECT ;
pi . hint = PROPERTY_HINT_RESOURCE_TYPE ;
2019-06-11 20:43:37 +02:00
pi . hint_string = " Texture2D " ;
2016-10-10 23:31:01 +02:00
} break ;
2018-09-26 13:13:56 +02:00
case ShaderLanguage : : TYPE_SAMPLER2DARRAY :
case ShaderLanguage : : TYPE_ISAMPLER2DARRAY :
case ShaderLanguage : : TYPE_USAMPLER2DARRAY : {
pi . type = Variant : : OBJECT ;
pi . hint = PROPERTY_HINT_RESOURCE_TYPE ;
pi . hint_string = " TextureArray " ;
} break ;
2018-06-26 13:59:26 +02:00
case ShaderLanguage : : TYPE_SAMPLER3D :
case ShaderLanguage : : TYPE_ISAMPLER3D :
case ShaderLanguage : : TYPE_USAMPLER3D : {
pi . type = Variant : : OBJECT ;
pi . hint = PROPERTY_HINT_RESOURCE_TYPE ;
pi . hint_string = " Texture3D " ;
} break ;
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_SAMPLERCUBE : {
2017-03-05 16:44:50 +01:00
pi . type = Variant : : OBJECT ;
pi . hint = PROPERTY_HINT_RESOURCE_TYPE ;
pi . hint_string = " CubeMap " ;
2016-10-10 23:31:01 +02:00
} break ;
} ;
p_param_list - > push_back ( pi ) ;
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : shader_set_default_texture_param ( RID p_shader , const StringName & p_name , RID p_texture ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Shader * shader = shader_owner . getornull ( p_shader ) ;
2016-10-10 23:31:01 +02:00
ERR_FAIL_COND ( ! shader ) ;
ERR_FAIL_COND ( p_texture . is_valid ( ) & & ! texture_owner . owns ( p_texture ) ) ;
if ( p_texture . is_valid ( ) )
2017-03-05 16:44:50 +01:00
shader - > default_textures [ p_name ] = p_texture ;
2016-10-10 23:31:01 +02:00
else
shader - > default_textures . erase ( p_name ) ;
2016-10-03 21:33:42 +02:00
2016-10-10 23:31:01 +02:00
_shader_make_dirty ( shader ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : shader_get_default_texture_param ( RID p_shader , const StringName & p_name ) const {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
const Shader * shader = shader_owner . getornull ( p_shader ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! shader , RID ( ) ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
const Map < StringName , RID > : : Element * E = shader - > default_textures . find ( p_name ) ;
2016-10-10 23:31:01 +02:00
if ( ! E )
return RID ( ) ;
return E - > get ( ) ;
2016-10-03 21:33:42 +02:00
}
/* COMMON MATERIAL API */
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : _material_make_dirty ( Material * p_material ) const {
2016-10-10 23:31:01 +02:00
if ( p_material - > dirty_list . in_list ( ) )
return ;
_material_dirty_list . add ( & p_material - > dirty_list ) ;
}
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : material_create ( ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Material * material = memnew ( Material ) ;
2016-10-10 23:31:01 +02:00
return material_owner . make_rid ( material ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : material_set_shader ( RID p_material , RID p_shader ) {
2016-10-10 23:31:01 +02:00
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2016-10-10 23:31:01 +02:00
ERR_FAIL_COND ( ! material ) ;
2017-03-05 16:44:50 +01:00
Shader * shader = shader_owner . getornull ( p_shader ) ;
2016-10-10 23:31:01 +02:00
if ( material - > shader ) {
//if shader, remove from previous shader material list
2017-03-05 16:44:50 +01:00
material - > shader - > materials . remove ( & material - > list ) ;
2016-10-10 23:31:01 +02:00
}
2017-03-05 16:44:50 +01:00
material - > shader = shader ;
2016-10-10 23:31:01 +02:00
if ( shader ) {
shader - > materials . add ( & material - > list ) ;
}
2016-10-03 21:33:42 +02:00
2016-10-10 23:31:01 +02:00
_material_make_dirty ( material ) ;
2016-10-03 21:33:42 +02:00
}
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : material_get_shader ( RID p_material ) const {
2016-10-10 23:31:01 +02:00
2019-06-10 17:38:51 +02:00
const Material * material = material_owner . getornull ( p_material ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! material , RID ( ) ) ;
2016-10-10 23:31:01 +02:00
if ( material - > shader )
return material - > shader - > self ;
2016-10-03 21:33:42 +02:00
return RID ( ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : material_set_param ( RID p_material , const StringName & p_param , const Variant & p_value ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2016-10-10 23:31:01 +02:00
ERR_FAIL_COND ( ! material ) ;
2017-03-05 16:44:50 +01:00
if ( p_value . get_type ( ) = = Variant : : NIL )
2016-10-10 23:31:01 +02:00
material - > params . erase ( p_param ) ;
else
2017-03-05 16:44:50 +01:00
material - > params [ p_param ] = p_value ;
2016-10-10 23:31:01 +02:00
_material_make_dirty ( material ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
Variant RasterizerStorageGLES3 : : material_get_param ( RID p_material , const StringName & p_param ) const {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
const Material * material = material_owner . getornull ( p_material ) ;
2018-02-24 09:58:17 +01:00
ERR_FAIL_COND_V ( ! material , Variant ( ) ) ;
2016-10-10 23:31:01 +02:00
if ( material - > params . has ( p_param ) )
return material - > params [ p_param ] ;
2018-09-05 00:54:35 +02:00
return material_get_param_default ( p_material , p_param ) ;
}
Variant RasterizerStorageGLES3 : : material_get_param_default ( RID p_material , const StringName & p_param ) const {
2019-06-10 17:38:51 +02:00
const Material * material = material_owner . getornull ( p_material ) ;
2018-09-05 00:54:35 +02:00
ERR_FAIL_COND_V ( ! material , Variant ( ) ) ;
if ( material - > shader ) {
if ( material - > shader - > uniforms . has ( p_param ) ) {
2018-11-16 12:20:23 +01:00
ShaderLanguage : : ShaderNode : : Uniform uniform = material - > shader - > uniforms [ p_param ] ;
Vector < ShaderLanguage : : ConstantNode : : Value > default_value = uniform . default_value ;
return ShaderLanguage : : constant_value_to_variant ( default_value , uniform . type , uniform . hint ) ;
2018-09-05 00:54:35 +02:00
}
}
2016-10-03 21:33:42 +02:00
return Variant ( ) ;
}
2016-10-30 01:48:09 +02:00
void RasterizerStorageGLES3 : : material_set_line_width ( RID p_material , float p_width ) {
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2016-10-30 01:48:09 +02:00
ERR_FAIL_COND ( ! material ) ;
2017-03-05 16:44:50 +01:00
material - > line_width = p_width ;
2016-10-30 01:48:09 +02:00
}
2017-07-08 17:34:05 +02:00
void RasterizerStorageGLES3 : : material_set_next_pass ( RID p_material , RID p_next_material ) {
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2017-07-08 17:34:05 +02:00
ERR_FAIL_COND ( ! material ) ;
material - > next_pass = p_next_material ;
}
2017-03-05 16:44:50 +01:00
bool RasterizerStorageGLES3 : : material_is_animated ( RID p_material ) {
2016-11-10 03:55:06 +01:00
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! material , false ) ;
2016-11-10 03:55:06 +01:00
if ( material - > dirty_list . in_list ( ) ) {
_update_material ( material ) ;
}
2017-07-08 17:34:05 +02:00
bool animated = material - > is_animated_cache ;
if ( ! animated & & material - > next_pass . is_valid ( ) ) {
animated = material_is_animated ( material - > next_pass ) ;
}
return animated ;
2016-11-10 03:55:06 +01:00
}
2017-03-05 16:44:50 +01:00
bool RasterizerStorageGLES3 : : material_casts_shadows ( RID p_material ) {
2016-11-10 03:55:06 +01:00
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! material , false ) ;
2016-11-10 03:55:06 +01:00
if ( material - > dirty_list . in_list ( ) ) {
_update_material ( material ) ;
}
2017-07-08 17:34:05 +02:00
bool casts_shadows = material - > can_cast_shadow_cache ;
if ( ! casts_shadows & & material - > next_pass . is_valid ( ) ) {
casts_shadows = material_casts_shadows ( material - > next_pass ) ;
}
return casts_shadows ;
2016-11-10 03:55:06 +01:00
}
void RasterizerStorageGLES3 : : material_add_instance_owner ( RID p_material , RasterizerScene : : InstanceBase * p_instance ) {
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! material ) ;
2017-03-05 16:44:50 +01:00
Map < RasterizerScene : : InstanceBase * , int > : : Element * E = material - > instance_owners . find ( p_instance ) ;
2016-11-10 03:55:06 +01:00
if ( E ) {
E - > get ( ) + + ;
} else {
2017-03-05 16:44:50 +01:00
material - > instance_owners [ p_instance ] = 1 ;
2016-11-10 03:55:06 +01:00
}
}
void RasterizerStorageGLES3 : : material_remove_instance_owner ( RID p_material , RasterizerScene : : InstanceBase * p_instance ) {
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! material ) ;
2017-03-05 16:44:50 +01:00
Map < RasterizerScene : : InstanceBase * , int > : : Element * E = material - > instance_owners . find ( p_instance ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! E ) ;
E - > get ( ) - - ;
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) = = 0 ) {
2016-11-10 03:55:06 +01:00
material - > instance_owners . erase ( E ) ;
}
}
2017-09-01 17:56:52 +02:00
void RasterizerStorageGLES3 : : material_set_render_priority ( RID p_material , int priority ) {
ERR_FAIL_COND ( priority < VS : : MATERIAL_RENDER_PRIORITY_MIN ) ;
ERR_FAIL_COND ( priority > VS : : MATERIAL_RENDER_PRIORITY_MAX ) ;
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_material ) ;
2017-09-01 17:56:52 +02:00
ERR_FAIL_COND ( ! material ) ;
material - > render_priority = priority ;
}
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ static void _fill_std140_variant_ubo_value ( ShaderLanguage : : DataType type , const Variant & value , uint8_t * data , bool p_linear_color ) {
switch ( type ) {
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_BOOL : {
bool v = value ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2016-10-10 23:31:01 +02:00
* gui = v ? GL_TRUE : GL_FALSE ;
} break ;
case ShaderLanguage : : TYPE_BVEC2 : {
int v = value ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2019-08-07 12:54:30 +02:00
gui [ 0 ] = ( v & 1 ) ? GL_TRUE : GL_FALSE ;
gui [ 1 ] = ( v & 2 ) ? GL_TRUE : GL_FALSE ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_BVEC3 : {
int v = value ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2019-07-07 23:08:51 +02:00
gui [ 0 ] = ( v & 1 ) ? GL_TRUE : GL_FALSE ;
gui [ 1 ] = ( v & 2 ) ? GL_TRUE : GL_FALSE ;
gui [ 2 ] = ( v & 4 ) ? GL_TRUE : GL_FALSE ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_BVEC4 : {
int v = value ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2019-07-07 23:08:51 +02:00
gui [ 0 ] = ( v & 1 ) ? GL_TRUE : GL_FALSE ;
gui [ 1 ] = ( v & 2 ) ? GL_TRUE : GL_FALSE ;
gui [ 2 ] = ( v & 4 ) ? GL_TRUE : GL_FALSE ;
gui [ 3 ] = ( v & 8 ) ? GL_TRUE : GL_FALSE ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_INT : {
int v = value ;
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
gui [ 0 ] = v ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_IVEC2 : {
2017-01-07 22:25:37 +01:00
PoolVector < int > iv = value ;
2016-10-10 23:31:01 +02:00
int s = iv . size ( ) ;
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = iv . read ( ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
if ( i < s )
gui [ i ] = r [ i ] ;
2016-10-10 23:31:01 +02:00
else
2017-03-05 16:44:50 +01:00
gui [ i ] = 0 ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_IVEC3 : {
2017-01-07 22:25:37 +01:00
PoolVector < int > iv = value ;
2016-10-10 23:31:01 +02:00
int s = iv . size ( ) ;
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = iv . read ( ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
if ( i < s )
gui [ i ] = r [ i ] ;
2016-10-10 23:31:01 +02:00
else
2017-03-05 16:44:50 +01:00
gui [ i ] = 0 ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_IVEC4 : {
2017-01-07 22:25:37 +01:00
PoolVector < int > iv = value ;
2016-10-10 23:31:01 +02:00
int s = iv . size ( ) ;
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = iv . read ( ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( i < s )
gui [ i ] = r [ i ] ;
2016-10-10 23:31:01 +02:00
else
2017-03-05 16:44:50 +01:00
gui [ i ] = 0 ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_UINT : {
int v = value ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
gui [ 0 ] = v ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_UVEC2 : {
2017-01-07 22:25:37 +01:00
PoolVector < int > iv = value ;
2016-10-10 23:31:01 +02:00
int s = iv . size ( ) ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2016-10-10 23:31:01 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = iv . read ( ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
if ( i < s )
gui [ i ] = r [ i ] ;
2016-10-10 23:31:01 +02:00
else
2017-03-05 16:44:50 +01:00
gui [ i ] = 0 ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_UVEC3 : {
2017-01-07 22:25:37 +01:00
PoolVector < int > iv = value ;
2016-10-10 23:31:01 +02:00
int s = iv . size ( ) ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2016-10-10 23:31:01 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = iv . read ( ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
if ( i < s )
gui [ i ] = r [ i ] ;
2016-10-10 23:31:01 +02:00
else
2017-03-05 16:44:50 +01:00
gui [ i ] = 0 ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_UVEC4 : {
2017-01-07 22:25:37 +01:00
PoolVector < int > iv = value ;
2016-10-10 23:31:01 +02:00
int s = iv . size ( ) ;
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2016-10-10 23:31:01 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = iv . read ( ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( i < s )
gui [ i ] = r [ i ] ;
2016-10-10 23:31:01 +02:00
else
2017-03-05 16:44:50 +01:00
gui [ i ] = 0 ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_FLOAT : {
float v = value ;
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
gui [ 0 ] = v ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_VEC2 : {
Vector2 v = value ;
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_VEC3 : {
Vector3 v = value ;
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_VEC4 : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
if ( value . get_type ( ) = = Variant : : COLOR ) {
Color v = value ;
2016-10-10 23:31:01 +02:00
2016-10-30 01:48:09 +02:00
if ( p_linear_color ) {
2017-03-05 16:44:50 +01:00
v = v . to_linear ( ) ;
2016-10-30 01:48:09 +02:00
}
2017-03-05 16:44:50 +01:00
gui [ 0 ] = v . r ;
gui [ 1 ] = v . g ;
gui [ 2 ] = v . b ;
gui [ 3 ] = v . a ;
} else if ( value . get_type ( ) = = Variant : : RECT2 ) {
Rect2 v = value ;
2017-06-04 00:25:13 +02:00
gui [ 0 ] = v . position . x ;
gui [ 1 ] = v . position . y ;
2017-03-05 16:44:50 +01:00
gui [ 2 ] = v . size . x ;
gui [ 3 ] = v . size . y ;
} else if ( value . get_type ( ) = = Variant : : QUAT ) {
Quat v = value ;
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
gui [ 3 ] = v . w ;
2016-10-10 23:31:01 +02:00
} else {
2017-03-05 16:44:50 +01:00
Plane v = value ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
gui [ 0 ] = v . normal . x ;
gui [ 1 ] = v . normal . y ;
2017-08-17 23:26:57 +02:00
gui [ 2 ] = v . normal . z ;
2017-03-05 16:44:50 +01:00
gui [ 3 ] = v . d ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_MAT2 : {
2017-01-11 04:52:51 +01:00
Transform2D v = value ;
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
2016-10-10 23:31:01 +02:00
2018-01-12 20:36:13 +01:00
//in std140 members of mat2 are treated as vec4s
2017-03-05 16:44:50 +01:00
gui [ 0 ] = v . elements [ 0 ] [ 0 ] ;
gui [ 1 ] = v . elements [ 0 ] [ 1 ] ;
2018-01-12 20:36:13 +01:00
gui [ 2 ] = 0 ;
gui [ 3 ] = 0 ;
gui [ 4 ] = v . elements [ 1 ] [ 0 ] ;
gui [ 5 ] = v . elements [ 1 ] [ 1 ] ;
gui [ 6 ] = 0 ;
gui [ 7 ] = 0 ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_MAT3 : {
2017-01-11 04:52:51 +01:00
Basis v = value ;
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
gui [ 0 ] = v . elements [ 0 ] [ 0 ] ;
gui [ 1 ] = v . elements [ 1 ] [ 0 ] ;
gui [ 2 ] = v . elements [ 2 ] [ 0 ] ;
gui [ 3 ] = 0 ;
gui [ 4 ] = v . elements [ 0 ] [ 1 ] ;
gui [ 5 ] = v . elements [ 1 ] [ 1 ] ;
gui [ 6 ] = v . elements [ 2 ] [ 1 ] ;
gui [ 7 ] = 0 ;
gui [ 8 ] = v . elements [ 0 ] [ 2 ] ;
gui [ 9 ] = v . elements [ 1 ] [ 2 ] ;
gui [ 10 ] = v . elements [ 2 ] [ 2 ] ;
gui [ 11 ] = 0 ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_MAT4 : {
Transform v = value ;
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
gui [ 0 ] = v . basis . elements [ 0 ] [ 0 ] ;
gui [ 1 ] = v . basis . elements [ 1 ] [ 0 ] ;
gui [ 2 ] = v . basis . elements [ 2 ] [ 0 ] ;
gui [ 3 ] = 0 ;
gui [ 4 ] = v . basis . elements [ 0 ] [ 1 ] ;
gui [ 5 ] = v . basis . elements [ 1 ] [ 1 ] ;
gui [ 6 ] = v . basis . elements [ 2 ] [ 1 ] ;
gui [ 7 ] = 0 ;
gui [ 8 ] = v . basis . elements [ 0 ] [ 2 ] ;
gui [ 9 ] = v . basis . elements [ 1 ] [ 2 ] ;
gui [ 10 ] = v . basis . elements [ 2 ] [ 2 ] ;
gui [ 11 ] = 0 ;
gui [ 12 ] = v . origin . x ;
gui [ 13 ] = v . origin . y ;
gui [ 14 ] = v . origin . z ;
gui [ 15 ] = 1 ;
2016-10-10 23:31:01 +02:00
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2016-10-10 23:31:01 +02:00
}
}
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ static void _fill_std140_ubo_value ( ShaderLanguage : : DataType type , const Vector < ShaderLanguage : : ConstantNode : : Value > & value , uint8_t * data ) {
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
switch ( type ) {
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_BOOL : {
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
2016-10-10 23:31:01 +02:00
* gui = value [ 0 ] . boolean ? GL_TRUE : GL_FALSE ;
} break ;
case ShaderLanguage : : TYPE_BVEC2 : {
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
gui [ 0 ] = value [ 0 ] . boolean ? GL_TRUE : GL_FALSE ;
gui [ 1 ] = value [ 1 ] . boolean ? GL_TRUE : GL_FALSE ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_BVEC3 : {
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
gui [ 0 ] = value [ 0 ] . boolean ? GL_TRUE : GL_FALSE ;
gui [ 1 ] = value [ 1 ] . boolean ? GL_TRUE : GL_FALSE ;
gui [ 2 ] = value [ 2 ] . boolean ? GL_TRUE : GL_FALSE ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_BVEC4 : {
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
gui [ 0 ] = value [ 0 ] . boolean ? GL_TRUE : GL_FALSE ;
gui [ 1 ] = value [ 1 ] . boolean ? GL_TRUE : GL_FALSE ;
gui [ 2 ] = value [ 2 ] . boolean ? GL_TRUE : GL_FALSE ;
gui [ 3 ] = value [ 3 ] . boolean ? GL_TRUE : GL_FALSE ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_INT : {
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
gui [ 0 ] = value [ 0 ] . sint ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_IVEC2 : {
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
gui [ i ] = value [ i ] . sint ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_IVEC3 : {
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
gui [ i ] = value [ i ] . sint ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_IVEC4 : {
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
gui [ i ] = value [ i ] . sint ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_UINT : {
2017-03-05 16:44:50 +01:00
GLuint * gui = ( GLuint * ) data ;
gui [ 0 ] = value [ 0 ] . uint ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_UVEC2 : {
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
gui [ i ] = value [ i ] . uint ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_UVEC3 : {
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
gui [ i ] = value [ i ] . uint ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_UVEC4 : {
2017-03-05 16:44:50 +01:00
GLint * gui = ( GLint * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
gui [ i ] = value [ i ] . uint ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_FLOAT : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
gui [ 0 ] = value [ 0 ] . real ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_VEC2 : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
gui [ i ] = value [ i ] . real ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_VEC3 : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
gui [ i ] = value [ i ] . real ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_VEC4 : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
gui [ i ] = value [ i ] . real ;
2016-10-10 23:31:01 +02:00
}
} break ;
case ShaderLanguage : : TYPE_MAT2 : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
2016-10-10 23:31:01 +02:00
2018-01-12 20:36:13 +01:00
//in std140 members of mat2 are treated as vec4s
gui [ 0 ] = value [ 0 ] . real ;
gui [ 1 ] = value [ 1 ] . real ;
gui [ 2 ] = 0 ;
gui [ 3 ] = 0 ;
gui [ 4 ] = value [ 2 ] . real ;
gui [ 5 ] = value [ 3 ] . real ;
gui [ 6 ] = 0 ;
gui [ 7 ] = 0 ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_MAT3 : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
gui [ 0 ] = value [ 0 ] . real ;
gui [ 1 ] = value [ 1 ] . real ;
gui [ 2 ] = value [ 2 ] . real ;
gui [ 3 ] = 0 ;
gui [ 4 ] = value [ 3 ] . real ;
gui [ 5 ] = value [ 4 ] . real ;
gui [ 6 ] = value [ 5 ] . real ;
gui [ 7 ] = 0 ;
gui [ 8 ] = value [ 6 ] . real ;
gui [ 9 ] = value [ 7 ] . real ;
gui [ 10 ] = value [ 8 ] . real ;
gui [ 11 ] = 0 ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_MAT4 : {
2017-03-05 16:44:50 +01:00
GLfloat * gui = ( GLfloat * ) data ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 16 ; i + + ) {
gui [ i ] = value [ i ] . real ;
2016-10-10 23:31:01 +02:00
}
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2016-10-10 23:31:01 +02:00
}
}
_FORCE_INLINE_ static void _fill_std140_ubo_empty ( ShaderLanguage : : DataType type , uint8_t * data ) {
2017-03-05 16:44:50 +01:00
switch ( type ) {
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_BOOL :
case ShaderLanguage : : TYPE_INT :
case ShaderLanguage : : TYPE_UINT :
case ShaderLanguage : : TYPE_FLOAT : {
2017-03-05 16:44:50 +01:00
zeromem ( data , 4 ) ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_BVEC2 :
case ShaderLanguage : : TYPE_IVEC2 :
case ShaderLanguage : : TYPE_UVEC2 :
case ShaderLanguage : : TYPE_VEC2 : {
2017-03-05 16:44:50 +01:00
zeromem ( data , 8 ) ;
2016-10-10 23:31:01 +02:00
} break ;
case ShaderLanguage : : TYPE_BVEC3 :
case ShaderLanguage : : TYPE_IVEC3 :
case ShaderLanguage : : TYPE_UVEC3 :
2019-09-06 08:06:20 +02:00
case ShaderLanguage : : TYPE_VEC3 : {
zeromem ( data , 12 ) ;
} break ;
2016-10-10 23:31:01 +02:00
case ShaderLanguage : : TYPE_BVEC4 :
case ShaderLanguage : : TYPE_IVEC4 :
case ShaderLanguage : : TYPE_UVEC4 :
2018-01-12 20:36:13 +01:00
case ShaderLanguage : : TYPE_VEC4 : {
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
zeromem ( data , 16 ) ;
2016-10-10 23:31:01 +02:00
} break ;
2018-01-12 20:36:13 +01:00
case ShaderLanguage : : TYPE_MAT2 : {
zeromem ( data , 32 ) ;
} break ;
2017-03-05 16:44:50 +01:00
case ShaderLanguage : : TYPE_MAT3 : {
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
zeromem ( data , 48 ) ;
2016-10-10 23:31:01 +02:00
} break ;
2017-03-05 16:44:50 +01:00
case ShaderLanguage : : TYPE_MAT4 : {
zeromem ( data , 64 ) ;
2016-10-10 23:31:01 +02:00
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2016-10-10 23:31:01 +02:00
}
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : _update_material ( Material * material ) {
2016-10-10 23:31:01 +02:00
if ( material - > dirty_list . in_list ( ) )
2017-03-05 16:44:50 +01:00
_material_dirty_list . remove ( & material - > dirty_list ) ;
2016-11-10 03:55:06 +01:00
if ( material - > shader & & material - > shader - > dirty_list . in_list ( ) ) {
_update_shader ( material - > shader ) ;
}
2017-06-13 00:23:37 +02:00
if ( material - > shader & & ! material - > shader - > valid )
return ;
2016-11-10 03:55:06 +01:00
//update caches
{
bool can_cast_shadow = false ;
bool is_animated = false ;
2017-03-05 16:44:50 +01:00
if ( material - > shader & & material - > shader - > mode = = VS : : SHADER_SPATIAL ) {
2017-02-16 12:55:11 +01:00
2017-10-20 21:13:22 +02:00
if ( material - > shader - > spatial . blend_mode = = Shader : : Spatial : : BLEND_MODE_MIX & &
2018-11-04 10:14:50 +01:00
( ! material - > shader - > spatial . uses_alpha | | material - > shader - > spatial . depth_draw_mode = = Shader : : Spatial : : DEPTH_DRAW_ALPHA_PREPASS ) ) {
2017-03-05 16:44:50 +01:00
can_cast_shadow = true ;
2016-11-10 03:55:06 +01:00
}
if ( material - > shader - > spatial . uses_discard & & material - > shader - > uses_fragment_time ) {
2017-03-05 16:44:50 +01:00
is_animated = true ;
2016-11-10 03:55:06 +01:00
}
if ( material - > shader - > spatial . uses_vertex & & material - > shader - > uses_vertex_time ) {
2017-03-05 16:44:50 +01:00
is_animated = true ;
2016-11-10 03:55:06 +01:00
}
2017-03-05 16:44:50 +01:00
if ( can_cast_shadow ! = material - > can_cast_shadow_cache | | is_animated ! = material - > is_animated_cache ) {
material - > can_cast_shadow_cache = can_cast_shadow ;
material - > is_animated_cache = is_animated ;
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
for ( Map < Geometry * , int > : : Element * E = material - > geometry_owners . front ( ) ; E ; E = E - > next ( ) ) {
2017-02-16 12:55:11 +01:00
E - > key ( ) - > material_changed_notify ( ) ;
}
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
for ( Map < RasterizerScene : : InstanceBase * , int > : : Element * E = material - > instance_owners . front ( ) ; E ; E = E - > next ( ) ) {
2018-11-14 13:32:39 +01:00
E - > key ( ) - > base_changed ( false , true ) ;
2017-02-16 12:55:11 +01:00
}
2016-11-10 03:55:06 +01:00
}
}
}
2016-10-10 23:31:01 +02:00
//clear ubo if it needs to be cleared
if ( material - > ubo_size ) {
2017-03-05 16:44:50 +01:00
if ( ! material - > shader | | material - > shader - > ubo_size ! = material - > ubo_size ) {
2016-10-10 23:31:01 +02:00
//by by ubo
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & material - > ubo_id ) ;
material - > ubo_id = 0 ;
material - > ubo_size = 0 ;
2016-10-10 23:31:01 +02:00
}
}
//create ubo if it needs to be created
2017-03-05 16:44:50 +01:00
if ( material - > ubo_size = = 0 & & material - > shader & & material - > shader - > ubo_size ) {
2016-10-10 23:31:01 +02:00
glGenBuffers ( 1 , & material - > ubo_id ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , material - > ubo_id ) ;
2017-10-03 22:34:08 +02:00
glBufferData ( GL_UNIFORM_BUFFER , material - > shader - > ubo_size , NULL , GL_STATIC_DRAW ) ;
2016-10-10 23:31:01 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
2017-03-05 16:44:50 +01:00
material - > ubo_size = material - > shader - > ubo_size ;
2016-10-10 23:31:01 +02:00
}
//fill up the UBO if it needs to be filled
if ( material - > shader & & material - > ubo_size ) {
2017-03-05 16:44:50 +01:00
uint8_t * local_ubo = ( uint8_t * ) alloca ( material - > ubo_size ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( Map < StringName , ShaderLanguage : : ShaderNode : : Uniform > : : Element * E = material - > shader - > uniforms . front ( ) ; E ; E = E - > next ( ) ) {
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) . order < 0 )
2016-10-10 23:31:01 +02:00
continue ; // texture, does not go here
//regular uniform
2017-03-05 16:44:50 +01:00
uint8_t * data = & local_ubo [ material - > shader - > ubo_offsets [ E - > get ( ) . order ] ] ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
Map < StringName , Variant > : : Element * V = material - > params . find ( E - > key ( ) ) ;
2016-10-10 23:31:01 +02:00
if ( V ) {
2017-03-05 16:44:50 +01:00
//user provided
_fill_std140_variant_ubo_value ( E - > get ( ) . type , V - > get ( ) , data , material - > shader - > mode = = VS : : SHADER_SPATIAL ) ;
2016-11-21 02:49:53 +01:00
2017-03-05 16:44:50 +01:00
} else if ( E - > get ( ) . default_value . size ( ) ) {
2016-10-10 23:31:01 +02:00
//default value
2017-03-05 16:44:50 +01:00
_fill_std140_ubo_value ( E - > get ( ) . type , E - > get ( ) . default_value , data ) ;
2016-10-10 23:31:01 +02:00
//value=E->get().default_value;
} else {
//zero because it was not provided
2017-08-20 17:34:15 +02:00
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 ) ;
}
2016-10-10 23:31:01 +02:00
}
}
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_UNIFORM_BUFFER , material - > ubo_id ) ;
2019-11-10 19:51:56 +01:00
glBufferData ( GL_UNIFORM_BUFFER , material - > ubo_size , local_ubo , GL_STATIC_DRAW ) ;
2016-10-10 23:31:01 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
}
//set up the texture array, for easy access when it needs to be drawn
if ( material - > shader & & material - > shader - > texture_count ) {
2018-06-26 13:59:26 +02:00
material - > texture_is_3d . resize ( material - > shader - > texture_count ) ;
2016-10-10 23:31:01 +02:00
material - > textures . resize ( material - > shader - > texture_count ) ;
2017-03-05 16:44:50 +01:00
for ( Map < StringName , ShaderLanguage : : ShaderNode : : Uniform > : : Element * E = material - > shader - > uniforms . front ( ) ; E ; E = E - > next ( ) ) {
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) . texture_order < 0 )
2016-10-10 23:31:01 +02:00
continue ; // not a texture, does not go here
RID texture ;
2018-06-26 13:59:26 +02:00
switch ( E - > get ( ) . type ) {
case ShaderLanguage : : TYPE_SAMPLER3D :
case ShaderLanguage : : TYPE_SAMPLER2DARRAY : {
material - > texture_is_3d . write [ E - > get ( ) . texture_order ] = true ;
} break ;
default : {
material - > texture_is_3d . write [ E - > get ( ) . texture_order ] = false ;
} break ;
}
2017-03-05 16:44:50 +01:00
Map < StringName , Variant > : : Element * V = material - > params . find ( E - > key ( ) ) ;
2016-10-10 23:31:01 +02:00
if ( V ) {
2017-03-05 16:44:50 +01:00
texture = V - > get ( ) ;
2016-10-10 23:31:01 +02:00
}
if ( ! texture . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
Map < StringName , RID > : : Element * W = material - > shader - > default_textures . find ( E - > key ( ) ) ;
2016-10-10 23:31:01 +02:00
if ( W ) {
2017-03-05 16:44:50 +01:00
texture = W - > get ( ) ;
2016-10-10 23:31:01 +02:00
}
}
2018-07-25 03:11:03 +02:00
material - > textures . write [ E - > get ( ) . texture_order ] = texture ;
2016-10-10 23:31:01 +02:00
}
} else {
material - > textures . clear ( ) ;
2018-06-26 13:59:26 +02:00
material - > texture_is_3d . clear ( ) ;
2016-10-10 23:31:01 +02:00
}
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : _material_add_geometry ( RID p_material , Geometry * p_geometry ) {
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
Material * material = material_owner . getornull ( p_material ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! material ) ;
2017-03-05 16:44:50 +01:00
Map < Geometry * , int > : : Element * I = material - > geometry_owners . find ( p_geometry ) ;
2016-11-10 03:55:06 +01:00
if ( I ) {
I - > get ( ) + + ;
} else {
2017-03-05 16:44:50 +01:00
material - > geometry_owners [ p_geometry ] = 1 ;
2016-11-10 03:55:06 +01:00
}
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : _material_remove_geometry ( RID p_material , Geometry * p_geometry ) {
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
Material * material = material_owner . getornull ( p_material ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! material ) ;
2017-03-05 16:44:50 +01:00
Map < Geometry * , int > : : Element * I = material - > geometry_owners . find ( p_geometry ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! I ) ;
I - > get ( ) - - ;
2017-03-05 16:44:50 +01:00
if ( I - > get ( ) = = 0 ) {
2016-11-25 00:46:55 +01:00
material - > geometry_owners . erase ( I ) ;
2016-11-10 03:55:06 +01:00
}
}
2016-10-10 23:31:01 +02:00
void RasterizerStorageGLES3 : : update_dirty_materials ( ) {
2017-03-05 16:44:50 +01:00
while ( _material_dirty_list . first ( ) ) {
2016-10-10 23:31:01 +02:00
Material * material = _material_dirty_list . first ( ) - > self ( ) ;
_update_material ( material ) ;
}
}
2016-10-03 21:33:42 +02:00
/* MESH API */
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : mesh_create ( ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Mesh * mesh = memnew ( Mesh ) ;
2016-10-19 16:14:41 +02:00
return mesh_owner . make_rid ( mesh ) ;
2016-10-03 21:33:42 +02:00
}
2017-11-17 03:09:00 +01:00
void RasterizerStorageGLES3 : : mesh_add_surface ( RID p_mesh , uint32_t p_format , VS : : PrimitiveType p_primitive , const PoolVector < uint8_t > & p_array , int p_vertex_count , const PoolVector < uint8_t > & p_index_array , int p_index_count , const AABB & p_aabb , const Vector < PoolVector < uint8_t > > & p_blend_shapes , const Vector < AABB > & p_bone_aabbs ) {
2017-02-07 00:18:35 +01:00
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > array = p_array ;
2016-12-25 12:05:23 +01:00
2016-10-19 16:14:41 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! ( p_format & VS : : ARRAY_FORMAT_VERTEX ) ) ;
2016-10-19 16:14:41 +02:00
//must have index and bones, both.
{
2017-03-05 16:44:50 +01:00
uint32_t bones_weight = VS : : ARRAY_FORMAT_BONES | VS : : ARRAY_FORMAT_WEIGHTS ;
2019-08-15 04:57:49 +02:00
ERR_FAIL_COND_MSG ( ( p_format & bones_weight ) & & ( p_format & bones_weight ) ! = bones_weight , " Array must have both bones and weights in format or none. " ) ;
2016-10-19 16:14:41 +02:00
}
2017-01-12 12:34:00 +01:00
//bool has_morph = p_blend_shapes.size();
2016-10-19 16:14:41 +02:00
2016-11-25 00:46:55 +01:00
Surface : : Attrib attribs [ VS : : ARRAY_MAX ] ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
int stride = 0 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < VS : : ARRAY_MAX ; i + + ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
attribs [ i ] . index = i ;
2016-12-24 20:23:30 +01:00
2017-03-05 16:44:50 +01:00
if ( ! ( p_format & ( 1 < < i ) ) ) {
attribs [ i ] . enabled = false ;
attribs [ i ] . integer = false ;
2016-10-19 16:14:41 +02:00
continue ;
}
2017-03-05 16:44:50 +01:00
attribs [ i ] . enabled = true ;
attribs [ i ] . offset = stride ;
attribs [ i ] . integer = false ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
switch ( i ) {
2016-10-19 16:14:41 +02:00
case VS : : ARRAY_VERTEX : {
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_FLAG_USE_2D_VERTICES ) {
attribs [ i ] . size = 2 ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = ( p_format & VS : : ARRAY_COMPRESS_VERTEX ) ? 4 : 3 ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_COMPRESS_VERTEX ) {
attribs [ i ] . type = GL_HALF_FLOAT ;
stride + = attribs [ i ] . size * 2 ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_FLOAT ;
stride + = attribs [ i ] . size * 4 ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
} break ;
case VS : : ARRAY_NORMAL : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 3 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_COMPRESS_NORMAL ) {
attribs [ i ] . type = GL_BYTE ;
stride + = 4 ; //pad extra byte
attribs [ i ] . normalized = GL_TRUE ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_FLOAT ;
stride + = 12 ;
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
}
} break ;
case VS : : ARRAY_TANGENT : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 4 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_COMPRESS_TANGENT ) {
attribs [ i ] . type = GL_BYTE ;
stride + = 4 ;
attribs [ i ] . normalized = GL_TRUE ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_FLOAT ;
stride + = 16 ;
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
}
} break ;
case VS : : ARRAY_COLOR : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 4 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_COMPRESS_COLOR ) {
attribs [ i ] . type = GL_UNSIGNED_BYTE ;
stride + = 4 ;
attribs [ i ] . normalized = GL_TRUE ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_FLOAT ;
stride + = 16 ;
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
}
} break ;
case VS : : ARRAY_TEX_UV : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 2 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_COMPRESS_TEX_UV ) {
attribs [ i ] . type = GL_HALF_FLOAT ;
stride + = 4 ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_FLOAT ;
stride + = 8 ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
} break ;
case VS : : ARRAY_TEX_UV2 : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 2 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_COMPRESS_TEX_UV2 ) {
attribs [ i ] . type = GL_HALF_FLOAT ;
stride + = 4 ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_FLOAT ;
stride + = 8 ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
} break ;
case VS : : ARRAY_BONES : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 4 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_FLAG_USE_16_BIT_BONES ) {
attribs [ i ] . type = GL_UNSIGNED_SHORT ;
stride + = 8 ;
2016-11-21 23:03:39 +01:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_UNSIGNED_BYTE ;
stride + = 4 ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
attribs [ i ] . normalized = GL_FALSE ;
attribs [ i ] . integer = true ;
2016-10-19 16:14:41 +02:00
} break ;
case VS : : ARRAY_WEIGHTS : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 4 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_COMPRESS_WEIGHTS ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_UNSIGNED_SHORT ;
stride + = 8 ;
attribs [ i ] . normalized = GL_TRUE ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_FLOAT ;
stride + = 16 ;
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
}
} break ;
case VS : : ARRAY_INDEX : {
2017-03-05 16:44:50 +01:00
attribs [ i ] . size = 1 ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_vertex_count > = ( 1 < < 16 ) ) {
attribs [ i ] . type = GL_UNSIGNED_INT ;
attribs [ i ] . stride = 4 ;
2016-10-19 16:14:41 +02:00
} else {
2017-03-05 16:44:50 +01:00
attribs [ i ] . type = GL_UNSIGNED_SHORT ;
attribs [ i ] . stride = 2 ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
attribs [ i ] . normalized = GL_FALSE ;
2016-10-19 16:14:41 +02:00
} break ;
}
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < VS : : ARRAY_MAX - 1 ; i + + ) {
attribs [ i ] . stride = stride ;
2016-10-19 16:14:41 +02:00
}
//validate sizes
int array_size = stride * p_vertex_count ;
2017-03-05 16:44:50 +01:00
int index_array_size = 0 ;
if ( array . size ( ) ! = array_size & & array . size ( ) + p_vertex_count * 2 = = array_size ) {
2016-12-25 12:05:23 +01:00
//old format, convert
2017-01-07 22:25:37 +01:00
array = PoolVector < uint8_t > ( ) ;
2016-12-25 12:05:23 +01:00
2017-03-05 16:44:50 +01:00
array . resize ( p_array . size ( ) + p_vertex_count * 2 ) ;
2016-12-25 12:05:23 +01:00
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Write w = array . write ( ) ;
PoolVector < uint8_t > : : Read r = p_array . read ( ) ;
2016-12-25 12:05:23 +01:00
2017-03-05 16:44:50 +01:00
uint16_t * w16 = ( uint16_t * ) w . ptr ( ) ;
const uint16_t * r16 = ( uint16_t * ) r . ptr ( ) ;
2016-12-25 12:05:23 +01:00
uint16_t one = Math : : make_half_float ( 1 ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_vertex_count ; i + + ) {
2016-12-25 12:05:23 +01:00
* w16 + + = * r16 + + ;
* w16 + + = * r16 + + ;
* w16 + + = * r16 + + ;
* w16 + + = one ;
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < ( stride / 2 ) - 4 ; j + + ) {
2016-12-25 12:05:23 +01:00
* w16 + + = * r16 + + ;
}
}
}
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( array . size ( ) ! = array_size ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_FORMAT_INDEX ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
index_array_size = attribs [ VS : : ARRAY_INDEX ] . stride * p_index_count ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_index_array . size ( ) ! = index_array_size ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_blend_shapes . size ( ) ! = mesh - > blend_shape_count ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_blend_shapes . size ( ) ; i + + ) {
ERR_FAIL_COND ( p_blend_shapes [ i ] . size ( ) ! = array_size ) ;
2016-10-19 16:14:41 +02:00
}
//ok all valid, create stuff
2017-03-05 16:44:50 +01:00
Surface * surface = memnew ( Surface ) ;
surface - > active = true ;
surface - > array_len = p_vertex_count ;
surface - > index_array_len = p_index_count ;
surface - > array_byte_size = array . size ( ) ;
surface - > index_array_byte_size = p_index_array . size ( ) ;
surface - > primitive = p_primitive ;
surface - > mesh = mesh ;
surface - > format = p_format ;
surface - > skeleton_bone_aabb = p_bone_aabbs ;
2016-10-19 16:14:41 +02:00
surface - > skeleton_bone_used . resize ( surface - > skeleton_bone_aabb . size ( ) ) ;
2017-03-05 16:44:50 +01:00
surface - > aabb = p_aabb ;
surface - > max_bone = p_bone_aabbs . size ( ) ;
2017-06-11 23:13:04 +02:00
surface - > total_data_size + = surface - > array_byte_size + surface - > index_array_byte_size ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < surface - > skeleton_bone_used . size ( ) ; i + + ) {
if ( surface - > skeleton_bone_aabb [ i ] . size . x < 0 | | surface - > skeleton_bone_aabb [ i ] . size . y < 0 | | surface - > skeleton_bone_aabb [ i ] . size . z < 0 ) {
2018-07-25 03:11:03 +02:00
surface - > skeleton_bone_used . write [ i ] = false ;
2016-10-19 16:14:41 +02:00
} else {
2018-07-25 03:11:03 +02:00
surface - > skeleton_bone_used . write [ i ] = true ;
2016-10-19 16:14:41 +02:00
}
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < VS : : ARRAY_MAX ; i + + ) {
surface - > attribs [ i ] = attribs [ i ] ;
2016-10-19 16:14:41 +02:00
}
{
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Read vr = array . read ( ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & surface - > vertex_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , surface - > vertex_id ) ;
2019-07-07 23:08:51 +02:00
glBufferData ( GL_ARRAY_BUFFER , array_size , vr . ptr ( ) , ( p_format & VS : : ARRAY_FLAG_USE_DYNAMIC_UPDATE ) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( p_format & VS : : ARRAY_FORMAT_INDEX ) {
2016-10-19 16:14:41 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Read ir = p_index_array . read ( ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & surface - > index_id ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , surface - > index_id ) ;
glBufferData ( GL_ELEMENT_ARRAY_BUFFER , index_array_size , ir . ptr ( ) , GL_STATIC_DRAW ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-19 16:14:41 +02:00
}
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
//generate arrays for faster state switching
2017-03-05 16:44:50 +01:00
for ( int ai = 0 ; ai < 2 ; ai + + ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( ai = = 0 ) {
2016-11-22 05:26:56 +01:00
//for normal draw
2017-03-05 16:44:50 +01:00
glGenVertexArrays ( 1 , & surface - > array_id ) ;
2016-11-22 05:26:56 +01:00
glBindVertexArray ( surface - > array_id ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , surface - > vertex_id ) ;
} else if ( ai = = 1 ) {
2016-11-22 05:26:56 +01:00
//for instancing draw (can be changed and no one cares)
2017-03-05 16:44:50 +01:00
glGenVertexArrays ( 1 , & surface - > instancing_array_id ) ;
2016-11-22 05:26:56 +01:00
glBindVertexArray ( surface - > instancing_array_id ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , surface - > vertex_id ) ;
2016-11-22 05:26:56 +01:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < VS : : ARRAY_MAX - 1 ; i + + ) {
2016-11-22 05:26:56 +01:00
if ( ! attribs [ i ] . enabled )
continue ;
if ( attribs [ i ] . integer ) {
2019-02-27 10:07:30 +01:00
glVertexAttribIPointer ( attribs [ i ] . index , attribs [ i ] . size , attribs [ i ] . type , attribs [ i ] . stride , CAST_INT_TO_UCHAR_PTR ( attribs [ i ] . offset ) ) ;
2016-11-22 05:26:56 +01:00
} else {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( attribs [ i ] . index , attribs [ i ] . size , attribs [ i ] . type , attribs [ i ] . normalized , attribs [ i ] . stride , CAST_INT_TO_UCHAR_PTR ( attribs [ i ] . offset ) ) ;
2016-11-22 05:26:56 +01:00
}
glEnableVertexAttribArray ( attribs [ i ] . index ) ;
2016-11-21 23:03:39 +01:00
}
2016-10-19 16:14:41 +02:00
2016-11-22 05:26:56 +01:00
if ( surface - > index_id ) {
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , surface - > index_id ) ;
2016-11-22 05:26:56 +01:00
}
2016-10-19 16:14:41 +02:00
2016-11-22 05:26:56 +01:00
glBindVertexArray ( 0 ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
2016-10-19 16:14:41 +02:00
}
2017-06-11 20:52:03 +02:00
# ifdef DEBUG_ENABLED
if ( config . generate_wireframes & & p_primitive = = VS : : PRIMITIVE_TRIANGLES ) {
//generate wireframes, this is used mostly by editor
PoolVector < uint32_t > wf_indices ;
int index_count ;
if ( p_format & VS : : ARRAY_FORMAT_INDEX ) {
index_count = p_index_count * 2 ;
wf_indices . resize ( index_count ) ;
PoolVector < uint8_t > : : Read ir = p_index_array . read ( ) ;
PoolVector < uint32_t > : : Write wr = wf_indices . write ( ) ;
if ( p_vertex_count < ( 1 < < 16 ) ) {
//read 16 bit indices
const uint16_t * src_idx = ( const uint16_t * ) ir . ptr ( ) ;
2019-06-09 14:49:59 +02:00
for ( int i = 0 ; i + 5 < index_count ; i + = 6 ) {
2017-06-11 20:52:03 +02:00
wr [ i + 0 ] = src_idx [ i / 2 ] ;
wr [ i + 1 ] = src_idx [ i / 2 + 1 ] ;
wr [ i + 2 ] = src_idx [ i / 2 + 1 ] ;
wr [ i + 3 ] = src_idx [ i / 2 + 2 ] ;
wr [ i + 4 ] = src_idx [ i / 2 + 2 ] ;
wr [ i + 5 ] = src_idx [ i / 2 ] ;
}
} else {
//read 16 bit indices
const uint32_t * src_idx = ( const uint32_t * ) ir . ptr ( ) ;
2019-06-09 14:49:59 +02:00
for ( int i = 0 ; i + 5 < index_count ; i + = 6 ) {
2017-06-11 20:52:03 +02:00
wr [ i + 0 ] = src_idx [ i / 2 ] ;
wr [ i + 1 ] = src_idx [ i / 2 + 1 ] ;
wr [ i + 2 ] = src_idx [ i / 2 + 1 ] ;
wr [ i + 3 ] = src_idx [ i / 2 + 2 ] ;
wr [ i + 4 ] = src_idx [ i / 2 + 2 ] ;
wr [ i + 5 ] = src_idx [ i / 2 ] ;
}
}
} else {
index_count = p_vertex_count * 2 ;
wf_indices . resize ( index_count ) ;
PoolVector < uint32_t > : : Write wr = wf_indices . write ( ) ;
2019-06-09 14:49:59 +02:00
for ( int i = 0 ; i + 5 < index_count ; i + = 6 ) {
2017-06-11 20:52:03 +02:00
wr [ i + 0 ] = i / 2 ;
wr [ i + 1 ] = i / 2 + 1 ;
wr [ i + 2 ] = i / 2 + 1 ;
wr [ i + 3 ] = i / 2 + 2 ;
wr [ i + 4 ] = i / 2 + 2 ;
wr [ i + 5 ] = i / 2 ;
}
}
{
PoolVector < uint32_t > : : Read ir = wf_indices . read ( ) ;
glGenBuffers ( 1 , & surface - > index_wireframe_id ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , surface - > index_wireframe_id ) ;
glBufferData ( GL_ELEMENT_ARRAY_BUFFER , index_count * sizeof ( uint32_t ) , ir . ptr ( ) , GL_STATIC_DRAW ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ; //unbind
surface - > index_wireframe_len = index_count ;
}
for ( int ai = 0 ; ai < 2 ; ai + + ) {
if ( ai = = 0 ) {
//for normal draw
glGenVertexArrays ( 1 , & surface - > array_wireframe_id ) ;
glBindVertexArray ( surface - > array_wireframe_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , surface - > vertex_id ) ;
} else if ( ai = = 1 ) {
//for instancing draw (can be changed and no one cares)
glGenVertexArrays ( 1 , & surface - > instancing_array_wireframe_id ) ;
glBindVertexArray ( surface - > instancing_array_wireframe_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , surface - > vertex_id ) ;
}
for ( int i = 0 ; i < VS : : ARRAY_MAX - 1 ; i + + ) {
if ( ! attribs [ i ] . enabled )
continue ;
if ( attribs [ i ] . integer ) {
2019-02-27 10:07:30 +01:00
glVertexAttribIPointer ( attribs [ i ] . index , attribs [ i ] . size , attribs [ i ] . type , attribs [ i ] . stride , CAST_INT_TO_UCHAR_PTR ( attribs [ i ] . offset ) ) ;
2017-06-11 20:52:03 +02:00
} else {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( attribs [ i ] . index , attribs [ i ] . size , attribs [ i ] . type , attribs [ i ] . normalized , attribs [ i ] . stride , CAST_INT_TO_UCHAR_PTR ( attribs [ i ] . offset ) ) ;
2017-06-11 20:52:03 +02:00
}
glEnableVertexAttribArray ( attribs [ i ] . index ) ;
}
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , surface - > index_wireframe_id ) ;
glBindVertexArray ( 0 ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
}
}
# endif
2016-10-19 16:14:41 +02:00
}
{
//blend shapes
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_blend_shapes . size ( ) ; i + + ) {
2016-10-19 16:14:41 +02:00
2017-01-12 12:34:00 +01:00
Surface : : BlendShape mt ;
2016-10-19 16:14:41 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Read vr = p_blend_shapes [ i ] . read ( ) ;
2016-10-19 16:14:41 +02:00
2017-06-11 23:13:04 +02:00
surface - > total_data_size + = array_size ;
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & mt . vertex_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , mt . vertex_id ) ;
glBufferData ( GL_ARRAY_BUFFER , array_size , vr . ptr ( ) , GL_STATIC_DRAW ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
glGenVertexArrays ( 1 , & mt . array_id ) ;
2016-10-19 16:14:41 +02:00
glBindVertexArray ( mt . array_id ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , mt . vertex_id ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < VS : : ARRAY_MAX - 1 ; j + + ) {
2016-10-19 16:14:41 +02:00
2016-11-25 00:46:55 +01:00
if ( ! attribs [ j ] . enabled )
2016-10-19 16:14:41 +02:00
continue ;
2016-11-25 00:46:55 +01:00
if ( attribs [ j ] . integer ) {
2019-02-27 10:07:30 +01:00
glVertexAttribIPointer ( attribs [ j ] . index , attribs [ j ] . size , attribs [ j ] . type , attribs [ j ] . stride , CAST_INT_TO_UCHAR_PTR ( attribs [ j ] . offset ) ) ;
2016-11-21 23:03:39 +01:00
} else {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( attribs [ j ] . index , attribs [ j ] . size , attribs [ j ] . type , attribs [ j ] . normalized , attribs [ j ] . stride , CAST_INT_TO_UCHAR_PTR ( attribs [ j ] . offset ) ) ;
2016-11-21 23:03:39 +01:00
}
2016-11-25 00:46:55 +01:00
glEnableVertexAttribArray ( attribs [ j ] . index ) ;
2016-10-19 16:14:41 +02:00
}
glBindVertexArray ( 0 ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-19 16:14:41 +02:00
2017-01-12 12:34:00 +01:00
surface - > blend_shapes . push_back ( mt ) ;
2016-10-19 16:14:41 +02:00
}
}
mesh - > surfaces . push_back ( surface ) ;
2019-02-22 20:26:19 +01:00
mesh - > instance_change_notify ( true , true ) ;
2017-06-11 23:13:04 +02:00
info . vertex_mem + = surface - > total_data_size ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : mesh_set_blend_shape_count ( RID p_mesh , int p_amount ) {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( mesh - > surfaces . size ( ) ! = 0 ) ;
ERR_FAIL_COND ( p_amount < 0 ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
mesh - > blend_shape_count = p_amount ;
2019-03-01 20:01:21 +01:00
mesh - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : mesh_get_blend_shape_count ( RID p_mesh ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , 0 ) ;
2016-10-19 16:14:41 +02:00
2017-01-12 12:34:00 +01:00
return mesh - > blend_shape_count ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : mesh_set_blend_shape_mode ( RID p_mesh , VS : : BlendShapeMode p_mode ) {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
2017-03-05 16:44:50 +01:00
mesh - > blend_shape_mode = p_mode ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
VS : : BlendShapeMode RasterizerStorageGLES3 : : mesh_get_blend_shape_mode ( RID p_mesh ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , VS : : BLEND_SHAPE_MODE_NORMALIZED ) ;
2016-10-19 16:14:41 +02:00
2017-01-12 12:34:00 +01:00
return mesh - > blend_shape_mode ;
2016-10-03 21:33:42 +02:00
}
2017-11-14 21:25:42 +01:00
void RasterizerStorageGLES3 : : mesh_surface_update_region ( RID p_mesh , int p_surface , int p_offset , const PoolVector < uint8_t > & p_data ) {
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
ERR_FAIL_INDEX ( p_surface , mesh - > surfaces . size ( ) ) ;
int total_size = p_data . size ( ) ;
ERR_FAIL_COND ( p_offset + total_size > mesh - > surfaces [ p_surface ] - > array_byte_size ) ;
PoolVector < uint8_t > : : Read r = p_data . read ( ) ;
2017-11-21 01:26:37 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , mesh - > surfaces [ p_surface ] - > vertex_id ) ;
2017-11-14 21:25:42 +01:00
glBufferSubData ( GL_ARRAY_BUFFER , p_offset , total_size , r . ptr ( ) ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : mesh_surface_set_material ( RID p_mesh , int p_surface , RID p_material ) {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_surface , mesh - > surfaces . size ( ) ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( mesh - > surfaces [ p_surface ] - > material = = p_material )
2016-11-10 03:55:06 +01:00
return ;
if ( mesh - > surfaces [ p_surface ] - > material . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
_material_remove_geometry ( mesh - > surfaces [ p_surface ] - > material , mesh - > surfaces [ p_surface ] ) ;
2016-11-10 03:55:06 +01:00
}
2017-03-05 16:44:50 +01:00
mesh - > surfaces [ p_surface ] - > material = p_material ;
2016-10-03 21:33:42 +02:00
2016-11-10 03:55:06 +01:00
if ( mesh - > surfaces [ p_surface ] - > material . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
_material_add_geometry ( mesh - > surfaces [ p_surface ] - > material , mesh - > surfaces [ p_surface ] ) ;
2016-11-10 03:55:06 +01:00
}
2018-11-14 13:32:39 +01:00
mesh - > instance_change_notify ( false , true ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : mesh_surface_get_material ( RID p_mesh , int p_surface ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , RID ( ) ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , RID ( ) ) ;
2016-10-19 16:14:41 +02:00
return mesh - > surfaces [ p_surface ] - > material ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : mesh_surface_get_array_len ( RID p_mesh , int p_surface ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , 0 ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , 0 ) ;
2016-10-19 16:14:41 +02:00
return mesh - > surfaces [ p_surface ] - > array_len ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : mesh_surface_get_array_index_len ( RID p_mesh , int p_surface ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , 0 ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , 0 ) ;
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
return mesh - > surfaces [ p_surface ] - > index_array_len ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
PoolVector < uint8_t > RasterizerStorageGLES3 : : mesh_surface_get_array ( RID p_mesh , int p_surface ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , PoolVector < uint8_t > ( ) ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , PoolVector < uint8_t > ( ) ) ;
2016-10-19 16:14:41 +02:00
Surface * surface = mesh - > surfaces [ p_surface ] ;
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > ret ;
2016-11-10 03:55:06 +01:00
ret . resize ( surface - > array_byte_size ) ;
2018-10-29 20:39:18 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , surface - > vertex_id ) ;
2016-10-19 16:14:41 +02:00
2018-10-29 20:39:18 +01:00
# if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector < uint8_t > : : Write w = ret . write ( ) ;
glGetBufferSubData ( GL_ARRAY_BUFFER , 0 , surface - > array_byte_size , w . ptr ( ) ) ;
}
# else
void * data = glMapBufferRange ( GL_ARRAY_BUFFER , 0 , surface - > array_byte_size , GL_MAP_READ_BIT ) ;
ERR_FAIL_NULL_V ( data , PoolVector < uint8_t > ( ) ) ;
2016-10-19 16:14:41 +02:00
{
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Write w = ret . write ( ) ;
2017-03-05 16:44:50 +01:00
copymem ( w . ptr ( ) , data , surface - > array_byte_size ) ;
2016-10-19 16:14:41 +02:00
}
glUnmapBuffer ( GL_ARRAY_BUFFER ) ;
2018-10-29 20:39:18 +01:00
# endif
2016-10-19 16:14:41 +02:00
2018-10-29 20:39:18 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2016-10-19 16:14:41 +02:00
return ret ;
2016-10-03 21:33:42 +02:00
}
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > RasterizerStorageGLES3 : : mesh_surface_get_index_array ( RID p_mesh , int p_surface ) const {
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , PoolVector < uint8_t > ( ) ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , PoolVector < uint8_t > ( ) ) ;
2016-10-19 16:14:41 +02:00
Surface * surface = mesh - > surfaces [ p_surface ] ;
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > ret ;
2016-11-10 03:55:06 +01:00
ret . resize ( surface - > index_array_byte_size ) ;
2019-01-12 15:44:20 +01:00
if ( surface - > index_array_byte_size > 0 ) {
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , surface - > index_id ) ;
2016-10-19 16:14:41 +02:00
2018-10-29 20:39:18 +01:00
# if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
2019-01-12 15:44:20 +01:00
{
PoolVector < uint8_t > : : Write w = ret . write ( ) ;
glGetBufferSubData ( GL_ELEMENT_ARRAY_BUFFER , 0 , surface - > index_array_byte_size , w . ptr ( ) ) ;
}
2018-10-29 20:39:18 +01:00
# else
2019-01-12 15:44:20 +01:00
void * data = glMapBufferRange ( GL_ELEMENT_ARRAY_BUFFER , 0 , surface - > index_array_byte_size , GL_MAP_READ_BIT ) ;
ERR_FAIL_NULL_V ( data , PoolVector < uint8_t > ( ) ) ;
{
PoolVector < uint8_t > : : Write w = ret . write ( ) ;
copymem ( w . ptr ( ) , data , surface - > index_array_byte_size ) ;
}
glUnmapBuffer ( GL_ELEMENT_ARRAY_BUFFER ) ;
2018-10-29 20:39:18 +01:00
# endif
2016-10-03 21:33:42 +02:00
2019-01-12 15:44:20 +01:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
}
2016-10-19 16:14:41 +02:00
return ret ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
uint32_t RasterizerStorageGLES3 : : mesh_surface_get_format ( RID p_mesh , int p_surface ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , 0 ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , 0 ) ;
2016-10-19 16:14:41 +02:00
return mesh - > surfaces [ p_surface ] - > format ;
2016-10-03 21:33:42 +02:00
}
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
VS : : PrimitiveType RasterizerStorageGLES3 : : mesh_surface_get_primitive_type ( RID p_mesh , int p_surface ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , VS : : PRIMITIVE_MAX ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , VS : : PRIMITIVE_MAX ) ;
2016-10-19 16:14:41 +02:00
return mesh - > surfaces [ p_surface ] - > primitive ;
2016-10-03 21:33:42 +02:00
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : mesh_surface_get_aabb ( RID p_mesh , int p_surface ) const {
2016-11-10 03:55:06 +01:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! mesh , AABB ( ) ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , AABB ( ) ) ;
2016-11-10 03:55:06 +01:00
return mesh - > surfaces [ p_surface ] - > aabb ;
}
2017-03-05 16:44:50 +01:00
Vector < PoolVector < uint8_t > > RasterizerStorageGLES3 : : mesh_surface_get_blend_shapes ( RID p_mesh , int p_surface ) const {
2016-11-10 03:55:06 +01:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , Vector < PoolVector < uint8_t > > ( ) ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , Vector < PoolVector < uint8_t > > ( ) ) ;
2016-11-10 03:55:06 +01:00
2017-01-07 22:25:37 +01:00
Vector < PoolVector < uint8_t > > bsarr ;
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < mesh - > surfaces [ p_surface ] - > blend_shapes . size ( ) ; i + + ) {
2016-11-10 03:55:06 +01:00
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > ret ;
2016-11-10 03:55:06 +01:00
ret . resize ( mesh - > surfaces [ p_surface ] - > array_byte_size ) ;
2018-10-29 20:39:18 +01:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , mesh - > surfaces [ p_surface ] - > blend_shapes [ i ] . vertex_id ) ;
2016-11-10 03:55:06 +01:00
2018-10-29 20:39:18 +01:00
# if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector < uint8_t > : : Write w = ret . write ( ) ;
glGetBufferSubData ( GL_ELEMENT_ARRAY_BUFFER , 0 , mesh - > surfaces [ p_surface ] - > array_byte_size , w . ptr ( ) ) ;
}
# else
void * data = glMapBufferRange ( GL_ELEMENT_ARRAY_BUFFER , 0 , mesh - > surfaces [ p_surface ] - > array_byte_size , GL_MAP_READ_BIT ) ;
ERR_FAIL_COND_V ( ! data , Vector < PoolVector < uint8_t > > ( ) ) ;
2016-11-10 03:55:06 +01:00
{
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Write w = ret . write ( ) ;
2017-03-05 16:44:50 +01:00
copymem ( w . ptr ( ) , data , mesh - > surfaces [ p_surface ] - > array_byte_size ) ;
2016-11-10 03:55:06 +01:00
}
2018-10-29 20:39:18 +01:00
glUnmapBuffer ( GL_ELEMENT_ARRAY_BUFFER ) ;
# endif
2016-11-10 03:55:06 +01:00
bsarr . push_back ( ret ) ;
}
return bsarr ;
}
2017-11-21 01:26:37 +01:00
2017-11-17 03:09:00 +01:00
Vector < AABB > RasterizerStorageGLES3 : : mesh_surface_get_skeleton_aabb ( RID p_mesh , int p_surface ) const {
2016-11-10 03:55:06 +01:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! mesh , Vector < AABB > ( ) ) ;
ERR_FAIL_INDEX_V ( p_surface , mesh - > surfaces . size ( ) , Vector < AABB > ( ) ) ;
2016-11-10 03:55:06 +01:00
return mesh - > surfaces [ p_surface ] - > skeleton_bone_aabb ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : mesh_remove_surface ( RID p_mesh , int p_surface ) {
2016-10-19 16:14:41 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_surface , mesh - > surfaces . size ( ) ) ;
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
Surface * surface = mesh - > surfaces [ p_surface ] ;
2016-10-03 21:33:42 +02:00
2016-11-10 03:55:06 +01:00
if ( surface - > material . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
_material_remove_geometry ( surface - > material , mesh - > surfaces [ p_surface ] ) ;
2016-11-10 03:55:06 +01:00
}
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & surface - > vertex_id ) ;
2016-10-19 16:14:41 +02:00
if ( surface - > index_id ) {
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & surface - > index_id ) ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
glDeleteVertexArrays ( 1 , & surface - > array_id ) ;
2017-06-16 02:39:16 +02:00
glDeleteVertexArrays ( 1 , & surface - > instancing_array_id ) ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < surface - > blend_shapes . size ( ) ; i + + ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & surface - > blend_shapes [ i ] . vertex_id ) ;
glDeleteVertexArrays ( 1 , & surface - > blend_shapes [ i ] . array_id ) ;
2016-10-19 16:14:41 +02:00
}
2017-06-11 20:52:03 +02:00
if ( surface - > index_wireframe_id ) {
glDeleteBuffers ( 1 , & surface - > index_wireframe_id ) ;
glDeleteVertexArrays ( 1 , & surface - > array_wireframe_id ) ;
glDeleteVertexArrays ( 1 , & surface - > instancing_array_wireframe_id ) ;
}
2017-06-11 23:13:04 +02:00
info . vertex_mem - = surface - > total_data_size ;
2016-10-19 16:14:41 +02:00
memdelete ( surface ) ;
mesh - > surfaces . remove ( p_surface ) ;
2018-11-14 13:32:39 +01:00
mesh - > instance_change_notify ( true , true ) ;
2016-10-03 21:33:42 +02:00
}
2017-11-21 01:26:37 +01:00
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : mesh_get_surface_count ( RID p_mesh ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! mesh , 0 ) ;
2016-10-19 16:14:41 +02:00
return mesh - > surfaces . size ( ) ;
2016-10-03 21:33:42 +02:00
}
2017-11-17 03:09:00 +01:00
void RasterizerStorageGLES3 : : mesh_set_custom_aabb ( RID p_mesh , const AABB & p_aabb ) {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
mesh - > custom_aabb = p_aabb ;
2018-11-14 13:32:39 +01:00
mesh - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-04-09 03:38:11 +02:00
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : mesh_get_custom_aabb ( RID p_mesh ) const {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
const Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! mesh , AABB ( ) ) ;
2016-10-19 16:14:41 +02:00
return mesh - > custom_aabb ;
2016-10-03 21:33:42 +02:00
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : mesh_get_aabb ( RID p_mesh , RID p_skeleton ) const {
2016-10-19 16:14:41 +02:00
2019-06-10 17:38:51 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! mesh , AABB ( ) ) ;
2016-10-19 16:14:41 +02:00
2018-11-19 14:42:27 +01:00
if ( mesh - > custom_aabb ! = AABB ( ) ) {
2016-10-19 16:14:41 +02:00
return mesh - > custom_aabb ;
2018-11-19 14:42:27 +01:00
}
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
Skeleton * sk = NULL ;
2018-11-19 14:42:27 +01:00
if ( p_skeleton . is_valid ( ) ) {
2019-06-10 17:38:51 +02:00
sk = skeleton_owner . getornull ( p_skeleton ) ;
2018-11-19 14:42:27 +01:00
}
2016-11-22 05:26:56 +01:00
2017-11-17 03:09:00 +01:00
AABB aabb ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
if ( sk & & sk - > size ! = 0 ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < mesh - > surfaces . size ( ) ; i + + ) {
2016-10-19 16:14:41 +02:00
2017-11-17 03:09:00 +01:00
AABB laabb ;
2017-09-07 21:48:50 +02:00
if ( ( mesh - > surfaces [ i ] - > format & VS : : ARRAY_FORMAT_BONES ) & & mesh - > surfaces [ i ] - > skeleton_bone_aabb . size ( ) ) {
2016-10-19 16:14:41 +02:00
int bs = mesh - > surfaces [ i ] - > skeleton_bone_aabb . size ( ) ;
2017-11-17 03:09:00 +01:00
const AABB * skbones = mesh - > surfaces [ i ] - > skeleton_bone_aabb . ptr ( ) ;
2016-10-19 16:14:41 +02:00
const bool * skused = mesh - > surfaces [ i ] - > skeleton_bone_used . ptr ( ) ;
2016-11-22 05:26:56 +01:00
int sbs = sk - > size ;
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( bs > sbs ) ;
2017-03-12 17:08:56 +01:00
const float * texture = sk - > skel_texture . ptr ( ) ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
bool first = true ;
2016-11-22 05:26:56 +01:00
if ( sk - > use_2d ) {
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < bs ; j + + ) {
2016-11-22 05:26:56 +01:00
if ( ! skused [ j ] )
continue ;
2017-03-12 17:08:56 +01:00
int base_ofs = ( ( j / 256 ) * 256 ) * 2 * 4 + ( j % 256 ) * 4 ;
2016-11-22 05:26:56 +01:00
Transform mtx ;
2017-03-24 00:14:12 +01:00
mtx . basis [ 0 ] . x = texture [ base_ofs + 0 ] ;
mtx . basis [ 0 ] . y = texture [ base_ofs + 1 ] ;
mtx . origin . x = texture [ base_ofs + 3 ] ;
base_ofs + = 256 * 4 ;
mtx . basis [ 1 ] . x = texture [ base_ofs + 0 ] ;
mtx . basis [ 1 ] . y = texture [ base_ofs + 1 ] ;
mtx . origin . y = texture [ base_ofs + 3 ] ;
2016-11-22 05:26:56 +01:00
2017-11-17 03:09:00 +01:00
AABB baabb = mtx . xform ( skbones [ j ] ) ;
2018-11-19 14:42:27 +01:00
2016-11-22 05:26:56 +01:00
if ( first ) {
2017-03-05 16:44:50 +01:00
laabb = baabb ;
first = false ;
2016-11-22 05:26:56 +01:00
} else {
laabb . merge_with ( baabb ) ;
}
}
} else {
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < bs ; j + + ) {
2016-11-22 05:26:56 +01:00
if ( ! skused [ j ] )
continue ;
2017-03-12 17:08:56 +01:00
int base_ofs = ( ( j / 256 ) * 256 ) * 3 * 4 + ( j % 256 ) * 4 ;
2016-11-22 05:26:56 +01:00
Transform mtx ;
2017-03-12 17:08:56 +01:00
2017-03-24 00:14:12 +01:00
mtx . basis [ 0 ] . x = texture [ base_ofs + 0 ] ;
mtx . basis [ 0 ] . y = texture [ base_ofs + 1 ] ;
mtx . basis [ 0 ] . z = texture [ base_ofs + 2 ] ;
mtx . origin . x = texture [ base_ofs + 3 ] ;
base_ofs + = 256 * 4 ;
mtx . basis [ 1 ] . x = texture [ base_ofs + 0 ] ;
mtx . basis [ 1 ] . y = texture [ base_ofs + 1 ] ;
mtx . basis [ 1 ] . z = texture [ base_ofs + 2 ] ;
mtx . origin . y = texture [ base_ofs + 3 ] ;
base_ofs + = 256 * 4 ;
mtx . basis [ 2 ] . x = texture [ base_ofs + 0 ] ;
mtx . basis [ 2 ] . y = texture [ base_ofs + 1 ] ;
mtx . basis [ 2 ] . z = texture [ base_ofs + 2 ] ;
mtx . origin . z = texture [ base_ofs + 3 ] ;
2017-03-05 16:44:50 +01:00
2017-11-17 03:09:00 +01:00
AABB baabb = mtx . xform ( skbones [ j ] ) ;
2016-11-22 05:26:56 +01:00
if ( first ) {
2017-03-05 16:44:50 +01:00
laabb = baabb ;
first = false ;
2016-11-22 05:26:56 +01:00
} else {
laabb . merge_with ( baabb ) ;
}
2016-10-19 16:14:41 +02:00
}
}
} else {
2017-03-05 16:44:50 +01:00
laabb = mesh - > surfaces [ i ] - > aabb ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
if ( i = = 0 )
aabb = laabb ;
2016-10-19 16:14:41 +02:00
else
aabb . merge_with ( laabb ) ;
}
} else {
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < mesh - > surfaces . size ( ) ; i + + ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
if ( i = = 0 )
aabb = mesh - > surfaces [ i ] - > aabb ;
2016-10-19 16:14:41 +02:00
else
aabb . merge_with ( mesh - > surfaces [ i ] - > aabb ) ;
}
}
2016-11-22 05:26:56 +01:00
2016-10-19 16:14:41 +02:00
return aabb ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : mesh_clear ( RID p_mesh ) {
2016-10-03 21:33:42 +02:00
2016-10-19 16:14:41 +02:00
Mesh * mesh = mesh_owner . getornull ( p_mesh ) ;
ERR_FAIL_COND ( ! mesh ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
while ( mesh - > surfaces . size ( ) ) {
mesh_remove_surface ( p_mesh , 0 ) ;
2016-10-19 16:14:41 +02:00
}
2016-10-03 21:33:42 +02:00
}
2017-11-25 04:07:54 +01:00
void RasterizerStorageGLES3 : : mesh_render_blend_shapes ( Surface * s , const float * p_weights ) {
2016-11-25 00:46:55 +01:00
glBindVertexArray ( s - > array_id ) ;
2017-03-05 16:44:50 +01:00
BlendShapeShaderGLES3 : : Conditionals cond [ VS : : ARRAY_MAX - 1 ] = {
2016-11-25 00:46:55 +01:00
BlendShapeShaderGLES3 : : ENABLE_NORMAL , //will be ignored
BlendShapeShaderGLES3 : : ENABLE_NORMAL ,
BlendShapeShaderGLES3 : : ENABLE_TANGENT ,
BlendShapeShaderGLES3 : : ENABLE_COLOR ,
BlendShapeShaderGLES3 : : ENABLE_UV ,
BlendShapeShaderGLES3 : : ENABLE_UV2 ,
BlendShapeShaderGLES3 : : ENABLE_SKELETON ,
BlendShapeShaderGLES3 : : ENABLE_SKELETON ,
} ;
2017-03-05 16:44:50 +01:00
int stride = 0 ;
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
if ( s - > format & VS : : ARRAY_FLAG_USE_2D_VERTICES ) {
stride = 2 * 4 ;
2016-11-25 00:46:55 +01:00
} else {
2017-03-05 16:44:50 +01:00
stride = 3 * 4 ;
}
static const int sizes [ VS : : ARRAY_MAX - 1 ] = {
3 * 4 ,
3 * 4 ,
4 * 4 ,
4 * 4 ,
2 * 4 ,
2 * 4 ,
4 * 4 ,
4 * 4
2016-11-25 00:46:55 +01:00
} ;
2017-03-05 16:44:50 +01:00
for ( int i = 1 ; i < VS : : ARRAY_MAX - 1 ; i + + ) {
shaders . blend_shapes . set_conditional ( cond [ i ] , s - > format & ( 1 < < i ) ) ; //enable conditional for format
if ( s - > format & ( 1 < < i ) ) {
stride + = sizes [ i ] ;
2016-11-25 00:46:55 +01:00
}
}
//copy all first
2017-03-05 16:44:50 +01:00
float base_weight = 1.0 ;
2016-11-25 00:46:55 +01:00
2017-01-12 12:34:00 +01:00
int mtc = s - > blend_shapes . size ( ) ;
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
if ( s - > mesh - > blend_shape_mode = = VS : : BLEND_SHAPE_MODE_NORMALIZED ) {
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < mtc ; i + + ) {
base_weight - = p_weights [ i ] ;
2016-11-25 00:46:55 +01:00
}
}
2017-03-05 16:44:50 +01:00
shaders . blend_shapes . set_conditional ( BlendShapeShaderGLES3 : : ENABLE_BLEND , false ) ; //first pass does not blend
shaders . blend_shapes . set_conditional ( BlendShapeShaderGLES3 : : USE_2D_VERTEX , s - > format & VS : : ARRAY_FLAG_USE_2D_VERTICES ) ; //use 2D vertices if needed
2016-11-25 00:46:55 +01:00
shaders . blend_shapes . bind ( ) ;
2017-03-05 16:44:50 +01:00
shaders . blend_shapes . set_uniform ( BlendShapeShaderGLES3 : : BLEND_AMOUNT , base_weight ) ;
2016-11-25 00:46:55 +01:00
glEnable ( GL_RASTERIZER_DISCARD ) ;
glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER , 0 , resources . transform_feedback_buffers [ 0 ] ) ;
glBeginTransformFeedback ( GL_POINTS ) ;
2017-03-05 16:44:50 +01:00
glDrawArrays ( GL_POINTS , 0 , s - > array_len ) ;
2016-11-25 00:46:55 +01:00
glEndTransformFeedback ( ) ;
2017-03-05 16:44:50 +01:00
shaders . blend_shapes . set_conditional ( BlendShapeShaderGLES3 : : ENABLE_BLEND , true ) ; //first pass does not blend
2016-11-25 00:46:55 +01:00
shaders . blend_shapes . bind ( ) ;
2017-03-05 16:44:50 +01:00
for ( int ti = 0 ; ti < mtc ; ti + + ) {
2016-11-25 00:46:55 +01:00
float weight = p_weights [ ti ] ;
2019-04-03 19:24:00 +02:00
if ( weight < 0.00001 ) //not bother with this one
2016-11-25 00:46:55 +01:00
continue ;
2017-01-12 12:34:00 +01:00
glBindVertexArray ( s - > blend_shapes [ ti ] . array_id ) ;
2016-11-25 00:46:55 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , resources . transform_feedback_buffers [ 0 ] ) ;
glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER , 0 , resources . transform_feedback_buffers [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
shaders . blend_shapes . set_uniform ( BlendShapeShaderGLES3 : : BLEND_AMOUNT , weight ) ;
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
int ofs = 0 ;
for ( int i = 0 ; i < VS : : ARRAY_MAX - 1 ; i + + ) {
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
if ( s - > format & ( 1 < < i ) ) {
glEnableVertexAttribArray ( i + 8 ) ;
switch ( i ) {
2016-11-25 00:46:55 +01:00
case VS : : ARRAY_VERTEX : {
2017-03-05 16:44:50 +01:00
if ( s - > format & VS : : ARRAY_FLAG_USE_2D_VERTICES ) {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 2 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 2 * 4 ;
2016-11-25 00:46:55 +01:00
} else {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 3 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 3 * 4 ;
2016-11-25 00:46:55 +01:00
}
} break ;
case VS : : ARRAY_NORMAL : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 3 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 3 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_TANGENT : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_COLOR : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_TEX_UV : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 2 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 2 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_TEX_UV2 : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 2 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 2 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_BONES : {
2019-02-27 10:07:30 +01:00
glVertexAttribIPointer ( i + 8 , 4 , GL_UNSIGNED_INT , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_WEIGHTS : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i + 8 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
}
} else {
2017-03-05 16:44:50 +01:00
glDisableVertexAttribArray ( i + 8 ) ;
2016-11-25 00:46:55 +01:00
}
}
glBeginTransformFeedback ( GL_POINTS ) ;
2017-03-05 16:44:50 +01:00
glDrawArrays ( GL_POINTS , 0 , s - > array_len ) ;
2016-11-25 00:46:55 +01:00
glEndTransformFeedback ( ) ;
2017-03-05 16:44:50 +01:00
SWAP ( resources . transform_feedback_buffers [ 0 ] , resources . transform_feedback_buffers [ 1 ] ) ;
2016-11-25 00:46:55 +01:00
}
glDisable ( GL_RASTERIZER_DISCARD ) ;
glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER , 0 , 0 ) ;
glBindVertexArray ( resources . transform_feedback_array ) ;
glBindBuffer ( GL_ARRAY_BUFFER , resources . transform_feedback_buffers [ 0 ] ) ;
2017-03-05 16:44:50 +01:00
int ofs = 0 ;
for ( int i = 0 ; i < VS : : ARRAY_MAX - 1 ; i + + ) {
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
if ( s - > format & ( 1 < < i ) ) {
2016-11-25 00:46:55 +01:00
glEnableVertexAttribArray ( i ) ;
2017-03-05 16:44:50 +01:00
switch ( i ) {
2016-11-25 00:46:55 +01:00
case VS : : ARRAY_VERTEX : {
2017-03-05 16:44:50 +01:00
if ( s - > format & VS : : ARRAY_FLAG_USE_2D_VERTICES ) {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 2 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 2 * 4 ;
2016-11-25 00:46:55 +01:00
} else {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 3 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 3 * 4 ;
2016-11-25 00:46:55 +01:00
}
} break ;
case VS : : ARRAY_NORMAL : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 3 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 3 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_TANGENT : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_COLOR : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_TEX_UV : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 2 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 2 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_TEX_UV2 : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 2 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 2 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_BONES : {
2019-02-27 10:07:30 +01:00
glVertexAttribIPointer ( i , 4 , GL_UNSIGNED_INT , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
case VS : : ARRAY_WEIGHTS : {
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( i , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( ofs ) ) ;
2017-03-05 16:44:50 +01:00
ofs + = 4 * 4 ;
2016-11-25 00:46:55 +01:00
} break ;
}
} else {
glDisableVertexAttribArray ( i ) ;
}
}
if ( s - > index_array_len ) {
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , s - > index_id ) ;
2016-11-25 00:46:55 +01:00
}
}
2016-10-03 21:33:42 +02:00
/* MULTIMESH API */
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : multimesh_create ( ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
MultiMesh * multimesh = memnew ( MultiMesh ) ;
2016-11-22 05:26:56 +01:00
return multimesh_owner . make_rid ( multimesh ) ;
2016-10-03 21:33:42 +02:00
}
2018-07-07 01:21:13 +02:00
void RasterizerStorageGLES3 : : multimesh_allocate ( RID p_multimesh , int p_instances , VS : : MultimeshTransformFormat p_transform_format , VS : : MultimeshColorFormat p_color_format , VS : : MultimeshCustomDataFormat p_data_format ) {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
2018-07-07 01:21:13 +02:00
if ( multimesh - > size = = p_instances & & multimesh - > transform_format = = p_transform_format & & multimesh - > color_format = = p_color_format & & multimesh - > custom_data_format = = p_data_format )
2016-11-22 05:26:56 +01:00
return ;
if ( multimesh - > buffer ) {
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & multimesh - > buffer ) ;
2016-11-22 05:26:56 +01:00
multimesh - > data . resize ( 0 ) ;
2019-12-28 19:35:23 +01:00
multimesh - > buffer = 0 ;
2016-11-22 05:26:56 +01:00
}
2017-03-05 16:44:50 +01:00
multimesh - > size = p_instances ;
multimesh - > transform_format = p_transform_format ;
multimesh - > color_format = p_color_format ;
2018-07-07 01:21:13 +02:00
multimesh - > custom_data_format = p_data_format ;
2016-11-22 05:26:56 +01:00
if ( multimesh - > size ) {
2017-03-05 16:44:50 +01:00
if ( multimesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_2D ) {
multimesh - > xform_floats = 8 ;
2016-11-22 05:26:56 +01:00
} else {
2017-03-05 16:44:50 +01:00
multimesh - > xform_floats = 12 ;
2016-11-22 05:26:56 +01:00
}
2020-01-13 02:45:06 +01:00
if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_8BIT ) {
2017-03-05 16:44:50 +01:00
multimesh - > color_floats = 1 ;
} else if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_FLOAT ) {
multimesh - > color_floats = 4 ;
2020-01-13 02:45:06 +01:00
} else {
multimesh - > color_floats = 0 ;
2016-11-22 05:26:56 +01:00
}
2020-01-13 02:45:06 +01:00
if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_8BIT ) {
2018-07-07 01:21:13 +02:00
multimesh - > custom_data_floats = 1 ;
} else if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_FLOAT ) {
multimesh - > custom_data_floats = 4 ;
2020-01-13 02:45:06 +01:00
} else {
multimesh - > custom_data_floats = 0 ;
2018-07-07 01:21:13 +02:00
}
int format_floats = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2017-03-05 16:44:50 +01:00
multimesh - > data . resize ( format_floats * p_instances ) ;
2018-07-07 01:21:13 +02:00
2018-10-08 05:51:48 +02:00
float * dataptr = multimesh - > data . ptrw ( ) ;
2018-07-10 23:13:59 +02:00
for ( int i = 0 ; i < p_instances * format_floats ; i + = format_floats ) {
2017-03-05 16:44:50 +01:00
int color_from = 0 ;
2018-07-07 01:21:13 +02:00
int custom_data_from = 0 ;
2017-03-05 16:44:50 +01:00
if ( multimesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_2D ) {
2018-10-08 05:51:48 +02:00
dataptr [ i + 0 ] = 1.0 ;
dataptr [ i + 1 ] = 0.0 ;
dataptr [ i + 2 ] = 0.0 ;
dataptr [ i + 3 ] = 0.0 ;
dataptr [ i + 4 ] = 0.0 ;
dataptr [ i + 5 ] = 1.0 ;
dataptr [ i + 6 ] = 0.0 ;
dataptr [ i + 7 ] = 0.0 ;
2017-03-05 16:44:50 +01:00
color_from = 8 ;
2018-07-07 01:21:13 +02:00
custom_data_from = 8 ;
2016-11-22 05:26:56 +01:00
} else {
2018-10-08 05:51:48 +02:00
dataptr [ i + 0 ] = 1.0 ;
dataptr [ i + 1 ] = 0.0 ;
dataptr [ i + 2 ] = 0.0 ;
dataptr [ i + 3 ] = 0.0 ;
dataptr [ i + 4 ] = 0.0 ;
dataptr [ i + 5 ] = 1.0 ;
dataptr [ i + 6 ] = 0.0 ;
dataptr [ i + 7 ] = 0.0 ;
dataptr [ i + 8 ] = 0.0 ;
dataptr [ i + 9 ] = 0.0 ;
dataptr [ i + 10 ] = 1.0 ;
dataptr [ i + 11 ] = 0.0 ;
2017-03-05 16:44:50 +01:00
color_from = 12 ;
2018-07-07 01:21:13 +02:00
custom_data_from = 12 ;
2016-11-22 05:26:56 +01:00
}
2017-03-05 16:44:50 +01:00
if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_NONE ) {
2016-11-22 05:26:56 +01:00
//none
2017-03-05 16:44:50 +01:00
} else if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_8BIT ) {
2016-11-22 05:26:56 +01:00
union {
uint32_t colu ;
float colf ;
} cu ;
2017-03-05 16:44:50 +01:00
cu . colu = 0xFFFFFFFF ;
2018-10-08 05:51:48 +02:00
dataptr [ i + color_from + 0 ] = cu . colf ;
2018-07-07 01:21:13 +02:00
custom_data_from = color_from + 1 ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
} else if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_FLOAT ) {
2018-10-08 05:51:48 +02:00
dataptr [ i + color_from + 0 ] = 1.0 ;
dataptr [ i + color_from + 1 ] = 1.0 ;
dataptr [ i + color_from + 2 ] = 1.0 ;
dataptr [ i + color_from + 3 ] = 1.0 ;
2018-07-07 01:21:13 +02:00
custom_data_from = color_from + 4 ;
}
if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_NONE ) {
//none
} else if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_8BIT ) {
union {
uint32_t colu ;
float colf ;
} cu ;
cu . colu = 0 ;
2018-10-08 05:51:48 +02:00
dataptr [ i + custom_data_from + 0 ] = cu . colf ;
2018-07-07 01:21:13 +02:00
} else if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_FLOAT ) {
2018-10-08 05:51:48 +02:00
dataptr [ i + custom_data_from + 0 ] = 0.0 ;
dataptr [ i + custom_data_from + 1 ] = 0.0 ;
dataptr [ i + custom_data_from + 2 ] = 0.0 ;
dataptr [ i + custom_data_from + 3 ] = 0.0 ;
2016-11-22 05:26:56 +01:00
}
}
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & multimesh - > buffer ) ;
glBindBuffer ( GL_ARRAY_BUFFER , multimesh - > buffer ) ;
2017-10-03 22:34:08 +02:00
glBufferData ( GL_ARRAY_BUFFER , multimesh - > data . size ( ) * sizeof ( float ) , NULL , GL_STATIC_DRAW ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2016-11-22 05:26:56 +01:00
}
2017-03-05 16:44:50 +01:00
multimesh - > dirty_data = true ;
multimesh - > dirty_aabb = true ;
2016-11-22 05:26:56 +01:00
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : multimesh_get_instance_count ( RID p_multimesh ) const {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! multimesh , 0 ) ;
2016-11-22 05:26:56 +01:00
return multimesh - > size ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : multimesh_set_mesh ( RID p_multimesh , RID p_mesh ) {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
2016-10-03 21:33:42 +02:00
2017-02-16 12:55:11 +01:00
if ( multimesh - > mesh . is_valid ( ) ) {
Mesh * mesh = mesh_owner . getornull ( multimesh - > mesh ) ;
if ( mesh ) {
mesh - > multimeshes . remove ( & multimesh - > mesh_list ) ;
}
}
2017-03-05 16:44:50 +01:00
multimesh - > mesh = p_mesh ;
2017-02-16 12:55:11 +01:00
if ( multimesh - > mesh . is_valid ( ) ) {
Mesh * mesh = mesh_owner . getornull ( multimesh - > mesh ) ;
if ( mesh ) {
mesh - > multimeshes . add ( & multimesh - > mesh_list ) ;
}
}
2017-03-05 16:44:50 +01:00
multimesh - > dirty_aabb = true ;
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : multimesh_instance_set_transform ( RID p_multimesh , int p_index , const Transform & p_transform ) {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_index , multimesh - > size ) ;
ERR_FAIL_COND ( multimesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_2D ) ;
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index ] ;
2017-03-05 16:44:50 +01:00
dataptr [ 0 ] = p_transform . basis . elements [ 0 ] [ 0 ] ;
dataptr [ 1 ] = p_transform . basis . elements [ 0 ] [ 1 ] ;
dataptr [ 2 ] = p_transform . basis . elements [ 0 ] [ 2 ] ;
dataptr [ 3 ] = p_transform . origin . x ;
dataptr [ 4 ] = p_transform . basis . elements [ 1 ] [ 0 ] ;
dataptr [ 5 ] = p_transform . basis . elements [ 1 ] [ 1 ] ;
dataptr [ 6 ] = p_transform . basis . elements [ 1 ] [ 2 ] ;
dataptr [ 7 ] = p_transform . origin . y ;
dataptr [ 8 ] = p_transform . basis . elements [ 2 ] [ 0 ] ;
dataptr [ 9 ] = p_transform . basis . elements [ 2 ] [ 1 ] ;
dataptr [ 10 ] = p_transform . basis . elements [ 2 ] [ 2 ] ;
dataptr [ 11 ] = p_transform . origin . z ;
multimesh - > dirty_data = true ;
multimesh - > dirty_aabb = true ;
2016-11-22 05:26:56 +01:00
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : multimesh_instance_set_transform_2d ( RID p_multimesh , int p_index , const Transform2D & p_transform ) {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_index , multimesh - > size ) ;
ERR_FAIL_COND ( multimesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_3D ) ;
2016-10-03 21:33:42 +02:00
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index ] ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
dataptr [ 0 ] = p_transform . elements [ 0 ] [ 0 ] ;
dataptr [ 1 ] = p_transform . elements [ 1 ] [ 0 ] ;
dataptr [ 2 ] = 0 ;
dataptr [ 3 ] = p_transform . elements [ 2 ] [ 0 ] ;
dataptr [ 4 ] = p_transform . elements [ 0 ] [ 1 ] ;
dataptr [ 5 ] = p_transform . elements [ 1 ] [ 1 ] ;
dataptr [ 6 ] = 0 ;
dataptr [ 7 ] = p_transform . elements [ 2 ] [ 1 ] ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
multimesh - > dirty_data = true ;
multimesh - > dirty_aabb = true ;
2016-11-22 05:26:56 +01:00
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : multimesh_instance_set_color ( RID p_multimesh , int p_index , const Color & p_color ) {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_index , multimesh - > size ) ;
ERR_FAIL_COND ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_NONE ) ;
2020-01-16 19:58:45 +01:00
ERR_FAIL_INDEX ( multimesh - > color_format , VS : : MULTIMESH_COLOR_MAX ) ;
2016-10-03 21:33:42 +02:00
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index + multimesh - > xform_floats ] ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_8BIT ) {
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
uint8_t * data8 = ( uint8_t * ) dataptr ;
data8 [ 0 ] = CLAMP ( p_color . r * 255.0 , 0 , 255 ) ;
data8 [ 1 ] = CLAMP ( p_color . g * 255.0 , 0 , 255 ) ;
data8 [ 2 ] = CLAMP ( p_color . b * 255.0 , 0 , 255 ) ;
data8 [ 3 ] = CLAMP ( p_color . a * 255.0 , 0 , 255 ) ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
} else if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_FLOAT ) {
dataptr [ 0 ] = p_color . r ;
dataptr [ 1 ] = p_color . g ;
dataptr [ 2 ] = p_color . b ;
dataptr [ 3 ] = p_color . a ;
2016-11-22 05:26:56 +01:00
}
2017-03-05 16:44:50 +01:00
multimesh - > dirty_data = true ;
multimesh - > dirty_aabb = true ;
2016-11-22 05:26:56 +01:00
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2018-07-07 01:21:13 +02:00
void RasterizerStorageGLES3 : : multimesh_instance_set_custom_data ( RID p_multimesh , int p_index , const Color & p_custom_data ) {
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
ERR_FAIL_INDEX ( p_index , multimesh - > size ) ;
ERR_FAIL_COND ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_NONE ) ;
2020-01-16 19:58:45 +01:00
ERR_FAIL_INDEX ( multimesh - > custom_data_format , VS : : MULTIMESH_CUSTOM_DATA_MAX ) ;
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index + multimesh - > xform_floats + multimesh - > color_floats ] ;
2018-07-07 01:21:13 +02:00
if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_8BIT ) {
uint8_t * data8 = ( uint8_t * ) dataptr ;
data8 [ 0 ] = CLAMP ( p_custom_data . r * 255.0 , 0 , 255 ) ;
data8 [ 1 ] = CLAMP ( p_custom_data . g * 255.0 , 0 , 255 ) ;
data8 [ 2 ] = CLAMP ( p_custom_data . b * 255.0 , 0 , 255 ) ;
data8 [ 3 ] = CLAMP ( p_custom_data . a * 255.0 , 0 , 255 ) ;
} else if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_FLOAT ) {
dataptr [ 0 ] = p_custom_data . r ;
dataptr [ 1 ] = p_custom_data . g ;
dataptr [ 2 ] = p_custom_data . b ;
dataptr [ 3 ] = p_custom_data . a ;
}
multimesh - > dirty_data = true ;
multimesh - > dirty_aabb = true ;
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
}
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : multimesh_get_mesh ( RID p_multimesh ) const {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! multimesh , RID ( ) ) ;
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
return multimesh - > mesh ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
Transform RasterizerStorageGLES3 : : multimesh_instance_get_transform ( RID p_multimesh , int p_index ) const {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! multimesh , Transform ( ) ) ;
ERR_FAIL_INDEX_V ( p_index , multimesh - > size , Transform ( ) ) ;
ERR_FAIL_COND_V ( multimesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_2D , Transform ( ) ) ;
2016-11-22 05:26:56 +01:00
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index ] ;
2016-11-22 05:26:56 +01:00
Transform xform ;
2017-03-05 16:44:50 +01:00
xform . basis . elements [ 0 ] [ 0 ] = dataptr [ 0 ] ;
xform . basis . elements [ 0 ] [ 1 ] = dataptr [ 1 ] ;
xform . basis . elements [ 0 ] [ 2 ] = dataptr [ 2 ] ;
xform . origin . x = dataptr [ 3 ] ;
xform . basis . elements [ 1 ] [ 0 ] = dataptr [ 4 ] ;
xform . basis . elements [ 1 ] [ 1 ] = dataptr [ 5 ] ;
xform . basis . elements [ 1 ] [ 2 ] = dataptr [ 6 ] ;
xform . origin . y = dataptr [ 7 ] ;
xform . basis . elements [ 2 ] [ 0 ] = dataptr [ 8 ] ;
xform . basis . elements [ 2 ] [ 1 ] = dataptr [ 9 ] ;
xform . basis . elements [ 2 ] [ 2 ] = dataptr [ 10 ] ;
xform . origin . z = dataptr [ 11 ] ;
2016-11-22 05:26:56 +01:00
return xform ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
Transform2D RasterizerStorageGLES3 : : multimesh_instance_get_transform_2d ( RID p_multimesh , int p_index ) const {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! multimesh , Transform2D ( ) ) ;
ERR_FAIL_INDEX_V ( p_index , multimesh - > size , Transform2D ( ) ) ;
ERR_FAIL_COND_V ( multimesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_3D , Transform2D ( ) ) ;
2016-10-03 21:33:42 +02:00
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index ] ;
2016-11-22 05:26:56 +01:00
2017-01-11 04:52:51 +01:00
Transform2D xform ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
xform . elements [ 0 ] [ 0 ] = dataptr [ 0 ] ;
xform . elements [ 1 ] [ 0 ] = dataptr [ 1 ] ;
xform . elements [ 2 ] [ 0 ] = dataptr [ 3 ] ;
xform . elements [ 0 ] [ 1 ] = dataptr [ 4 ] ;
xform . elements [ 1 ] [ 1 ] = dataptr [ 5 ] ;
xform . elements [ 2 ] [ 1 ] = dataptr [ 7 ] ;
2016-11-22 05:26:56 +01:00
return xform ;
2016-10-03 21:33:42 +02:00
}
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
Color RasterizerStorageGLES3 : : multimesh_instance_get_color ( RID p_multimesh , int p_index ) const {
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! multimesh , Color ( ) ) ;
ERR_FAIL_INDEX_V ( p_index , multimesh - > size , Color ( ) ) ;
ERR_FAIL_COND_V ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_NONE , Color ( ) ) ;
2020-01-16 19:58:45 +01:00
ERR_FAIL_INDEX_V ( multimesh - > color_format , VS : : MULTIMESH_COLOR_MAX , Color ( ) ) ;
2016-11-22 05:26:56 +01:00
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index + multimesh - > xform_floats ] ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_8BIT ) {
2016-11-22 05:26:56 +01:00
union {
uint32_t colu ;
float colf ;
} cu ;
2017-08-12 16:17:53 +02:00
cu . colf = dataptr [ 0 ] ;
2016-12-20 04:21:07 +01:00
return Color : : hex ( BSWAP32 ( cu . colu ) ) ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
} else if ( multimesh - > color_format = = VS : : MULTIMESH_COLOR_FLOAT ) {
2016-11-22 05:26:56 +01:00
Color c ;
2017-03-05 16:44:50 +01:00
c . r = dataptr [ 0 ] ;
c . g = dataptr [ 1 ] ;
c . b = dataptr [ 2 ] ;
c . a = dataptr [ 3 ] ;
2016-11-22 05:26:56 +01:00
return c ;
}
2016-10-03 21:33:42 +02:00
return Color ( ) ;
}
2018-07-07 01:21:13 +02:00
Color RasterizerStorageGLES3 : : multimesh_instance_get_custom_data ( RID p_multimesh , int p_index ) const {
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND_V ( ! multimesh , Color ( ) ) ;
ERR_FAIL_INDEX_V ( p_index , multimesh - > size , Color ( ) ) ;
ERR_FAIL_COND_V ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_NONE , Color ( ) ) ;
2020-01-16 19:58:45 +01:00
ERR_FAIL_INDEX_V ( multimesh - > custom_data_format , VS : : MULTIMESH_CUSTOM_DATA_MAX , Color ( ) ) ;
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2018-07-25 03:11:03 +02:00
float * dataptr = & multimesh - > data . write [ stride * p_index + multimesh - > xform_floats + multimesh - > color_floats ] ;
2018-07-07 01:21:13 +02:00
if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_8BIT ) {
union {
uint32_t colu ;
float colf ;
} cu ;
cu . colf = dataptr [ 0 ] ;
return Color : : hex ( BSWAP32 ( cu . colu ) ) ;
} else if ( multimesh - > custom_data_format = = VS : : MULTIMESH_CUSTOM_DATA_FLOAT ) {
Color c ;
c . r = dataptr [ 0 ] ;
c . g = dataptr [ 1 ] ;
c . b = dataptr [ 2 ] ;
c . a = dataptr [ 3 ] ;
return c ;
}
return Color ( ) ;
}
void RasterizerStorageGLES3 : : multimesh_set_as_bulk_array ( RID p_multimesh , const PoolVector < float > & p_array ) {
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
2019-10-28 08:07:29 +01:00
ERR_FAIL_COND ( ! multimesh - > data . ptr ( ) ) ;
2018-07-07 01:21:13 +02:00
int dsize = multimesh - > data . size ( ) ;
ERR_FAIL_COND ( dsize ! = p_array . size ( ) ) ;
PoolVector < float > : : Read r = p_array . read ( ) ;
copymem ( multimesh - > data . ptrw ( ) , r . ptr ( ) , dsize * sizeof ( float ) ) ;
multimesh - > dirty_data = true ;
multimesh - > dirty_aabb = true ;
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : multimesh_set_visible_instances ( RID p_multimesh , int p_visible ) {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
ERR_FAIL_COND ( ! multimesh ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
multimesh - > visible_instances = p_visible ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : multimesh_get_visible_instances ( RID p_multimesh ) const {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! multimesh , - 1 ) ;
2016-11-22 05:26:56 +01:00
return multimesh - > visible_instances ;
2016-10-03 21:33:42 +02:00
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : multimesh_get_aabb ( RID p_multimesh ) const {
2016-10-03 21:33:42 +02:00
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_multimesh ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! multimesh , AABB ( ) ) ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
const_cast < RasterizerStorageGLES3 * > ( this ) - > update_dirty_multimeshes ( ) ; //update pending AABBs
2016-11-22 05:26:56 +01:00
return multimesh - > aabb ;
}
void RasterizerStorageGLES3 : : update_dirty_multimeshes ( ) {
2017-03-05 16:44:50 +01:00
while ( multimesh_update_list . first ( ) ) {
2016-11-22 05:26:56 +01:00
MultiMesh * multimesh = multimesh_update_list . first ( ) - > self ( ) ;
if ( multimesh - > size & & multimesh - > dirty_data ) {
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , multimesh - > buffer ) ;
glBufferSubData ( GL_ARRAY_BUFFER , 0 , multimesh - > data . size ( ) * sizeof ( float ) , multimesh - > data . ptr ( ) ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2016-11-22 05:26:56 +01:00
}
if ( multimesh - > size & & multimesh - > dirty_aabb ) {
2017-11-17 03:09:00 +01:00
AABB mesh_aabb ;
2016-11-22 05:26:56 +01:00
if ( multimesh - > mesh . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
mesh_aabb = mesh_get_aabb ( multimesh - > mesh , RID ( ) ) ;
2016-11-22 05:26:56 +01:00
} else {
2017-03-05 16:44:50 +01:00
mesh_aabb . size + = Vector3 ( 0.001 , 0.001 , 0.001 ) ;
2016-11-22 05:26:56 +01:00
}
2018-07-07 01:21:13 +02:00
int stride = multimesh - > color_floats + multimesh - > xform_floats + multimesh - > custom_data_floats ;
2016-11-22 05:26:56 +01:00
int count = multimesh - > data . size ( ) ;
2017-11-25 04:07:54 +01:00
float * data = multimesh - > data . ptrw ( ) ;
2016-11-22 05:26:56 +01:00
2017-11-17 03:09:00 +01:00
AABB aabb ;
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
if ( multimesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_2D ) {
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < count ; i + = stride ) {
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
float * dataptr = & data [ i ] ;
2016-11-22 05:26:56 +01:00
Transform xform ;
2017-03-05 16:44:50 +01:00
xform . basis [ 0 ] [ 0 ] = dataptr [ 0 ] ;
xform . basis [ 0 ] [ 1 ] = dataptr [ 1 ] ;
xform . origin [ 0 ] = dataptr [ 3 ] ;
xform . basis [ 1 ] [ 0 ] = dataptr [ 4 ] ;
xform . basis [ 1 ] [ 1 ] = dataptr [ 5 ] ;
xform . origin [ 1 ] = dataptr [ 7 ] ;
2016-11-22 05:26:56 +01:00
2017-11-17 03:09:00 +01:00
AABB laabb = xform . xform ( mesh_aabb ) ;
2017-03-05 16:44:50 +01:00
if ( i = = 0 )
aabb = laabb ;
2016-11-22 05:26:56 +01:00
else
aabb . merge_with ( laabb ) ;
}
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < count ; i + = stride ) {
2016-11-22 05:26:56 +01:00
2017-03-05 16:44:50 +01:00
float * dataptr = & data [ i ] ;
2016-11-22 05:26:56 +01:00
Transform xform ;
2017-03-05 16:44:50 +01:00
xform . basis . elements [ 0 ] [ 0 ] = dataptr [ 0 ] ;
xform . basis . elements [ 0 ] [ 1 ] = dataptr [ 1 ] ;
xform . basis . elements [ 0 ] [ 2 ] = dataptr [ 2 ] ;
xform . origin . x = dataptr [ 3 ] ;
xform . basis . elements [ 1 ] [ 0 ] = dataptr [ 4 ] ;
xform . basis . elements [ 1 ] [ 1 ] = dataptr [ 5 ] ;
xform . basis . elements [ 1 ] [ 2 ] = dataptr [ 6 ] ;
xform . origin . y = dataptr [ 7 ] ;
xform . basis . elements [ 2 ] [ 0 ] = dataptr [ 8 ] ;
xform . basis . elements [ 2 ] [ 1 ] = dataptr [ 9 ] ;
xform . basis . elements [ 2 ] [ 2 ] = dataptr [ 10 ] ;
xform . origin . z = dataptr [ 11 ] ;
2016-11-22 05:26:56 +01:00
2017-11-17 03:09:00 +01:00
AABB laabb = xform . xform ( mesh_aabb ) ;
2017-03-05 16:44:50 +01:00
if ( i = = 0 )
aabb = laabb ;
2016-11-22 05:26:56 +01:00
else
aabb . merge_with ( laabb ) ;
}
}
2017-03-05 16:44:50 +01:00
multimesh - > aabb = aabb ;
2016-11-22 05:26:56 +01:00
}
2017-03-05 16:44:50 +01:00
multimesh - > dirty_aabb = false ;
multimesh - > dirty_data = false ;
2016-11-22 05:26:56 +01:00
2018-11-14 13:32:39 +01:00
multimesh - > instance_change_notify ( true , false ) ;
2016-11-22 05:26:56 +01:00
multimesh_update_list . remove ( multimesh_update_list . first ( ) ) ;
}
2016-10-03 21:33:42 +02:00
}
/* IMMEDIATE API */
2016-11-23 11:04:55 +01:00
RID RasterizerStorageGLES3 : : immediate_create ( ) {
2017-03-05 16:44:50 +01:00
Immediate * im = memnew ( Immediate ) ;
2016-11-23 11:04:55 +01:00
return immediate_owner . make_rid ( im ) ;
2016-10-03 21:33:42 +02:00
}
2016-11-23 11:04:55 +01:00
2019-10-28 08:07:29 +01:00
void RasterizerStorageGLES3 : : immediate_begin ( RID p_immediate , VS : : PrimitiveType p_primitive , RID p_texture ) {
2016-11-23 11:04:55 +01:00
2019-10-28 08:07:29 +01:00
ERR_FAIL_INDEX ( p_primitive , ( int ) VS : : PRIMITIVE_MAX ) ;
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( im - > building ) ;
Immediate : : Chunk ic ;
2017-03-05 16:44:50 +01:00
ic . texture = p_texture ;
2019-10-28 08:07:29 +01:00
ic . primitive = p_primitive ;
2016-11-23 11:04:55 +01:00
im - > chunks . push_back ( ic ) ;
2017-03-05 16:44:50 +01:00
im - > mask = 0 ;
im - > building = true ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_vertex ( RID p_immediate , const Vector3 & p_vertex ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( ! im - > building ) ;
2016-10-03 21:33:42 +02:00
2016-11-23 11:04:55 +01:00
Immediate : : Chunk * c = & im - > chunks . back ( ) - > get ( ) ;
2017-03-05 16:44:50 +01:00
if ( c - > vertices . empty ( ) & & im - > chunks . size ( ) = = 1 ) {
2016-11-23 11:04:55 +01:00
2017-06-06 20:33:51 +02:00
im - > aabb . position = p_vertex ;
2017-03-05 16:44:50 +01:00
im - > aabb . size = Vector3 ( ) ;
2016-11-23 11:04:55 +01:00
} else {
im - > aabb . expand_to ( p_vertex ) ;
}
2017-03-05 16:44:50 +01:00
if ( im - > mask & VS : : ARRAY_FORMAT_NORMAL )
2016-11-23 11:04:55 +01:00
c - > normals . push_back ( chunk_normal ) ;
2017-03-05 16:44:50 +01:00
if ( im - > mask & VS : : ARRAY_FORMAT_TANGENT )
2016-11-23 11:04:55 +01:00
c - > tangents . push_back ( chunk_tangent ) ;
2017-03-05 16:44:50 +01:00
if ( im - > mask & VS : : ARRAY_FORMAT_COLOR )
2016-11-23 11:04:55 +01:00
c - > colors . push_back ( chunk_color ) ;
2017-03-05 16:44:50 +01:00
if ( im - > mask & VS : : ARRAY_FORMAT_TEX_UV )
2016-11-23 11:04:55 +01:00
c - > uvs . push_back ( chunk_uv ) ;
2017-03-05 16:44:50 +01:00
if ( im - > mask & VS : : ARRAY_FORMAT_TEX_UV2 )
2016-11-23 11:04:55 +01:00
c - > uvs2 . push_back ( chunk_uv2 ) ;
2017-03-05 16:44:50 +01:00
im - > mask | = VS : : ARRAY_FORMAT_VERTEX ;
2016-11-23 11:04:55 +01:00
c - > vertices . push_back ( p_vertex ) ;
2016-10-03 21:33:42 +02:00
}
2016-11-23 11:04:55 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_normal ( RID p_immediate , const Vector3 & p_normal ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( ! im - > building ) ;
2017-03-05 16:44:50 +01:00
im - > mask | = VS : : ARRAY_FORMAT_NORMAL ;
chunk_normal = p_normal ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_tangent ( RID p_immediate , const Plane & p_tangent ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( ! im - > building ) ;
2017-03-05 16:44:50 +01:00
im - > mask | = VS : : ARRAY_FORMAT_TANGENT ;
chunk_tangent = p_tangent ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_color ( RID p_immediate , const Color & p_color ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( ! im - > building ) ;
2017-03-05 16:44:50 +01:00
im - > mask | = VS : : ARRAY_FORMAT_COLOR ;
chunk_color = p_color ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_uv ( RID p_immediate , const Vector2 & tex_uv ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( ! im - > building ) ;
2017-03-05 16:44:50 +01:00
im - > mask | = VS : : ARRAY_FORMAT_TEX_UV ;
chunk_uv = tex_uv ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_uv2 ( RID p_immediate , const Vector2 & tex_uv ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( ! im - > building ) ;
2017-03-05 16:44:50 +01:00
im - > mask | = VS : : ARRAY_FORMAT_TEX_UV2 ;
chunk_uv2 = tex_uv ;
2016-10-03 21:33:42 +02:00
}
2016-11-23 11:04:55 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_end ( RID p_immediate ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( ! im - > building ) ;
2017-03-05 16:44:50 +01:00
im - > building = false ;
2016-11-23 11:04:55 +01:00
2018-11-14 13:32:39 +01:00
im - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2016-11-23 11:04:55 +01:00
void RasterizerStorageGLES3 : : immediate_clear ( RID p_immediate ) {
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
ERR_FAIL_COND ( im - > building ) ;
2016-10-03 21:33:42 +02:00
2016-11-23 11:04:55 +01:00
im - > chunks . clear ( ) ;
2018-11-14 13:32:39 +01:00
im - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : immediate_get_aabb ( RID p_immediate ) const {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! im , AABB ( ) ) ;
2016-11-23 11:04:55 +01:00
return im - > aabb ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : immediate_set_material ( RID p_immediate , RID p_material ) {
2016-11-23 11:04:55 +01:00
2019-06-10 17:38:51 +02:00
Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2016-11-23 11:04:55 +01:00
ERR_FAIL_COND ( ! im ) ;
2017-03-05 16:44:50 +01:00
im - > material = p_material ;
2018-11-14 13:32:39 +01:00
im - > instance_change_notify ( false , true ) ;
2016-11-23 11:04:55 +01:00
}
RID RasterizerStorageGLES3 : : immediate_get_material ( RID p_immediate ) const {
2019-06-10 17:38:51 +02:00
const Immediate * im = immediate_owner . getornull ( p_immediate ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! im , RID ( ) ) ;
2016-11-23 11:04:55 +01:00
return im - > material ;
2016-10-03 21:33:42 +02:00
}
/* SKELETON API */
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : skeleton_create ( ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Skeleton * skeleton = memnew ( Skeleton ) ;
2017-03-12 17:08:56 +01:00
2017-03-24 00:14:12 +01:00
glGenTextures ( 1 , & skeleton - > texture ) ;
2017-03-12 17:08:56 +01:00
2016-11-21 23:03:39 +01:00
return skeleton_owner . make_rid ( skeleton ) ;
2016-10-03 21:33:42 +02:00
}
2016-11-21 23:03:39 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : skeleton_allocate ( RID p_skeleton , int p_bones , bool p_2d_skeleton ) {
2016-10-03 21:33:42 +02:00
2016-11-21 23:03:39 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
ERR_FAIL_COND ( ! skeleton ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_bones < 0 ) ;
2016-11-21 23:03:39 +01:00
2017-03-05 16:44:50 +01:00
if ( skeleton - > size = = p_bones & & skeleton - > use_2d = = p_2d_skeleton )
2016-11-21 23:03:39 +01:00
return ;
2017-03-24 00:14:12 +01:00
skeleton - > size = p_bones ;
skeleton - > use_2d = p_2d_skeleton ;
2016-11-21 23:03:39 +01:00
2017-03-24 00:14:12 +01:00
int height = p_bones / 256 ;
if ( p_bones % 256 )
2017-03-12 17:08:56 +01:00
height + + ;
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-24 00:14:12 +01:00
glBindTexture ( GL_TEXTURE_2D , skeleton - > texture ) ;
2017-03-12 17:08:56 +01:00
if ( skeleton - > use_2d ) {
2017-03-24 00:14:12 +01:00
skeleton - > skel_texture . resize ( 256 * height * 2 * 4 ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA32F , 256 , height * 2 , 0 , GL_RGBA , GL_FLOAT , NULL ) ;
2016-11-21 23:03:39 +01:00
} else {
2017-03-24 00:14:12 +01:00
skeleton - > skel_texture . resize ( 256 * height * 3 * 4 ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA32F , 256 , height * 3 , 0 , GL_RGBA , GL_FLOAT , NULL ) ;
2016-11-21 23:03:39 +01:00
}
2017-03-12 17:08:56 +01:00
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 ) ;
2016-11-21 23:03:39 +01:00
if ( ! skeleton - > update_list . in_list ( ) ) {
skeleton_update_list . add ( & skeleton - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : skeleton_get_bone_count ( RID p_skeleton ) const {
2016-10-03 21:33:42 +02:00
2016-11-21 23:03:39 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! skeleton , 0 ) ;
2016-11-21 23:03:39 +01:00
return skeleton - > size ;
2016-10-03 21:33:42 +02:00
}
2016-11-21 23:03:39 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : skeleton_bone_set_transform ( RID p_skeleton , int p_bone , const Transform & p_transform ) {
2016-10-03 21:33:42 +02:00
2016-11-21 23:03:39 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
ERR_FAIL_COND ( ! skeleton ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_bone , skeleton - > size ) ;
2016-11-21 23:03:39 +01:00
ERR_FAIL_COND ( skeleton - > use_2d ) ;
2017-11-25 04:07:54 +01:00
float * texture = skeleton - > skel_texture . ptrw ( ) ;
2017-03-12 17:08:56 +01:00
int base_ofs = ( ( p_bone / 256 ) * 256 ) * 3 * 4 + ( p_bone % 256 ) * 4 ;
2017-03-24 00:14:12 +01:00
texture [ base_ofs + 0 ] = p_transform . basis [ 0 ] . x ;
texture [ base_ofs + 1 ] = p_transform . basis [ 0 ] . y ;
texture [ base_ofs + 2 ] = p_transform . basis [ 0 ] . z ;
texture [ base_ofs + 3 ] = p_transform . origin . x ;
base_ofs + = 256 * 4 ;
texture [ base_ofs + 0 ] = p_transform . basis [ 1 ] . x ;
texture [ base_ofs + 1 ] = p_transform . basis [ 1 ] . y ;
texture [ base_ofs + 2 ] = p_transform . basis [ 1 ] . z ;
texture [ base_ofs + 3 ] = p_transform . origin . y ;
base_ofs + = 256 * 4 ;
texture [ base_ofs + 0 ] = p_transform . basis [ 2 ] . x ;
texture [ base_ofs + 1 ] = p_transform . basis [ 2 ] . y ;
texture [ base_ofs + 2 ] = p_transform . basis [ 2 ] . z ;
texture [ base_ofs + 3 ] = p_transform . origin . z ;
2016-11-21 23:03:39 +01:00
if ( ! skeleton - > update_list . in_list ( ) ) {
skeleton_update_list . add ( & skeleton - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2016-11-21 23:03:39 +01:00
2017-03-05 16:44:50 +01:00
Transform RasterizerStorageGLES3 : : skeleton_bone_get_transform ( RID p_skeleton , int p_bone ) const {
2016-10-03 21:33:42 +02:00
2016-11-21 23:03:39 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! skeleton , Transform ( ) ) ;
ERR_FAIL_INDEX_V ( p_bone , skeleton - > size , Transform ( ) ) ;
ERR_FAIL_COND_V ( skeleton - > use_2d , Transform ( ) ) ;
2016-11-21 23:03:39 +01:00
2017-03-12 17:08:56 +01:00
const float * texture = skeleton - > skel_texture . ptr ( ) ;
Transform ret ;
int base_ofs = ( ( p_bone / 256 ) * 256 ) * 3 * 4 + ( p_bone % 256 ) * 4 ;
2017-03-24 00:14:12 +01:00
ret . basis [ 0 ] . x = texture [ base_ofs + 0 ] ;
ret . basis [ 0 ] . y = texture [ base_ofs + 1 ] ;
ret . basis [ 0 ] . z = texture [ base_ofs + 2 ] ;
ret . origin . x = texture [ base_ofs + 3 ] ;
base_ofs + = 256 * 4 ;
ret . basis [ 1 ] . x = texture [ base_ofs + 0 ] ;
ret . basis [ 1 ] . y = texture [ base_ofs + 1 ] ;
ret . basis [ 1 ] . z = texture [ base_ofs + 2 ] ;
ret . origin . y = texture [ base_ofs + 3 ] ;
base_ofs + = 256 * 4 ;
ret . basis [ 2 ] . x = texture [ base_ofs + 0 ] ;
ret . basis [ 2 ] . y = texture [ base_ofs + 1 ] ;
ret . basis [ 2 ] . z = texture [ base_ofs + 2 ] ;
ret . origin . z = texture [ base_ofs + 3 ] ;
2017-03-12 17:08:56 +01:00
return ret ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : skeleton_bone_set_transform_2d ( RID p_skeleton , int p_bone , const Transform2D & p_transform ) {
2016-10-03 21:33:42 +02:00
2016-11-21 23:03:39 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
ERR_FAIL_COND ( ! skeleton ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_bone , skeleton - > size ) ;
2016-11-21 23:03:39 +01:00
ERR_FAIL_COND ( ! skeleton - > use_2d ) ;
2017-11-25 04:07:54 +01:00
float * texture = skeleton - > skel_texture . ptrw ( ) ;
2017-03-12 17:08:56 +01:00
int base_ofs = ( ( p_bone / 256 ) * 256 ) * 2 * 4 + ( p_bone % 256 ) * 4 ;
2017-03-24 00:14:12 +01:00
texture [ base_ofs + 0 ] = p_transform [ 0 ] [ 0 ] ;
texture [ base_ofs + 1 ] = p_transform [ 1 ] [ 0 ] ;
texture [ base_ofs + 2 ] = 0 ;
texture [ base_ofs + 3 ] = p_transform [ 2 ] [ 0 ] ;
base_ofs + = 256 * 4 ;
texture [ base_ofs + 0 ] = p_transform [ 0 ] [ 1 ] ;
texture [ base_ofs + 1 ] = p_transform [ 1 ] [ 1 ] ;
texture [ base_ofs + 2 ] = 0 ;
texture [ base_ofs + 3 ] = p_transform [ 2 ] [ 1 ] ;
2016-11-21 23:03:39 +01:00
if ( ! skeleton - > update_list . in_list ( ) ) {
skeleton_update_list . add ( & skeleton - > update_list ) ;
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
Transform2D RasterizerStorageGLES3 : : skeleton_bone_get_transform_2d ( RID p_skeleton , int p_bone ) const {
2016-10-03 21:33:42 +02:00
2016-11-21 23:03:39 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! skeleton , Transform2D ( ) ) ;
ERR_FAIL_INDEX_V ( p_bone , skeleton - > size , Transform2D ( ) ) ;
ERR_FAIL_COND_V ( ! skeleton - > use_2d , Transform2D ( ) ) ;
2016-11-21 23:03:39 +01:00
2017-03-12 17:08:56 +01:00
const float * texture = skeleton - > skel_texture . ptr ( ) ;
Transform2D ret ;
int base_ofs = ( ( p_bone / 256 ) * 256 ) * 2 * 4 + ( p_bone % 256 ) * 4 ;
2016-11-21 23:03:39 +01:00
2017-03-24 00:14:12 +01:00
ret [ 0 ] [ 0 ] = texture [ base_ofs + 0 ] ;
ret [ 1 ] [ 0 ] = texture [ base_ofs + 1 ] ;
ret [ 2 ] [ 0 ] = texture [ base_ofs + 3 ] ;
base_ofs + = 256 * 4 ;
ret [ 0 ] [ 1 ] = texture [ base_ofs + 0 ] ;
ret [ 1 ] [ 1 ] = texture [ base_ofs + 1 ] ;
ret [ 2 ] [ 1 ] = texture [ base_ofs + 3 ] ;
2016-11-21 23:03:39 +01:00
2017-03-12 17:08:56 +01:00
return ret ;
2016-11-21 23:03:39 +01:00
}
2018-05-03 22:29:15 +02:00
void RasterizerStorageGLES3 : : skeleton_set_base_transform_2d ( RID p_skeleton , const Transform2D & p_base_transform ) {
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
ERR_FAIL_COND ( ! skeleton - > use_2d ) ;
skeleton - > base_transform_2d = p_base_transform ;
}
2016-11-21 23:03:39 +01:00
void RasterizerStorageGLES3 : : update_dirty_skeletons ( ) {
2017-03-12 17:08:56 +01:00
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
while ( skeleton_update_list . first ( ) ) {
2016-11-21 23:03:39 +01:00
Skeleton * skeleton = skeleton_update_list . first ( ) - > self ( ) ;
if ( skeleton - > size ) {
2017-03-12 17:08:56 +01:00
2017-03-24 00:14:12 +01:00
int height = skeleton - > size / 256 ;
if ( skeleton - > size % 256 )
2017-03-12 17:08:56 +01:00
height + + ;
2017-03-24 00:14:12 +01:00
glBindTexture ( GL_TEXTURE_2D , skeleton - > texture ) ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 , 256 , height * ( skeleton - > use_2d ? 2 : 3 ) , GL_RGBA , GL_FLOAT , skeleton - > skel_texture . ptr ( ) ) ;
2016-11-21 23:03:39 +01:00
}
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
for ( Set < RasterizerScene : : InstanceBase * > : : Element * E = skeleton - > instances . front ( ) ; E ; E = E - > next ( ) ) {
2018-11-14 13:32:39 +01:00
E - > get ( ) - > base_changed ( true , false ) ;
2016-11-25 00:46:55 +01:00
}
2016-11-21 23:03:39 +01:00
skeleton_update_list . remove ( skeleton_update_list . first ( ) ) ;
}
2016-10-03 21:33:42 +02:00
}
/* Light API */
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : light_create ( VS : : LightType p_type ) {
Light * light = memnew ( Light ) ;
light - > type = p_type ;
light - > param [ VS : : LIGHT_PARAM_ENERGY ] = 1.0 ;
2017-11-20 01:45:42 +01:00
light - > param [ VS : : LIGHT_PARAM_INDIRECT_ENERGY ] = 1.0 ;
2017-03-05 16:44:50 +01:00
light - > param [ VS : : LIGHT_PARAM_SPECULAR ] = 0.5 ;
light - > param [ VS : : LIGHT_PARAM_RANGE ] = 1.0 ;
light - > param [ VS : : LIGHT_PARAM_SPOT_ANGLE ] = 45 ;
light - > param [ VS : : LIGHT_PARAM_CONTACT_SHADOW_SIZE ] = 45 ;
light - > param [ VS : : LIGHT_PARAM_SHADOW_MAX_DISTANCE ] = 0 ;
light - > param [ VS : : LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET ] = 0.1 ;
light - > param [ VS : : LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET ] = 0.3 ;
light - > param [ VS : : LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET ] = 0.6 ;
light - > param [ VS : : LIGHT_PARAM_SHADOW_NORMAL_BIAS ] = 0.1 ;
2017-08-30 13:07:25 +02:00
light - > param [ VS : : LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE ] = 0.1 ;
2017-03-05 16:44:50 +01:00
light - > color = Color ( 1 , 1 , 1 , 1 ) ;
light - > shadow = false ;
light - > negative = false ;
light - > cull_mask = 0xFFFFFFFF ;
light - > directional_shadow_mode = VS : : LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ;
light - > omni_shadow_mode = VS : : LIGHT_OMNI_SHADOW_DUAL_PARABOLOID ;
light - > omni_shadow_detail = VS : : LIGHT_OMNI_SHADOW_DETAIL_VERTICAL ;
light - > directional_blend_splits = false ;
2017-09-07 23:00:47 +02:00
light - > directional_range_mode = VS : : LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE ;
2017-08-20 01:06:40 +02:00
light - > reverse_cull = false ;
2019-04-23 11:36:36 +02:00
light - > use_gi = true ;
2017-03-05 16:44:50 +01:00
light - > version = 0 ;
2016-10-27 16:50:26 +02:00
return light_owner . make_rid ( light ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_set_color ( RID p_light , const Color & p_color ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
light - > color = p_color ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_set_param ( RID p_light , VS : : LightParam p_param , float p_value ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_param , VS : : LIGHT_PARAM_MAX ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
switch ( p_param ) {
2016-11-10 03:55:06 +01:00
case VS : : LIGHT_PARAM_RANGE :
case VS : : LIGHT_PARAM_SPOT_ANGLE :
case VS : : LIGHT_PARAM_SHADOW_MAX_DISTANCE :
case VS : : LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET :
case VS : : LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET :
case VS : : LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET :
case VS : : LIGHT_PARAM_SHADOW_NORMAL_BIAS :
2017-06-14 21:56:47 +02:00
case VS : : LIGHT_PARAM_SHADOW_BIAS : {
2016-11-10 03:55:06 +01:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2016-11-10 03:55:06 +01:00
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2016-10-27 16:50:26 +02:00
}
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
light - > param [ p_param ] = p_value ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_set_shadow ( RID p_light , bool p_enabled ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2017-03-05 16:44:50 +01:00
light - > shadow = p_enabled ;
2016-10-03 21:33:42 +02:00
2016-11-10 03:55:06 +01:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2016-11-11 16:27:52 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_set_shadow_color ( RID p_light , const Color & p_color ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2017-03-05 16:44:50 +01:00
light - > shadow_color = p_color ;
2016-10-03 21:33:42 +02:00
}
2016-11-11 16:27:52 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_set_projector ( RID p_light , RID p_texture ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2016-11-11 16:27:52 +01:00
2017-03-05 16:44:50 +01:00
light - > projector = p_texture ;
2016-10-03 21:33:42 +02:00
}
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_set_negative ( RID p_light , bool p_enable ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
light - > negative = p_enable ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_set_cull_mask ( RID p_light , uint32_t p_mask ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
light - > cull_mask = p_mask ;
2016-11-10 03:55:06 +01:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-08-20 01:06:40 +02:00
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 ;
2018-09-26 21:49:24 +02:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2017-08-20 01:06:40 +02:00
}
2019-04-23 11:36:36 +02:00
void RasterizerStorageGLES3 : : light_set_use_gi ( RID p_light , bool p_enabled ) {
Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND ( ! light ) ;
light - > use_gi = p_enabled ;
light - > version + + ;
light - > instance_change_notify ( true , false ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_omni_set_shadow_mode ( RID p_light , VS : : LightOmniShadowMode p_mode ) {
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! light ) ;
2017-03-05 16:44:50 +01:00
light - > omni_shadow_mode = p_mode ;
2016-11-10 03:55:06 +01:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2016-11-10 03:55:06 +01:00
}
VS : : LightOmniShadowMode RasterizerStorageGLES3 : : light_omni_get_shadow_mode ( RID p_light ) {
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , VS : : LIGHT_OMNI_SHADOW_CUBE ) ;
2016-11-10 03:55:06 +01:00
return light - > omni_shadow_mode ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_omni_set_shadow_detail ( RID p_light , VS : : LightOmniShadowDetail p_detail ) {
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! light ) ;
2017-03-05 16:44:50 +01:00
light - > omni_shadow_detail = p_detail ;
2016-11-10 03:55:06 +01:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2016-11-10 03:55:06 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_directional_set_shadow_mode ( RID p_light , VS : : LightDirectionalShadowMode p_mode ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-10-27 16:50:26 +02:00
ERR_FAIL_COND ( ! light ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
light - > directional_shadow_mode = p_mode ;
2016-11-10 03:55:06 +01:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2016-11-10 03:55:06 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : light_directional_set_blend_splits ( RID p_light , bool p_enable ) {
2016-11-11 16:27:52 +01:00
2017-03-05 16:44:50 +01:00
Light * light = light_owner . getornull ( p_light ) ;
2016-11-11 16:27:52 +01:00
ERR_FAIL_COND ( ! light ) ;
2017-03-05 16:44:50 +01:00
light - > directional_blend_splits = p_enable ;
2016-11-11 16:27:52 +01:00
light - > version + + ;
2018-11-14 13:32:39 +01:00
light - > instance_change_notify ( true , false ) ;
2016-11-11 16:27:52 +01:00
}
bool RasterizerStorageGLES3 : : light_directional_get_blend_splits ( RID p_light ) const {
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , false ) ;
2016-11-11 16:27:52 +01:00
return light - > directional_blend_splits ;
}
2016-11-10 03:55:06 +01:00
VS : : LightDirectionalShadowMode RasterizerStorageGLES3 : : light_directional_get_shadow_mode ( RID p_light ) {
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , VS : : LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ) ;
2016-11-10 03:55:06 +01:00
return light - > directional_shadow_mode ;
2016-10-03 21:33:42 +02:00
}
2017-09-07 23:00:47 +02:00
void RasterizerStorageGLES3 : : light_directional_set_shadow_depth_range_mode ( RID p_light , VS : : LightDirectionalShadowDepthRangeMode p_range_mode ) {
Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND ( ! light ) ;
2017-09-07 21:48:50 +02:00
light - > directional_range_mode = p_range_mode ;
2017-09-07 23:00:47 +02:00
}
VS : : LightDirectionalShadowDepthRangeMode RasterizerStorageGLES3 : : light_directional_get_shadow_depth_range_mode ( RID p_light ) const {
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , VS : : LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE ) ;
return light - > directional_range_mode ;
}
2016-10-19 16:14:41 +02:00
VS : : LightType RasterizerStorageGLES3 : : light_get_type ( RID p_light ) const {
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , VS : : LIGHT_DIRECTIONAL ) ;
2016-10-27 16:50:26 +02:00
2016-11-10 03:55:06 +01:00
return light - > type ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
float RasterizerStorageGLES3 : : light_get_param ( RID p_light , VS : : LightParam p_param ) {
2016-11-10 03:55:06 +01:00
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , VS : : LIGHT_DIRECTIONAL ) ;
2016-11-10 03:55:06 +01:00
return light - > param [ p_param ] ;
}
2016-12-20 04:21:07 +01:00
Color RasterizerStorageGLES3 : : light_get_color ( RID p_light ) {
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , Color ( ) ) ;
2016-12-20 04:21:07 +01:00
return light - > color ;
}
2019-04-23 11:36:36 +02:00
bool RasterizerStorageGLES3 : : light_get_use_gi ( RID p_light ) {
Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , false ) ;
return light - > use_gi ;
}
2016-11-10 03:55:06 +01:00
bool RasterizerStorageGLES3 : : light_has_shadow ( RID p_light ) const {
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , VS : : LIGHT_DIRECTIONAL ) ;
2016-11-10 03:55:06 +01:00
return light - > shadow ;
}
uint64_t RasterizerStorageGLES3 : : light_get_version ( RID p_light ) const {
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
ERR_FAIL_COND_V ( ! light , 0 ) ;
2016-11-10 03:55:06 +01:00
return light - > version ;
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : light_get_aabb ( RID p_light ) const {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
const Light * light = light_owner . getornull ( p_light ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! light , AABB ( ) ) ;
2016-10-27 16:50:26 +02:00
2017-03-05 16:44:50 +01:00
switch ( light - > type ) {
2016-10-27 16:50:26 +02:00
case VS : : LIGHT_SPOT : {
2017-03-05 16:44:50 +01:00
float len = light - > param [ VS : : LIGHT_PARAM_RANGE ] ;
float size = Math : : tan ( Math : : deg2rad ( light - > param [ VS : : LIGHT_PARAM_SPOT_ANGLE ] ) ) * len ;
2017-11-17 03:09:00 +01:00
return AABB ( Vector3 ( - size , - size , - len ) , Vector3 ( size * 2 , size * 2 , len ) ) ;
2019-07-20 08:09:57 +02:00
} ;
2016-10-27 16:50:26 +02:00
case VS : : LIGHT_OMNI : {
float r = light - > param [ VS : : LIGHT_PARAM_RANGE ] ;
2017-11-17 03:09:00 +01:00
return AABB ( - Vector3 ( r , r , r ) , Vector3 ( r , r , r ) * 2 ) ;
2019-07-20 08:09:57 +02:00
} ;
2016-10-27 16:50:26 +02:00
case VS : : LIGHT_DIRECTIONAL : {
2017-11-17 03:09:00 +01:00
return AABB ( ) ;
2019-07-20 08:09:57 +02:00
} ;
2016-10-27 16:50:26 +02:00
}
2017-11-17 03:09:00 +01:00
ERR_FAIL_V ( AABB ( ) ) ;
2016-10-19 16:14:41 +02:00
}
2016-10-03 21:33:42 +02:00
/* PROBE API */
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : reflection_probe_create ( ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
ReflectionProbe * reflection_probe = memnew ( ReflectionProbe ) ;
2016-11-19 17:23:37 +01:00
2017-03-05 16:44:50 +01:00
reflection_probe - > intensity = 1.0 ;
reflection_probe - > interior_ambient = Color ( ) ;
reflection_probe - > interior_ambient_energy = 1.0 ;
2019-03-04 19:52:39 +01:00
reflection_probe - > interior_ambient_probe_contrib = 0.0 ;
2017-03-05 16:44:50 +01:00
reflection_probe - > max_distance = 0 ;
reflection_probe - > extents = Vector3 ( 1 , 1 , 1 ) ;
reflection_probe - > origin_offset = Vector3 ( 0 , 0 , 0 ) ;
reflection_probe - > interior = false ;
reflection_probe - > box_projection = false ;
reflection_probe - > enable_shadows = false ;
reflection_probe - > cull_mask = ( 1 < < 20 ) - 1 ;
reflection_probe - > update_mode = VS : : REFLECTION_PROBE_UPDATE_ONCE ;
2016-11-19 17:23:37 +01:00
return reflection_probe_owner . make_rid ( reflection_probe ) ;
2016-10-03 21:33:42 +02:00
}
2016-11-19 17:23:37 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_update_mode ( RID p_probe , VS : : ReflectionProbeUpdateMode p_mode ) {
2016-10-03 21:33:42 +02:00
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > update_mode = p_mode ;
2018-11-14 13:32:39 +01:00
reflection_probe - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2016-11-19 17:23:37 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_intensity ( RID p_probe , float p_intensity ) {
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > intensity = p_intensity ;
2016-11-19 17:23:37 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_interior_ambient ( RID p_probe , const Color & p_ambient ) {
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > interior_ambient = p_ambient ;
2016-11-19 17:23:37 +01:00
}
void RasterizerStorageGLES3 : : reflection_probe_set_interior_ambient_energy ( RID p_probe , float p_energy ) {
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > interior_ambient_energy = p_energy ;
2016-10-03 21:33:42 +02:00
}
2016-11-19 17:23:37 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_interior_ambient_probe_contribution ( RID p_probe , float p_contrib ) {
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > interior_ambient_probe_contrib = p_contrib ;
2016-11-19 17:23:37 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_max_distance ( RID p_probe , float p_distance ) {
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > max_distance = p_distance ;
2018-11-14 13:32:39 +01:00
reflection_probe - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_extents ( RID p_probe , const Vector3 & p_extents ) {
2016-10-03 21:33:42 +02:00
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > extents = p_extents ;
2018-11-14 13:32:39 +01:00
reflection_probe - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_origin_offset ( RID p_probe , const Vector3 & p_offset ) {
2016-10-03 21:33:42 +02:00
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > origin_offset = p_offset ;
2018-11-14 13:32:39 +01:00
reflection_probe - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_as_interior ( RID p_probe , bool p_enable ) {
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > interior = p_enable ;
2019-02-26 01:46:24 +01:00
reflection_probe - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_enable_box_projection ( RID p_probe , bool p_enable ) {
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
reflection_probe - > box_projection = p_enable ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_enable_shadows ( RID p_probe , bool p_enable ) {
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > enable_shadows = p_enable ;
2018-11-14 13:32:39 +01:00
reflection_probe - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : reflection_probe_set_cull_mask ( RID p_probe , uint32_t p_layers ) {
2016-10-03 21:33:42 +02:00
2016-11-19 17:23:37 +01:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! reflection_probe ) ;
2017-03-05 16:44:50 +01:00
reflection_probe - > cull_mask = p_layers ;
2018-11-14 13:32:39 +01:00
reflection_probe - > instance_change_notify ( true , false ) ;
2016-10-03 21:33:42 +02:00
}
2018-09-28 21:40:20 +02:00
void RasterizerStorageGLES3 : : reflection_probe_set_resolution ( RID p_probe , int p_resolution ) {
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : reflection_probe_get_aabb ( RID p_probe ) const {
2016-11-19 17:23:37 +01:00
const ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! reflection_probe , AABB ( ) ) ;
2016-11-19 17:23:37 +01:00
2017-11-17 03:09:00 +01:00
AABB aabb ;
2017-06-06 20:33:51 +02:00
aabb . position = - reflection_probe - > extents ;
2017-03-05 16:44:50 +01:00
aabb . size = reflection_probe - > extents * 2.0 ;
2016-11-19 17:23:37 +01:00
return aabb ;
}
2017-03-05 16:44:50 +01:00
VS : : ReflectionProbeUpdateMode RasterizerStorageGLES3 : : reflection_probe_get_update_mode ( RID p_probe ) const {
2016-11-19 17:23:37 +01:00
const ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! reflection_probe , VS : : REFLECTION_PROBE_UPDATE_ALWAYS ) ;
2016-11-19 17:23:37 +01:00
return reflection_probe - > update_mode ;
}
uint32_t RasterizerStorageGLES3 : : reflection_probe_get_cull_mask ( RID p_probe ) const {
const ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! reflection_probe , 0 ) ;
2016-11-19 17:23:37 +01:00
return reflection_probe - > cull_mask ;
}
Vector3 RasterizerStorageGLES3 : : reflection_probe_get_extents ( RID p_probe ) const {
const ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! reflection_probe , Vector3 ( ) ) ;
2016-11-19 17:23:37 +01:00
return reflection_probe - > extents ;
}
2017-03-05 16:44:50 +01:00
Vector3 RasterizerStorageGLES3 : : reflection_probe_get_origin_offset ( RID p_probe ) const {
2016-11-19 17:23:37 +01:00
const ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! reflection_probe , Vector3 ( ) ) ;
2016-11-19 17:23:37 +01:00
return reflection_probe - > origin_offset ;
}
bool RasterizerStorageGLES3 : : reflection_probe_renders_shadows ( RID p_probe ) const {
const ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! reflection_probe , false ) ;
2016-11-19 17:23:37 +01:00
return reflection_probe - > enable_shadows ;
}
2017-03-05 16:44:50 +01:00
float RasterizerStorageGLES3 : : reflection_probe_get_origin_max_distance ( RID p_probe ) const {
2016-11-19 17:23:37 +01:00
const ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! reflection_probe , 0 ) ;
2016-11-19 17:23:37 +01:00
return reflection_probe - > max_distance ;
}
2016-10-03 21:33:42 +02:00
2016-12-20 04:21:07 +01:00
RID RasterizerStorageGLES3 : : gi_probe_create ( ) {
2017-03-05 16:44:50 +01:00
GIProbe * gip = memnew ( GIProbe ) ;
2016-12-20 04:21:07 +01:00
2017-11-17 03:09:00 +01:00
gip - > bounds = AABB ( Vector3 ( ) , Vector3 ( 1 , 1 , 1 ) ) ;
2017-03-05 16:44:50 +01:00
gip - > dynamic_range = 1.0 ;
gip - > energy = 1.0 ;
gip - > propagation = 1.0 ;
gip - > bias = 0.4 ;
2017-07-16 04:24:37 +02:00
gip - > normal_bias = 0.4 ;
2017-03-05 16:44:50 +01:00
gip - > interior = false ;
gip - > compress = false ;
gip - > version = 1 ;
gip - > cell_size = 1.0 ;
2016-12-20 04:21:07 +01:00
return gi_probe_owner . make_rid ( gip ) ;
}
2017-11-17 03:09:00 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_bounds ( RID p_probe , const AABB & p_bounds ) {
2016-12-20 04:21:07 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > bounds = p_bounds ;
2016-12-20 04:21:07 +01:00
gip - > version + + ;
2018-11-14 13:32:39 +01:00
gip - > instance_change_notify ( true , false ) ;
2016-12-20 04:21:07 +01:00
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : gi_probe_get_bounds ( RID p_probe ) const {
2016-12-20 04:21:07 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! gip , AABB ( ) ) ;
2016-12-20 04:21:07 +01:00
return gip - > bounds ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_cell_size ( RID p_probe , float p_size ) {
2016-12-20 04:21:07 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > cell_size = p_size ;
2016-12-20 04:21:07 +01:00
gip - > version + + ;
2018-11-14 13:32:39 +01:00
gip - > instance_change_notify ( true , false ) ;
2016-12-20 04:21:07 +01:00
}
float RasterizerStorageGLES3 : : gi_probe_get_cell_size ( RID p_probe ) const {
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , 0 ) ;
2016-12-20 04:21:07 +01:00
return gip - > cell_size ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_to_cell_xform ( RID p_probe , const Transform & p_xform ) {
2016-12-20 04:21:07 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > to_cell = p_xform ;
2016-12-20 04:21:07 +01:00
}
Transform RasterizerStorageGLES3 : : gi_probe_get_to_cell_xform ( RID p_probe ) const {
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , Transform ( ) ) ;
2016-12-20 04:21:07 +01:00
return gip - > to_cell ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_dynamic_data ( RID p_probe , const PoolVector < int > & p_data ) {
2016-12-20 04:21:07 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > dynamic_data = p_data ;
2016-12-20 04:21:07 +01:00
gip - > version + + ;
2018-11-14 13:32:39 +01:00
gip - > instance_change_notify ( true , false ) ;
2016-12-20 04:21:07 +01:00
}
2017-03-05 16:44:50 +01:00
PoolVector < int > RasterizerStorageGLES3 : : gi_probe_get_dynamic_data ( RID p_probe ) const {
2016-12-20 04:21:07 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , PoolVector < int > ( ) ) ;
2016-12-20 04:21:07 +01:00
return gip - > dynamic_data ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_dynamic_range ( RID p_probe , int p_range ) {
2016-12-20 04:21:07 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > dynamic_range = p_range ;
2016-12-20 04:21:07 +01:00
}
2017-03-05 16:44:50 +01:00
int RasterizerStorageGLES3 : : gi_probe_get_dynamic_range ( RID p_probe ) const {
2016-12-20 04:21:07 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , 0 ) ;
2016-12-20 04:21:07 +01:00
return gip - > dynamic_range ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_energy ( RID p_probe , float p_range ) {
2016-12-22 14:00:15 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > energy = p_range ;
2016-12-22 14:00:15 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_bias ( RID p_probe , float p_range ) {
2017-02-16 12:55:11 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > bias = p_range ;
2017-02-16 12:55:11 +01:00
}
2017-07-16 04:24:37 +02:00
void RasterizerStorageGLES3 : : gi_probe_set_normal_bias ( RID p_probe , float p_range ) {
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
gip - > normal_bias = p_range ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_propagation ( RID p_probe , float p_range ) {
2017-02-06 09:12:15 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > propagation = p_range ;
2017-02-06 09:12:15 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_interior ( RID p_probe , bool p_enable ) {
2016-12-22 14:00:15 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > interior = p_enable ;
2016-12-22 14:00:15 +01:00
}
2017-03-05 16:44:50 +01:00
bool RasterizerStorageGLES3 : : gi_probe_is_interior ( RID p_probe ) const {
2016-12-22 14:00:15 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , false ) ;
2016-12-22 14:00:15 +01:00
return gip - > interior ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : gi_probe_set_compress ( RID p_probe , bool p_enable ) {
2016-12-31 14:53:29 +01:00
GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND ( ! gip ) ;
2017-03-05 16:44:50 +01:00
gip - > compress = p_enable ;
2016-12-31 14:53:29 +01:00
}
2017-03-05 16:44:50 +01:00
bool RasterizerStorageGLES3 : : gi_probe_is_compressed ( RID p_probe ) const {
2016-12-31 14:53:29 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , false ) ;
2016-12-31 14:53:29 +01:00
return gip - > compress ;
}
2017-03-05 16:44:50 +01:00
float RasterizerStorageGLES3 : : gi_probe_get_energy ( RID p_probe ) const {
2016-12-22 14:00:15 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , 0 ) ;
2016-12-22 14:00:15 +01:00
return gip - > energy ;
}
2017-03-05 16:44:50 +01:00
float RasterizerStorageGLES3 : : gi_probe_get_bias ( RID p_probe ) const {
2017-02-16 12:55:11 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , 0 ) ;
2017-02-16 12:55:11 +01:00
return gip - > bias ;
}
2017-07-16 04:24:37 +02:00
float RasterizerStorageGLES3 : : gi_probe_get_normal_bias ( RID p_probe ) const {
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
ERR_FAIL_COND_V ( ! gip , 0 ) ;
return gip - > normal_bias ;
}
2017-03-05 16:44:50 +01:00
float RasterizerStorageGLES3 : : gi_probe_get_propagation ( RID p_probe ) const {
2017-02-06 09:12:15 +01:00
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , 0 ) ;
2017-02-06 09:12:15 +01:00
return gip - > propagation ;
}
2016-12-20 04:21:07 +01:00
uint32_t RasterizerStorageGLES3 : : gi_probe_get_version ( RID p_probe ) {
const GIProbe * gip = gi_probe_owner . getornull ( p_probe ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! gip , 0 ) ;
2016-12-20 04:21:07 +01:00
return gip - > version ;
}
2016-12-30 12:35:54 +01:00
RasterizerStorage : : GIProbeCompression RasterizerStorageGLES3 : : gi_probe_get_dynamic_data_get_preferred_compression ( ) const {
if ( config . s3tc_supported ) {
return GI_PROBE_S3TC ;
} else {
return GI_PROBE_UNCOMPRESSED ;
}
}
RID RasterizerStorageGLES3 : : gi_probe_dynamic_data_create ( int p_width , int p_height , int p_depth , GIProbeCompression p_compression ) {
2016-12-20 04:21:07 +01:00
2017-03-05 16:44:50 +01:00
GIProbeData * gipd = memnew ( GIProbeData ) ;
2016-12-20 04:21:07 +01:00
2017-03-05 16:44:50 +01:00
gipd - > width = p_width ;
gipd - > height = p_height ;
gipd - > depth = p_depth ;
gipd - > compression = p_compression ;
2016-12-20 04:21:07 +01:00
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glGenTextures ( 1 , & gipd - > tex_id ) ;
glBindTexture ( GL_TEXTURE_3D , gipd - > tex_id ) ;
2016-12-20 04:21:07 +01:00
2017-03-05 16:44:50 +01:00
int level = 0 ;
int min_size = 1 ;
2016-12-30 12:35:54 +01:00
2017-03-05 16:44:50 +01:00
if ( gipd - > compression = = GI_PROBE_S3TC ) {
min_size = 4 ;
2016-12-30 12:35:54 +01:00
}
2016-12-20 04:21:07 +01:00
2017-03-05 16:44:50 +01:00
while ( true ) {
2016-12-20 04:21:07 +01:00
2017-03-05 16:44:50 +01:00
if ( gipd - > compression = = GI_PROBE_S3TC ) {
2016-12-30 12:35:54 +01:00
int size = p_width * p_height * p_depth ;
2017-03-05 16:44:50 +01:00
glCompressedTexImage3D ( GL_TEXTURE_3D , level , _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT , p_width , p_height , p_depth , 0 , size , NULL ) ;
2016-12-30 12:35:54 +01:00
} else {
2017-03-05 16:44:50 +01:00
glTexImage3D ( GL_TEXTURE_3D , level , GL_RGBA8 , p_width , p_height , p_depth , 0 , GL_RGBA , GL_UNSIGNED_BYTE , NULL ) ;
2016-12-20 04:21:07 +01:00
}
2017-03-05 16:44:50 +01:00
if ( p_width < = min_size | | p_height < = min_size | | p_depth < = min_size )
2016-12-20 04:21:07 +01:00
break ;
2017-03-05 16:44:50 +01:00
p_width > > = 1 ;
p_height > > = 1 ;
p_depth > > = 1 ;
2016-12-20 04:21:07 +01:00
level + + ;
}
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_MAX_LEVEL , level ) ;
2017-03-05 16:44:50 +01:00
gipd - > levels = level + 1 ;
2016-12-20 04:21:07 +01:00
return gi_probe_data_owner . make_rid ( gipd ) ;
}
2016-12-30 12:35:54 +01:00
void RasterizerStorageGLES3 : : gi_probe_dynamic_data_update ( RID p_gi_probe_data , int p_depth_slice , int p_slice_count , int p_mipmap , const void * p_data ) {
2016-12-20 04:21:07 +01:00
GIProbeData * gipd = gi_probe_data_owner . getornull ( p_gi_probe_data ) ;
ERR_FAIL_COND ( ! gipd ) ;
2017-03-05 16:44:50 +01:00
/*
2016-12-20 04:21:07 +01:00
Vector < uint8_t > data ;
data . resize ( ( gipd - > width > > p_mipmap ) * ( gipd - > height > > p_mipmap ) * ( gipd - > depth > > p_mipmap ) * 4 ) ;
for ( int i = 0 ; i < ( gipd - > width > > p_mipmap ) ; i + + ) {
for ( int j = 0 ; j < ( gipd - > height > > p_mipmap ) ; j + + ) {
for ( int k = 0 ; k < ( gipd - > depth > > p_mipmap ) ; k + + ) {
int ofs = ( k * ( gipd - > height > > p_mipmap ) * ( gipd - > width > > p_mipmap ) ) + j * ( gipd - > width > > p_mipmap ) + i ;
ofs * = 4 ;
data [ ofs + 0 ] = i * 0xFF / ( gipd - > width > > p_mipmap ) ;
data [ ofs + 1 ] = j * 0xFF / ( gipd - > height > > p_mipmap ) ;
data [ ofs + 2 ] = k * 0xFF / ( gipd - > depth > > p_mipmap ) ;
data [ ofs + 3 ] = 0xFF ;
}
}
}
*/
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_3D , gipd - > tex_id ) ;
if ( gipd - > compression = = GI_PROBE_S3TC ) {
int size = ( gipd - > width > > p_mipmap ) * ( gipd - > height > > p_mipmap ) * p_slice_count ;
glCompressedTexSubImage3D ( GL_TEXTURE_3D , p_mipmap , 0 , 0 , p_depth_slice , gipd - > width > > p_mipmap , gipd - > height > > p_mipmap , p_slice_count , _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT , size , p_data ) ;
2016-12-30 12:35:54 +01:00
} else {
2017-03-05 16:44:50 +01:00
glTexSubImage3D ( GL_TEXTURE_3D , p_mipmap , 0 , 0 , p_depth_slice , gipd - > width > > p_mipmap , gipd - > height > > p_mipmap , p_slice_count , GL_RGBA , GL_UNSIGNED_BYTE , p_data ) ;
2016-12-30 12:35:54 +01:00
}
2016-12-20 04:21:07 +01:00
//glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data);
//glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr());
2016-12-30 12:35:54 +01:00
}
2017-12-14 12:59:46 +01:00
/////////////////////////////
RID RasterizerStorageGLES3 : : lightmap_capture_create ( ) {
LightmapCapture * capture = memnew ( LightmapCapture ) ;
return lightmap_capture_data_owner . make_rid ( capture ) ;
}
void RasterizerStorageGLES3 : : lightmap_capture_set_bounds ( RID p_capture , const AABB & p_bounds ) {
LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND ( ! capture ) ;
capture - > bounds = p_bounds ;
2018-11-14 13:32:39 +01:00
capture - > instance_change_notify ( true , false ) ;
2017-12-14 12:59:46 +01:00
}
AABB RasterizerStorageGLES3 : : lightmap_capture_get_bounds ( RID p_capture ) const {
const LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND_V ( ! capture , AABB ( ) ) ;
return capture - > bounds ;
}
void RasterizerStorageGLES3 : : lightmap_capture_set_octree ( RID p_capture , const PoolVector < uint8_t > & p_octree ) {
LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND ( ! capture ) ;
ERR_FAIL_COND ( p_octree . size ( ) = = 0 | | ( p_octree . size ( ) % sizeof ( LightmapCaptureOctree ) ) ! = 0 ) ;
capture - > octree . resize ( p_octree . size ( ) / sizeof ( LightmapCaptureOctree ) ) ;
if ( p_octree . size ( ) ) {
PoolVector < LightmapCaptureOctree > : : Write w = capture - > octree . write ( ) ;
PoolVector < uint8_t > : : Read r = p_octree . read ( ) ;
copymem ( w . ptr ( ) , r . ptr ( ) , p_octree . size ( ) ) ;
}
2018-11-14 13:32:39 +01:00
capture - > instance_change_notify ( true , false ) ;
2017-12-14 12:59:46 +01:00
}
PoolVector < uint8_t > RasterizerStorageGLES3 : : lightmap_capture_get_octree ( RID p_capture ) const {
const LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND_V ( ! capture , PoolVector < uint8_t > ( ) ) ;
if ( capture - > octree . size ( ) = = 0 )
return PoolVector < uint8_t > ( ) ;
PoolVector < uint8_t > ret ;
ret . resize ( capture - > octree . size ( ) * sizeof ( LightmapCaptureOctree ) ) ;
{
PoolVector < LightmapCaptureOctree > : : Read r = capture - > octree . read ( ) ;
PoolVector < uint8_t > : : Write w = ret . write ( ) ;
copymem ( w . ptr ( ) , r . ptr ( ) , ret . size ( ) ) ;
}
return ret ;
}
void RasterizerStorageGLES3 : : lightmap_capture_set_octree_cell_transform ( RID p_capture , const Transform & p_xform ) {
LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND ( ! capture ) ;
capture - > cell_xform = p_xform ;
}
Transform RasterizerStorageGLES3 : : lightmap_capture_get_octree_cell_transform ( RID p_capture ) const {
const LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND_V ( ! capture , Transform ( ) ) ;
return capture - > cell_xform ;
}
void RasterizerStorageGLES3 : : lightmap_capture_set_octree_cell_subdiv ( RID p_capture , int p_subdiv ) {
LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND ( ! capture ) ;
capture - > cell_subdiv = p_subdiv ;
}
int RasterizerStorageGLES3 : : lightmap_capture_get_octree_cell_subdiv ( RID p_capture ) const {
const LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND_V ( ! capture , 0 ) ;
return capture - > cell_subdiv ;
}
void RasterizerStorageGLES3 : : lightmap_capture_set_energy ( RID p_capture , float p_energy ) {
LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND ( ! capture ) ;
capture - > energy = p_energy ;
}
float RasterizerStorageGLES3 : : lightmap_capture_get_energy ( RID p_capture ) const {
const LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND_V ( ! capture , 0 ) ;
return capture - > energy ;
}
const PoolVector < RasterizerStorage : : LightmapCaptureOctree > * RasterizerStorageGLES3 : : lightmap_capture_get_octree_ptr ( RID p_capture ) const {
const LightmapCapture * capture = lightmap_capture_data_owner . getornull ( p_capture ) ;
ERR_FAIL_COND_V ( ! capture , NULL ) ;
return & capture - > octree ;
}
2016-12-30 12:35:54 +01:00
///////
RID RasterizerStorageGLES3 : : particles_create ( ) {
2017-03-05 16:44:50 +01:00
Particles * particles = memnew ( Particles ) ;
2016-12-30 12:35:54 +01:00
return particles_owner . make_rid ( particles ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_emitting ( RID p_particles , bool p_emitting ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2019-06-22 07:33:11 +02:00
2017-03-05 16:44:50 +01:00
particles - > emitting = p_emitting ;
2016-12-30 12:35:54 +01:00
}
2017-12-23 05:08:50 +01:00
bool RasterizerStorageGLES3 : : particles_get_emitting ( RID p_particles ) {
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND_V ( ! particles , false ) ;
return particles - > emitting ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_amount ( RID p_particles , int p_amount ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-04-07 04:36:37 +02:00
particles - > amount = p_amount ;
2017-03-05 16:44:50 +01:00
int floats = p_amount * 24 ;
float * data = memnew_arr ( float , floats ) ;
2017-01-02 02:16:52 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < floats ; i + + ) {
data [ i ] = 0 ;
2017-01-02 02:16:52 +01:00
}
2017-04-07 04:36:37 +02:00
for ( int i = 0 ; i < 2 ; i + + ) {
2017-01-02 02:16:52 +01:00
2017-04-07 04:36:37 +02:00
glBindVertexArray ( particles - > particle_vaos [ i ] ) ;
2017-01-02 02:16:52 +01:00
2017-04-07 04:36:37 +02:00
glBindBuffer ( GL_ARRAY_BUFFER , particles - > particle_buffers [ i ] ) ;
2017-10-03 22:34:08 +02:00
glBufferData ( GL_ARRAY_BUFFER , floats * sizeof ( float ) , data , GL_STATIC_DRAW ) ;
2017-04-07 04:36:37 +02:00
2019-02-12 21:10:08 +01:00
for ( int j = 0 ; j < 6 ; j + + ) {
glEnableVertexAttribArray ( j ) ;
2019-04-06 21:01:49 +02:00
glVertexAttribPointer ( j , 4 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 * 6 , CAST_INT_TO_UCHAR_PTR ( j * 16 ) ) ;
2017-04-07 04:36:37 +02:00
}
}
2017-04-09 03:38:11 +02:00
if ( particles - > histories_enabled ) {
for ( int i = 0 ; i < 2 ; i + + ) {
glBindVertexArray ( particles - > particle_vao_histories [ i ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , particles - > particle_buffer_histories [ i ] ) ;
glBufferData ( GL_ARRAY_BUFFER , floats * sizeof ( float ) , data , GL_DYNAMIC_COPY ) ;
for ( int j = 0 ; j < 6 ; j + + ) {
glEnableVertexAttribArray ( j ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( j , 4 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 * 6 , CAST_INT_TO_UCHAR_PTR ( j * 16 ) ) ;
2017-04-09 03:38:11 +02:00
}
particles - > particle_valid_histories [ i ] = false ;
}
}
2017-04-07 04:36:37 +02:00
glBindVertexArray ( 0 ) ;
2017-01-02 02:16:52 +01:00
2017-03-05 16:44:50 +01:00
particles - > prev_ticks = 0 ;
particles - > phase = 0 ;
particles - > prev_phase = 0 ;
2017-04-07 04:36:37 +02:00
particles - > clear = true ;
2017-01-02 02:16:52 +01:00
memdelete_arr ( data ) ;
2016-12-30 12:35:54 +01:00
}
2017-01-02 02:16:52 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_lifetime ( RID p_particles , float p_lifetime ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
particles - > lifetime = p_lifetime ;
2016-12-30 12:35:54 +01:00
}
2017-06-25 13:01:15 +02:00
void RasterizerStorageGLES3 : : particles_set_one_shot ( RID p_particles , bool p_one_shot ) {
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
particles - > one_shot = p_one_shot ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_pre_process_time ( RID p_particles , float p_time ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
particles - > pre_process_time = p_time ;
2016-12-30 12:35:54 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_explosiveness_ratio ( RID p_particles , float p_ratio ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
particles - > explosiveness = p_ratio ;
2016-12-30 12:35:54 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_randomness_ratio ( RID p_particles , float p_ratio ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
particles - > randomness = p_ratio ;
2016-12-30 12:35:54 +01:00
}
2017-04-09 03:38:11 +02:00
void RasterizerStorageGLES3 : : _particles_update_histories ( Particles * particles ) {
bool needs_histories = particles - > draw_order = = VS : : PARTICLES_DRAW_ORDER_VIEW_DEPTH ;
if ( needs_histories = = particles - > histories_enabled )
return ;
particles - > histories_enabled = needs_histories ;
int floats = particles - > amount * 24 ;
if ( ! needs_histories ) {
glDeleteBuffers ( 2 , particles - > particle_buffer_histories ) ;
glDeleteVertexArrays ( 2 , particles - > particle_vao_histories ) ;
} else {
glGenBuffers ( 2 , particles - > particle_buffer_histories ) ;
glGenVertexArrays ( 2 , particles - > particle_vao_histories ) ;
for ( int i = 0 ; i < 2 ; i + + ) {
glBindVertexArray ( particles - > particle_vao_histories [ i ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , particles - > particle_buffer_histories [ i ] ) ;
glBufferData ( GL_ARRAY_BUFFER , floats * sizeof ( float ) , NULL , GL_DYNAMIC_COPY ) ;
for ( int j = 0 ; j < 6 ; j + + ) {
glEnableVertexAttribArray ( j ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( j , 4 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 * 6 , CAST_INT_TO_UCHAR_PTR ( j * 16 ) ) ;
2017-04-09 03:38:11 +02:00
}
particles - > particle_valid_histories [ i ] = false ;
}
}
particles - > clear = true ;
}
2017-11-17 03:09:00 +01:00
void RasterizerStorageGLES3 : : particles_set_custom_aabb ( RID p_particles , const AABB & p_aabb ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
particles - > custom_aabb = p_aabb ;
2017-04-09 03:38:11 +02:00
_particles_update_histories ( particles ) ;
2018-11-14 13:32:39 +01:00
particles - > instance_change_notify ( true , false ) ;
2016-12-20 04:21:07 +01:00
}
2017-04-09 03:38:11 +02:00
void RasterizerStorageGLES3 : : particles_set_speed_scale ( RID p_particles , float p_scale ) {
2016-12-20 04:21:07 +01:00
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2016-12-20 04:21:07 +01:00
2017-04-09 03:38:11 +02:00
particles - > speed_scale = p_scale ;
2016-12-30 12:35:54 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_use_local_coordinates ( RID p_particles , bool p_enable ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
particles - > use_local_coords = p_enable ;
2016-12-30 12:35:54 +01:00
}
2017-04-07 04:36:37 +02:00
void RasterizerStorageGLES3 : : particles_set_fixed_fps ( RID p_particles , int p_fps ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-04-07 04:36:37 +02:00
particles - > fixed_fps = p_fps ;
2016-12-30 12:35:54 +01:00
}
2017-04-07 04:36:37 +02:00
void RasterizerStorageGLES3 : : particles_set_fractional_delta ( RID p_particles , bool p_enable ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-04-07 04:36:37 +02:00
particles - > fractional_delta = p_enable ;
2016-12-30 12:35:54 +01:00
}
2017-04-07 04:36:37 +02:00
void RasterizerStorageGLES3 : : particles_set_process_material ( RID p_particles , RID p_material ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-04-07 04:36:37 +02:00
particles - > process_material = p_material ;
2016-12-30 12:35:54 +01:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : particles_set_draw_order ( RID p_particles , VS : : ParticlesDrawOrder p_order ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
particles - > draw_order = p_order ;
2017-04-09 03:38:11 +02:00
_particles_update_histories ( particles ) ;
2016-12-30 12:35:54 +01:00
}
2017-04-07 04:36:37 +02:00
void RasterizerStorageGLES3 : : particles_set_draw_passes ( RID p_particles , int p_passes ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-04-07 04:36:37 +02:00
particles - > draw_passes . resize ( p_passes ) ;
2016-12-30 12:35:54 +01:00
}
2017-04-07 04:36:37 +02:00
void RasterizerStorageGLES3 : : particles_set_draw_pass_mesh ( RID p_particles , int p_pass , RID p_mesh ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_pass , particles - > draw_passes . size ( ) ) ;
2018-07-25 03:11:03 +02:00
particles - > draw_passes . write [ p_pass ] = p_mesh ;
2016-12-30 12:35:54 +01:00
}
2017-04-07 04:36:37 +02:00
2017-06-25 13:01:15 +02:00
void RasterizerStorageGLES3 : : particles_restart ( RID p_particles ) {
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
particles - > restart_request = true ;
}
2017-04-07 04:36:37 +02:00
void RasterizerStorageGLES3 : : particles_request_process ( RID p_particles ) {
2016-12-30 12:35:54 +01:00
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
2017-04-07 04:36:37 +02:00
if ( ! particles - > particle_element . in_list ( ) ) {
particle_update_list . add ( & particles - > particle_element ) ;
}
2016-12-30 12:35:54 +01:00
}
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : particles_get_current_aabb ( RID p_particles ) {
2016-12-30 12:35:54 +01:00
const Particles * particles = particles_owner . getornull ( p_particles ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! particles , AABB ( ) ) ;
2016-12-30 12:35:54 +01:00
2018-10-29 20:39:18 +01:00
const float * data ;
2017-04-09 03:38:11 +02:00
glBindBuffer ( GL_ARRAY_BUFFER , particles - > particle_buffers [ 0 ] ) ;
2018-10-29 20:39:18 +01:00
# if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
PoolVector < uint8_t > vector ;
vector . resize ( particles - > amount * 16 * 6 ) ;
{
PoolVector < uint8_t > : : Write w = vector . write ( ) ;
glGetBufferSubData ( GL_ARRAY_BUFFER , 0 , particles - > amount * 16 * 6 , w . ptr ( ) ) ;
}
PoolVector < uint8_t > : : Read r = vector . read ( ) ;
data = reinterpret_cast < const float * > ( r . ptr ( ) ) ;
# else
data = ( float * ) glMapBufferRange ( GL_ARRAY_BUFFER , 0 , particles - > amount * 16 * 6 , GL_MAP_READ_BIT ) ;
# endif
2017-11-17 03:09:00 +01:00
AABB aabb ;
2017-04-09 03:38:11 +02:00
Transform inv = particles - > emission_transform . affine_inverse ( ) ;
for ( int i = 0 ; i < particles - > amount ; i + + ) {
int ofs = i * 24 ;
Vector3 pos = Vector3 ( data [ ofs + 15 ] , data [ ofs + 19 ] , data [ ofs + 23 ] ) ;
if ( ! particles - > use_local_coords ) {
pos = inv . xform ( pos ) ;
}
if ( i = = 0 )
2017-06-06 20:33:51 +02:00
aabb . position = pos ;
2017-04-09 03:38:11 +02:00
else
aabb . expand_to ( pos ) ;
}
2018-10-29 20:39:18 +01:00
# if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
2019-07-05 19:08:43 +02:00
r . release ( ) ;
2018-10-29 20:39:18 +01:00
vector = PoolVector < uint8_t > ( ) ;
# else
2017-04-09 03:38:11 +02:00
glUnmapBuffer ( GL_ARRAY_BUFFER ) ;
2018-10-29 20:39:18 +01:00
# endif
2017-04-09 03:38:11 +02:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
float longest_axis = 0 ;
for ( int i = 0 ; i < particles - > draw_passes . size ( ) ; i + + ) {
if ( particles - > draw_passes [ i ] . is_valid ( ) ) {
2017-11-17 03:09:00 +01:00
AABB maabb = mesh_get_aabb ( particles - > draw_passes [ i ] , RID ( ) ) ;
2017-04-09 03:38:11 +02:00
longest_axis = MAX ( maabb . get_longest_axis_size ( ) , longest_axis ) ;
}
}
aabb . grow_by ( longest_axis ) ;
return aabb ;
2016-12-30 12:35:54 +01:00
}
2016-12-20 04:21:07 +01:00
2017-11-17 03:09:00 +01:00
AABB RasterizerStorageGLES3 : : particles_get_aabb ( RID p_particles ) const {
2017-04-07 04:36:37 +02:00
const Particles * particles = particles_owner . getornull ( p_particles ) ;
2017-11-17 03:09:00 +01:00
ERR_FAIL_COND_V ( ! particles , AABB ( ) ) ;
2017-04-07 04:36:37 +02:00
2017-04-09 03:38:11 +02:00
return particles - > custom_aabb ;
2017-04-07 04:36:37 +02:00
}
void RasterizerStorageGLES3 : : particles_set_emission_transform ( RID p_particles , const Transform & p_transform ) {
Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND ( ! particles ) ;
particles - > emission_transform = p_transform ;
}
2017-06-17 12:32:49 +02:00
int RasterizerStorageGLES3 : : particles_get_draw_passes ( RID p_particles ) const {
const Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND_V ( ! particles , 0 ) ;
return particles - > draw_passes . size ( ) ;
}
RID RasterizerStorageGLES3 : : particles_get_draw_pass_mesh ( RID p_particles , int p_pass ) const {
const Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND_V ( ! particles , RID ( ) ) ;
ERR_FAIL_INDEX_V ( p_pass , particles - > draw_passes . size ( ) , RID ( ) ) ;
return particles - > draw_passes [ p_pass ] ;
}
2017-08-11 21:10:05 +02:00
void RasterizerStorageGLES3 : : _particles_process ( Particles * p_particles , float p_delta ) {
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
float new_phase = Math : : fmod ( ( float ) p_particles - > phase + ( p_delta / p_particles - > lifetime ) * p_particles - > speed_scale , ( float ) 1.0 ) ;
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
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 ;
2017-06-25 13:01:15 +02:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : EMITTING , false ) ;
}
2017-08-11 21:10:05 +02:00
p_particles - > cycle_number + + ;
2017-04-07 04:36:37 +02:00
}
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : SYSTEM_PHASE , new_phase ) ;
2017-08-11 21:10:05 +02:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : PREV_SYSTEM_PHASE , p_particles - > phase ) ;
p_particles - > phase = new_phase ;
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
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 ) ;
2017-06-23 19:31:21 +02:00
2017-08-11 21:10:05 +02:00
if ( p_particles - > use_local_coords )
2017-04-07 04:36:37 +02:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : EMISSION_TRANSFORM , Transform ( ) ) ;
else
2017-08-11 21:10:05 +02:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : EMISSION_TRANSFORM , p_particles - > emission_transform ) ;
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
glUniform1ui ( shaders . particles . get_uniform ( ParticlesShaderGLES3 : : CYCLE ) , p_particles - > cycle_number ) ;
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
p_particles - > clear = false ;
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
glBindVertexArray ( p_particles - > particle_vaos [ 0 ] ) ;
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER , 0 , p_particles - > particle_buffers [ 1 ] ) ;
2017-04-07 04:36:37 +02:00
// GLint size = 0;
// glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
glBeginTransformFeedback ( GL_POINTS ) ;
2017-08-11 21:10:05 +02:00
glDrawArrays ( GL_POINTS , 0 , p_particles - > amount ) ;
2017-04-07 04:36:37 +02:00
glEndTransformFeedback ( ) ;
2017-08-11 21:10:05 +02:00
SWAP ( p_particles - > particle_buffers [ 0 ] , p_particles - > particle_buffers [ 1 ] ) ;
SWAP ( p_particles - > particle_vaos [ 0 ] , p_particles - > particle_vaos [ 1 ] ) ;
2017-04-07 04:36:37 +02:00
2018-01-15 20:39:17 +01:00
glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER , 0 , 0 ) ;
2017-04-07 04:36:37 +02:00
glBindVertexArray ( 0 ) ;
/* //debug particles :D
2017-08-11 21:10:05 +02:00
glBindBuffer ( GL_ARRAY_BUFFER , p_particles - > particle_buffers [ 0 ] ) ;
2017-04-07 04:36:37 +02:00
2017-08-11 21:10:05 +02:00
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 + + ) {
2017-04-07 04:36:37 +02:00
int ofs = i * 24 ;
print_line ( itos ( i ) + " : " ) ;
print_line ( " \t Color: " + Color ( data [ ofs + 0 ] , data [ ofs + 1 ] , data [ ofs + 2 ] , data [ ofs + 3 ] ) ) ;
print_line ( " \t Velocity: " + Vector3 ( data [ ofs + 4 ] , data [ ofs + 5 ] , data [ ofs + 6 ] ) ) ;
print_line ( " \t Active: " + itos ( data [ ofs + 7 ] ) ) ;
print_line ( " \t Custom: " + Color ( data [ ofs + 8 ] , data [ ofs + 9 ] , data [ ofs + 10 ] , data [ ofs + 11 ] ) ) ;
print_line ( " \t XF X: " + Color ( data [ ofs + 12 ] , data [ ofs + 13 ] , data [ ofs + 14 ] , data [ ofs + 15 ] ) ) ;
print_line ( " \t XF Y: " + Color ( data [ ofs + 16 ] , data [ ofs + 17 ] , data [ ofs + 18 ] , data [ ofs + 19 ] ) ) ;
print_line ( " \t XF Z: " + Color ( data [ ofs + 20 ] , data [ ofs + 21 ] , data [ ofs + 22 ] , data [ ofs + 23 ] ) ) ;
}
glUnmapBuffer ( GL_ARRAY_BUFFER ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
//*/
}
2017-01-02 02:16:52 +01:00
void RasterizerStorageGLES3 : : update_particles ( ) {
glEnable ( GL_RASTERIZER_DISCARD ) ;
while ( particle_update_list . first ( ) ) {
//use transform feedback to process particles
Particles * particles = particle_update_list . first ( ) - > self ( ) ;
2017-06-25 13:01:15 +02:00
if ( particles - > restart_request ) {
particles - > prev_ticks = 0 ;
particles - > phase = 0 ;
particles - > prev_phase = 0 ;
particles - > clear = true ;
particles - > particle_valid_histories [ 0 ] = false ;
particles - > particle_valid_histories [ 1 ] = false ;
particles - > restart_request = false ;
}
2017-06-23 19:31:21 +02:00
if ( particles - > inactive & & ! particles - > emitting ) {
particle_update_list . remove ( particle_update_list . first ( ) ) ;
continue ;
}
if ( particles - > emitting ) {
if ( particles - > inactive ) {
//restart system from scratch
particles - > prev_ticks = 0 ;
particles - > phase = 0 ;
particles - > prev_phase = 0 ;
particles - > clear = true ;
particles - > particle_valid_histories [ 0 ] = false ;
particles - > particle_valid_histories [ 1 ] = false ;
}
particles - > inactive = false ;
particles - > inactive_time = 0 ;
} else {
particles - > inactive_time + = particles - > speed_scale * frame . delta ;
if ( particles - > inactive_time > particles - > lifetime * 1.2 ) {
particles - > inactive = true ;
particle_update_list . remove ( particle_update_list . first ( ) ) ;
continue ;
}
}
2017-01-02 02:16:52 +01:00
Material * material = material_owner . getornull ( particles - > process_material ) ;
2017-03-05 16:44:50 +01:00
if ( ! material | | ! material - > shader | | material - > shader - > mode ! = VS : : SHADER_PARTICLES ) {
2017-01-02 02:16:52 +01:00
shaders . particles . set_custom_shader ( 0 ) ;
} else {
2017-03-05 16:44:50 +01:00
shaders . particles . set_custom_shader ( material - > shader - > custom_code_id ) ;
2017-01-02 02:16:52 +01:00
if ( material - > ubo_id ) {
2017-03-05 16:44:50 +01:00
glBindBufferBase ( GL_UNIFORM_BUFFER , 0 , material - > ubo_id ) ;
2017-01-02 02:16:52 +01:00
}
int tc = material - > textures . size ( ) ;
2017-11-25 04:07:54 +01:00
RID * textures = material - > textures . ptrw ( ) ;
ShaderLanguage : : ShaderNode : : Uniform : : Hint * texture_hints = material - > shader - > texture_hints . ptrw ( ) ;
2017-01-02 02:16:52 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < tc ; i + + ) {
2017-01-02 02:16:52 +01:00
2017-03-05 16:44:50 +01:00
glActiveTexture ( GL_TEXTURE0 + i ) ;
2017-01-02 02:16:52 +01:00
GLenum target ;
GLuint tex ;
2017-03-05 16:44:50 +01:00
RasterizerStorageGLES3 : : Texture * t = texture_owner . getornull ( textures [ i ] ) ;
2017-01-02 02:16:52 +01:00
if ( ! t ) {
//check hints
2017-03-05 16:44:50 +01:00
target = GL_TEXTURE_2D ;
2017-01-02 02:16:52 +01:00
2017-03-05 16:44:50 +01:00
switch ( texture_hints [ i ] ) {
2017-01-02 02:16:52 +01:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_BLACK_ALBEDO :
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_BLACK : {
2017-03-05 16:44:50 +01:00
tex = resources . black_tex ;
2017-01-02 02:16:52 +01:00
} break ;
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_ANISO : {
2017-03-05 16:44:50 +01:00
tex = resources . aniso_tex ;
2017-01-02 02:16:52 +01:00
} break ;
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_NORMAL : {
2017-03-05 16:44:50 +01:00
tex = resources . normal_tex ;
2017-01-02 02:16:52 +01:00
} break ;
default : {
2017-03-05 16:44:50 +01:00
tex = resources . white_tex ;
2017-01-02 02:16:52 +01:00
} break ;
}
} else {
2018-05-19 04:37:26 +02:00
t = t - > get_ptr ( ) ; //resolve for proxies
2017-03-05 16:44:50 +01:00
target = t - > target ;
2017-01-02 02:16:52 +01:00
tex = t - > tex_id ;
}
2017-03-05 16:44:50 +01:00
glBindTexture ( target , tex ) ;
2017-01-02 02:16:52 +01:00
}
}
2017-04-07 04:36:37 +02:00
shaders . particles . set_conditional ( ParticlesShaderGLES3 : : USE_FRACTIONAL_DELTA , particles - > fractional_delta ) ;
2017-01-02 02:16:52 +01:00
2017-04-07 04:36:37 +02:00
shaders . particles . bind ( ) ;
2017-01-02 02:16:52 +01:00
2017-03-05 16:44:50 +01:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : TOTAL_PARTICLES , particles - > amount ) ;
2017-06-16 13:29:43 +02:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : TIME , frame . time [ 0 ] ) ;
2017-03-05 16:44:50 +01:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : EXPLOSIVENESS , particles - > explosiveness ) ;
2017-04-07 04:36:37 +02:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : LIFETIME , particles - > lifetime ) ;
2017-03-05 16:44:50 +01:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : ATTRACTOR_COUNT , 0 ) ;
2017-04-07 04:36:37 +02:00
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : EMITTING , particles - > emitting ) ;
shaders . particles . set_uniform ( ParticlesShaderGLES3 : : RANDOMNESS , particles - > randomness ) ;
2017-01-02 02:16:52 +01:00
2018-02-08 20:57:10 +01:00
bool zero_time_scale = Engine : : get_singleton ( ) - > get_time_scale ( ) < = 0.0 ;
2017-04-07 04:36:37 +02:00
if ( particles - > clear & & particles - > pre_process_time > 0.0 ) {
2017-01-02 02:16:52 +01:00
2017-04-07 04:36:37 +02:00
float frame_time ;
if ( particles - > fixed_fps > 0 )
frame_time = 1.0 / particles - > fixed_fps ;
else
frame_time = 1.0 / 30.0 ;
2017-11-25 15:41:14 +01:00
float todo = particles - > pre_process_time ;
2017-04-07 04:36:37 +02:00
2017-11-25 15:41:14 +01:00
while ( todo > = 0 ) {
2017-04-07 04:36:37 +02:00
_particles_process ( particles , frame_time ) ;
todo - = frame_time ;
}
2017-01-02 02:16:52 +01:00
}
2017-04-07 04:36:37 +02:00
if ( particles - > fixed_fps > 0 ) {
2018-02-08 20:57:10 +01:00
float frame_time ;
float decr ;
if ( zero_time_scale ) {
frame_time = 0.0 ;
decr = 1.0 / particles - > fixed_fps ;
} else {
frame_time = 1.0 / particles - > fixed_fps ;
decr = frame_time ;
}
2017-04-07 04:36:37 +02:00
float delta = frame . delta ;
if ( delta > 0.1 ) { //avoid recursive stalls if fps goes below 10
delta = 0.1 ;
} else if ( delta < = 0.0 ) { //unlikely but..
delta = 0.001 ;
}
float todo = particles - > frame_remainder + delta ;
2017-01-02 02:16:52 +01:00
2017-04-07 04:36:37 +02:00
while ( todo > = frame_time ) {
_particles_process ( particles , frame_time ) ;
2018-02-08 20:57:10 +01:00
todo - = decr ;
2017-04-07 04:36:37 +02:00
}
particles - > frame_remainder = todo ;
} else {
2018-02-08 20:57:10 +01:00
if ( zero_time_scale )
_particles_process ( particles , 0.0 ) ;
else
_particles_process ( particles , frame . delta ) ;
2017-04-07 04:36:37 +02:00
}
2017-01-02 02:16:52 +01:00
2017-04-07 04:36:37 +02:00
particle_update_list . remove ( particle_update_list . first ( ) ) ;
2017-04-09 03:38:11 +02:00
if ( particles - > histories_enabled ) {
SWAP ( particles - > particle_buffer_histories [ 0 ] , particles - > particle_buffer_histories [ 1 ] ) ;
SWAP ( particles - > particle_vao_histories [ 0 ] , particles - > particle_vao_histories [ 1 ] ) ;
SWAP ( particles - > particle_valid_histories [ 0 ] , particles - > particle_valid_histories [ 1 ] ) ;
//copy
glBindBuffer ( GL_COPY_READ_BUFFER , particles - > particle_buffers [ 0 ] ) ;
glBindBuffer ( GL_COPY_WRITE_BUFFER , particles - > particle_buffer_histories [ 0 ] ) ;
glCopyBufferSubData ( GL_COPY_READ_BUFFER , GL_COPY_WRITE_BUFFER , 0 , 0 , particles - > amount * 24 * sizeof ( float ) ) ;
particles - > particle_valid_histories [ 0 ] = true ;
}
2017-06-17 12:32:49 +02:00
2018-11-14 13:32:39 +01:00
particles - > instance_change_notify ( true , false ) ; //make sure shadows are updated
2017-01-02 02:16:52 +01:00
}
glDisable ( GL_RASTERIZER_DISCARD ) ;
}
2018-11-20 00:34:29 +01:00
bool RasterizerStorageGLES3 : : particles_is_inactive ( RID p_particles ) const {
const Particles * particles = particles_owner . getornull ( p_particles ) ;
ERR_FAIL_COND_V ( ! particles , false ) ;
return ! particles - > emitting & & particles - > inactive ;
}
2016-12-30 12:35:54 +01:00
////////
2016-12-20 04:21:07 +01:00
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : instance_add_skeleton ( RID p_skeleton , RasterizerScene : : InstanceBase * p_instance ) {
2016-11-25 00:46:55 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
ERR_FAIL_COND ( ! skeleton ) ;
skeleton - > instances . insert ( p_instance ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : instance_remove_skeleton ( RID p_skeleton , RasterizerScene : : InstanceBase * p_instance ) {
2016-11-25 00:46:55 +01:00
Skeleton * skeleton = skeleton_owner . getornull ( p_skeleton ) ;
ERR_FAIL_COND ( ! skeleton ) ;
skeleton - > instances . erase ( p_instance ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : instance_add_dependency ( RID p_base , RasterizerScene : : InstanceBase * p_instance ) {
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
Instantiable * inst = NULL ;
switch ( p_instance - > base_type ) {
2016-10-19 16:14:41 +02:00
case VS : : INSTANCE_MESH : {
inst = mesh_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-11-22 05:26:56 +01:00
case VS : : INSTANCE_MULTIMESH : {
inst = multimesh_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-11-23 11:04:55 +01:00
case VS : : INSTANCE_IMMEDIATE : {
inst = immediate_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2017-04-07 04:36:37 +02:00
case VS : : INSTANCE_PARTICLES : {
inst = particles_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-11-19 17:23:37 +01:00
case VS : : INSTANCE_REFLECTION_PROBE : {
inst = reflection_probe_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-10-27 16:50:26 +02:00
case VS : : INSTANCE_LIGHT : {
inst = light_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-12-20 04:21:07 +01:00
case VS : : INSTANCE_GI_PROBE : {
inst = gi_probe_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2017-12-14 12:59:46 +01:00
case VS : : INSTANCE_LIGHTMAP_CAPTURE : {
inst = lightmap_capture_data_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-10-19 16:14:41 +02:00
default : {
2019-06-20 16:59:48 +02:00
ERR_FAIL ( ) ;
2016-10-19 16:14:41 +02:00
}
}
2017-03-05 16:44:50 +01:00
inst - > instance_list . add ( & p_instance - > dependency_item ) ;
2016-10-19 16:14:41 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : instance_remove_dependency ( RID p_base , RasterizerScene : : InstanceBase * p_instance ) {
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
Instantiable * inst = NULL ;
2016-10-19 16:14:41 +02:00
2017-03-05 16:44:50 +01:00
switch ( p_instance - > base_type ) {
2016-10-19 16:14:41 +02:00
case VS : : INSTANCE_MESH : {
inst = mesh_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-11-22 05:26:56 +01:00
case VS : : INSTANCE_MULTIMESH : {
inst = multimesh_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-11-23 11:04:55 +01:00
case VS : : INSTANCE_IMMEDIATE : {
inst = immediate_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2017-04-07 04:36:37 +02:00
case VS : : INSTANCE_PARTICLES : {
inst = particles_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-11-19 17:23:37 +01:00
case VS : : INSTANCE_REFLECTION_PROBE : {
inst = reflection_probe_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-10-27 16:50:26 +02:00
case VS : : INSTANCE_LIGHT : {
inst = light_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-12-20 04:21:07 +01:00
case VS : : INSTANCE_GI_PROBE : {
inst = gi_probe_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2017-12-14 12:59:46 +01:00
case VS : : INSTANCE_LIGHTMAP_CAPTURE : {
inst = lightmap_capture_data_owner . getornull ( p_base ) ;
ERR_FAIL_COND ( ! inst ) ;
} break ;
2016-10-19 16:14:41 +02:00
default : {
2019-06-20 16:59:48 +02:00
ERR_FAIL ( ) ;
2016-10-19 16:14:41 +02:00
}
}
2017-03-05 16:44:50 +01:00
inst - > instance_list . remove ( & p_instance - > dependency_item ) ;
2016-10-19 16:14:41 +02:00
}
2016-10-03 21:33:42 +02:00
/* RENDER TARGET */
void RasterizerStorageGLES3 : : _render_target_clear ( RenderTarget * rt ) {
2016-11-29 23:55:12 +01:00
if ( rt - > fbo ) {
2017-03-05 16:44:50 +01:00
glDeleteFramebuffers ( 1 , & rt - > fbo ) ;
glDeleteTextures ( 1 , & rt - > color ) ;
rt - > fbo = 0 ;
2016-10-03 21:33:42 +02:00
}
2017-07-22 19:07:38 +02:00
if ( rt - > buffers . active ) {
2017-03-05 16:44:50 +01:00
glDeleteFramebuffers ( 1 , & rt - > buffers . fbo ) ;
glDeleteRenderbuffers ( 1 , & rt - > buffers . depth ) ;
glDeleteRenderbuffers ( 1 , & rt - > buffers . diffuse ) ;
2017-07-22 19:07:38 +02:00
if ( rt - > buffers . effects_active ) {
glDeleteRenderbuffers ( 1 , & rt - > buffers . specular ) ;
glDeleteRenderbuffers ( 1 , & rt - > buffers . normal_rough ) ;
glDeleteRenderbuffers ( 1 , & rt - > buffers . sss ) ;
glDeleteFramebuffers ( 1 , & rt - > buffers . effect_fbo ) ;
glDeleteTextures ( 1 , & rt - > buffers . effect ) ;
}
2017-01-02 02:16:52 +01:00
2017-07-22 19:07:38 +02:00
rt - > buffers . effects_active = false ;
rt - > buffers . active = false ;
2016-10-03 21:33:42 +02:00
}
if ( rt - > depth ) {
2017-03-05 16:44:50 +01:00
glDeleteTextures ( 1 , & rt - > depth ) ;
rt - > depth = 0 ;
2016-10-03 21:33:42 +02:00
}
2016-12-04 16:45:30 +01:00
if ( rt - > effects . ssao . blur_fbo [ 0 ] ) {
2017-03-05 16:44:50 +01:00
glDeleteFramebuffers ( 1 , & rt - > effects . ssao . blur_fbo [ 0 ] ) ;
glDeleteTextures ( 1 , & rt - > effects . ssao . blur_red [ 0 ] ) ;
glDeleteFramebuffers ( 1 , & rt - > effects . ssao . blur_fbo [ 1 ] ) ;
glDeleteTextures ( 1 , & rt - > effects . ssao . blur_red [ 1 ] ) ;
for ( int i = 0 ; i < rt - > effects . ssao . depth_mipmap_fbos . size ( ) ; i + + ) {
glDeleteFramebuffers ( 1 , & rt - > effects . ssao . depth_mipmap_fbos [ i ] ) ;
2016-12-04 16:45:30 +01:00
}
rt - > effects . ssao . depth_mipmap_fbos . clear ( ) ;
2017-03-05 16:44:50 +01:00
glDeleteTextures ( 1 , & rt - > effects . ssao . linear_depth ) ;
2017-02-07 00:18:35 +01:00
2017-03-05 16:44:50 +01:00
rt - > effects . ssao . blur_fbo [ 0 ] = 0 ;
rt - > effects . ssao . blur_fbo [ 1 ] = 0 ;
2016-12-04 16:45:30 +01:00
}
2016-12-07 21:49:52 +01:00
if ( rt - > exposure . fbo ) {
2017-03-05 16:44:50 +01:00
glDeleteFramebuffers ( 1 , & rt - > exposure . fbo ) ;
glDeleteTextures ( 1 , & rt - > exposure . color ) ;
rt - > exposure . fbo = 0 ;
2016-12-07 21:49:52 +01:00
}
2019-03-30 14:03:49 +01:00
if ( rt - > external . fbo ! = 0 ) {
// free this
glDeleteFramebuffers ( 1 , & rt - > external . fbo ) ;
// clean up our texture
2019-06-10 17:38:51 +02:00
Texture * t = texture_owner . getornull ( rt - > external . texture ) ;
2019-03-30 14:03:49 +01:00
t - > alloc_height = 0 ;
t - > alloc_width = 0 ;
t - > width = 0 ;
t - > height = 0 ;
t - > active = false ;
texture_owner . free ( rt - > external . texture ) ;
memdelete ( t ) ;
rt - > external . fbo = 0 ;
}
2019-06-10 17:38:51 +02:00
Texture * tex = texture_owner . getornull ( rt - > texture ) ;
2017-03-05 16:44:50 +01:00
tex - > alloc_height = 0 ;
tex - > alloc_width = 0 ;
tex - > width = 0 ;
tex - > height = 0 ;
2017-06-09 05:23:50 +02:00
tex - > active = false ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
2017-07-22 19:07:38 +02:00
if ( rt - > effects . mip_maps [ i ] . color ) {
for ( int j = 0 ; j < rt - > effects . mip_maps [ i ] . sizes . size ( ) ; j + + ) {
glDeleteFramebuffers ( 1 , & rt - > effects . mip_maps [ i ] . sizes [ j ] . fbo ) ;
}
2016-11-29 23:55:12 +01:00
2017-07-22 19:07:38 +02:00
glDeleteTextures ( 1 , & rt - > effects . mip_maps [ i ] . color ) ;
rt - > effects . mip_maps [ i ] . sizes . clear ( ) ;
rt - > effects . mip_maps [ i ] . levels = 0 ;
2017-12-19 19:26:18 +01:00
rt - > effects . mip_maps [ i ] . color = 0 ;
2017-07-22 19:07:38 +02:00
}
2016-11-29 23:55:12 +01:00
}
2017-02-07 00:18:35 +01:00
2017-03-05 16:44:50 +01:00
/*
2016-11-29 23:55:12 +01:00
if ( rt - > effects . screen_space_depth ) {
glDeleteTextures ( 1 , & rt - > effects . screen_space_depth ) ;
rt - > effects . screen_space_depth = 0 ;
}
*/
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : _render_target_allocate ( RenderTarget * rt ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( rt - > width < = 0 | | rt - > height < = 0 )
2016-10-03 21:33:42 +02:00
return ;
GLuint color_internal_format ;
GLuint color_format ;
GLuint color_type ;
2016-10-05 06:26:35 +02:00
Image : : Format image_format ;
2016-10-03 21:33:42 +02:00
2019-02-13 11:13:49 +01:00
bool hdr = rt - > flags [ RENDER_TARGET_HDR ] & & config . framebuffer_half_float_supported ;
2017-05-30 03:11:33 +02:00
//hdr = false;
2016-10-03 21:33:42 +02:00
2017-02-22 23:14:21 +01:00
if ( ! hdr | | rt - > flags [ RENDER_TARGET_NO_3D ] ) {
2016-10-03 21:33:42 +02:00
2017-07-22 19:07:38 +02:00
if ( rt - > flags [ RENDER_TARGET_NO_3D_EFFECTS ] & & ! rt - > flags [ RENDER_TARGET_TRANSPARENT ] ) {
//if this is not used, linear colorspace looks pretty bad
//this is the default mode used for mobile
color_internal_format = GL_RGB10_A2 ;
color_format = GL_RGBA ;
color_type = GL_UNSIGNED_INT_2_10_10_10_REV ;
2018-01-03 20:43:07 +01:00
image_format = Image : : FORMAT_RGBA8 ;
2017-07-22 19:07:38 +02:00
} else {
color_internal_format = GL_RGBA8 ;
color_format = GL_RGBA ;
color_type = GL_UNSIGNED_BYTE ;
image_format = Image : : FORMAT_RGBA8 ;
}
2016-10-30 01:48:09 +02:00
} else {
2017-03-05 16:44:50 +01:00
color_internal_format = GL_RGBA16F ;
color_format = GL_RGBA ;
color_type = GL_HALF_FLOAT ;
image_format = Image : : FORMAT_RGBAH ;
2016-10-03 21:33:42 +02:00
}
2016-10-30 01:48:09 +02:00
{
/* FRONT FBO */
2016-10-03 21:33:42 +02:00
2016-10-30 01:48:09 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2016-11-29 23:55:12 +01:00
glGenFramebuffers ( 1 , & rt - > fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , rt - > fbo ) ;
2016-10-30 01:48:09 +02:00
2016-11-29 23:55:12 +01:00
glGenTextures ( 1 , & rt - > depth ) ;
glBindTexture ( GL_TEXTURE_2D , rt - > depth ) ;
2019-02-13 11:58:52 +01:00
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_DEPTH_COMPONENT24 , rt - > width , rt - > height , 0 ,
GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , NULL ) ;
2016-11-29 23:55:12 +01:00
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 ) ;
2016-10-30 01:48:09 +02:00
2016-11-29 23:55:12 +01:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT ,
2017-03-05 16:44:50 +01:00
GL_TEXTURE_2D , rt - > depth , 0 ) ;
2016-10-30 01:48:09 +02:00
2016-11-29 23:55:12 +01:00
glGenTextures ( 1 , & rt - > color ) ;
glBindTexture ( GL_TEXTURE_2D , rt - > color ) ;
2016-10-30 01:48:09 +02:00
2017-03-05 16:44:50 +01:00
glTexImage2D ( GL_TEXTURE_2D , 0 , color_internal_format , rt - > width , rt - > height , 0 , color_format , color_type , NULL ) ;
2016-10-30 01:48:09 +02:00
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 ) ;
2016-11-29 23:55:12 +01:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , rt - > color , 0 ) ;
2016-10-03 21:33:42 +02:00
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
2017-01-07 09:33:11 +01:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
2016-10-03 21:33:42 +02:00
2017-02-22 23:14:21 +01:00
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
2017-03-05 16:44:50 +01:00
printf ( " framebuffer fail, status: %x \n " , status ) ;
2017-02-22 23:14:21 +01:00
}
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
Texture * tex = texture_owner . getornull ( rt - > texture ) ;
2017-03-05 16:44:50 +01:00
tex - > format = image_format ;
tex - > gl_format_cache = color_format ;
tex - > gl_type_cache = color_type ;
tex - > gl_internal_format_cache = color_internal_format ;
tex - > tex_id = rt - > color ;
tex - > width = rt - > width ;
tex - > alloc_width = rt - > width ;
tex - > height = rt - > height ;
tex - > alloc_height = rt - > height ;
2017-06-09 05:23:50 +02:00
tex - > active = true ;
2016-10-30 01:48:09 +02:00
2017-03-05 16:44:50 +01:00
texture_set_flags ( rt - > texture , tex - > flags ) ;
2016-10-30 01:48:09 +02:00
}
2016-10-05 06:26:35 +02:00
2016-10-30 01:48:09 +02:00
/* BACK FBO */
2016-10-03 21:33:42 +02:00
2017-07-22 19:07:38 +02:00
if ( ! rt - > flags [ RENDER_TARGET_NO_3D ] & & ( ! rt - > flags [ RENDER_TARGET_NO_3D_EFFECTS ] | | rt - > msaa ! = VS : : VIEWPORT_MSAA_DISABLED ) ) {
rt - > buffers . active = true ;
2016-10-03 21:33:42 +02:00
2019-11-10 09:30:20 +01:00
static const int msaa_value [ ] = { 0 , 2 , 4 , 8 , 16 , 4 , 16 } ; // MSAA_EXT_nX is a GLES2 temporary hack ignored in GLES3 for now...
2017-03-05 16:44:50 +01:00
int msaa = msaa_value [ rt - > msaa ] ;
2017-01-02 02:16:52 +01:00
2017-07-27 15:43:21 +02:00
int max_samples = 0 ;
glGetIntegerv ( GL_MAX_SAMPLES , & max_samples ) ;
if ( msaa > max_samples ) {
2019-11-07 09:44:15 +01:00
WARN_PRINT ( " MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos ( max_samples ) ) ;
2017-07-27 15:43:21 +02:00
msaa = max_samples ;
}
2016-10-03 21:33:42 +02:00
//regular fbo
2016-10-30 01:48:09 +02:00
glGenFramebuffers ( 1 , & rt - > buffers . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , rt - > buffers . fbo ) ;
2016-10-03 21:33:42 +02:00
2017-01-02 02:16:52 +01:00
glGenRenderbuffers ( 1 , & rt - > buffers . depth ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , rt - > buffers . depth ) ;
2017-03-05 16:44:50 +01:00
if ( msaa = = 0 )
2019-02-13 11:58:52 +01:00
glRenderbufferStorage ( GL_RENDERBUFFER , GL_DEPTH_COMPONENT24 , rt - > width , rt - > height ) ;
2017-01-02 02:16:52 +01:00
else
2019-02-13 11:58:52 +01:00
glRenderbufferStorageMultisample ( GL_RENDERBUFFER , msaa , GL_DEPTH_COMPONENT24 , rt - > width , rt - > height ) ;
2017-03-05 16:44:50 +01:00
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER , rt - > buffers . depth ) ;
2016-10-03 21:33:42 +02:00
2017-01-02 02:16:52 +01:00
glGenRenderbuffers ( 1 , & rt - > buffers . diffuse ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , rt - > buffers . diffuse ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( msaa = = 0 )
glRenderbufferStorage ( GL_RENDERBUFFER , color_internal_format , rt - > width , rt - > height ) ;
2017-01-02 02:16:52 +01:00
else
2017-03-05 16:44:50 +01:00
glRenderbufferStorageMultisample ( GL_RENDERBUFFER , msaa , color_internal_format , rt - > width , rt - > height ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER , rt - > buffers . diffuse ) ;
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
if ( ! rt - > flags [ RENDER_TARGET_NO_3D_EFFECTS ] ) {
2017-01-02 02:16:52 +01:00
2017-07-22 19:07:38 +02:00
rt - > buffers . effects_active = true ;
2017-06-09 05:23:50 +02:00
glGenRenderbuffers ( 1 , & rt - > buffers . specular ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , rt - > buffers . specular ) ;
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
if ( msaa = = 0 )
glRenderbufferStorage ( GL_RENDERBUFFER , color_internal_format , rt - > width , rt - > height ) ;
else
glRenderbufferStorageMultisample ( GL_RENDERBUFFER , msaa , color_internal_format , rt - > width , rt - > height ) ;
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER , rt - > buffers . specular ) ;
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
glGenRenderbuffers ( 1 , & rt - > buffers . normal_rough ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , rt - > buffers . normal_rough ) ;
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
if ( msaa = = 0 )
glRenderbufferStorage ( GL_RENDERBUFFER , GL_RGBA8 , rt - > width , rt - > height ) ;
else
glRenderbufferStorageMultisample ( GL_RENDERBUFFER , msaa , GL_RGBA8 , rt - > width , rt - > height ) ;
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER , rt - > buffers . normal_rough ) ;
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
glGenRenderbuffers ( 1 , & rt - > buffers . sss ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , rt - > buffers . sss ) ;
2016-10-03 21:33:42 +02:00
2017-06-09 05:23:50 +02:00
if ( msaa = = 0 )
glRenderbufferStorage ( GL_RENDERBUFFER , GL_R8 , rt - > width , rt - > height ) ;
else
glRenderbufferStorageMultisample ( GL_RENDERBUFFER , msaa , GL_R8 , rt - > width , rt - > height ) ;
2016-10-03 21:33:42 +02:00
2017-06-09 05:23:50 +02:00
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER , rt - > buffers . sss ) ;
2016-10-03 21:33:42 +02:00
2017-06-09 05:23:50 +02:00
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
2016-10-03 21:33:42 +02:00
2017-06-09 05:23:50 +02:00
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
printf ( " err status: %x \n " , status ) ;
_render_target_clear ( rt ) ;
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
}
2016-10-03 21:33:42 +02:00
2017-06-09 05:23:50 +02:00
glBindRenderbuffer ( GL_RENDERBUFFER , 0 ) ;
2016-10-03 21:33:42 +02:00
2017-06-09 05:23:50 +02:00
// effect resolver
2017-01-02 02:16:52 +01:00
2017-06-09 05:23:50 +02:00
glGenFramebuffers ( 1 , & rt - > buffers . effect_fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , rt - > buffers . effect_fbo ) ;
2016-10-03 21:33:42 +02:00
2017-06-09 05:23:50 +02:00
glGenTextures ( 1 , & rt - > buffers . effect ) ;
glBindTexture ( GL_TEXTURE_2D , rt - > buffers . effect ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , color_internal_format , rt - > width , rt - > height , 0 ,
color_format , color_type , NULL ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 ,
GL_TEXTURE_2D , rt - > buffers . effect , 0 ) ;
2017-01-02 02:16:52 +01:00
2017-07-19 16:04:19 +02:00
status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
2017-06-09 05:23:50 +02:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
2017-07-19 16:04:19 +02:00
printf ( " err status: %x \n " , status ) ;
2017-06-09 05:23:50 +02:00
_render_target_clear ( rt ) ;
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
}
///////////////// ssao
//AO strength textures
for ( int i = 0 ; i < 2 ; i + + ) {
glGenFramebuffers ( 1 , & rt - > effects . ssao . blur_fbo [ i ] ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , rt - > effects . ssao . blur_fbo [ i ] ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT ,
GL_TEXTURE_2D , rt - > depth , 0 ) ;
glGenTextures ( 1 , & rt - > effects . ssao . blur_red [ i ] ) ;
glBindTexture ( GL_TEXTURE_2D , rt - > effects . ssao . blur_red [ i ] ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_R8 , rt - > width , rt - > height , 0 , GL_RED , GL_UNSIGNED_BYTE , NULL ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , rt - > effects . ssao . blur_red [ i ] , 0 ) ;
status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_render_target_clear ( rt ) ;
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
}
}
//5 mip levels for depth texture, but base is read separately
glGenTextures ( 1 , & rt - > effects . ssao . linear_depth ) ;
glBindTexture ( GL_TEXTURE_2D , rt - > effects . ssao . linear_depth ) ;
int ssao_w = rt - > width / 2 ;
int ssao_h = rt - > height / 2 ;
for ( int i = 0 ; i < 4 ; i + + ) { //5, but 4 mips, base is read directly to save bw
glTexImage2D ( GL_TEXTURE_2D , i , GL_R16UI , ssao_w , ssao_h , 0 , GL_RED_INTEGER , GL_UNSIGNED_SHORT , NULL ) ;
ssao_w > > = 1 ;
ssao_h > > = 1 ;
}
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST_MIPMAP_NEAREST ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , 3 ) ;
for ( int i = 0 ; i < 4 ; i + + ) { //5, but 4 mips, base is read directly to save bw
GLuint fbo ;
glGenFramebuffers ( 1 , & fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , fbo ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , rt - > effects . ssao . linear_depth , i ) ;
rt - > effects . ssao . depth_mipmap_fbos . push_back ( fbo ) ;
}
//////Exposure
glGenFramebuffers ( 1 , & rt - > exposure . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , rt - > exposure . fbo ) ;
glGenTextures ( 1 , & rt - > exposure . color ) ;
glBindTexture ( GL_TEXTURE_2D , rt - > exposure . color ) ;
2019-02-13 11:13:49 +01:00
if ( config . framebuffer_float_supported ) {
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_R32F , 1 , 1 , 0 , GL_RED , GL_FLOAT , NULL ) ;
} else if ( config . framebuffer_half_float_supported ) {
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_R16F , 1 , 1 , 0 , GL_RED , GL_HALF_FLOAT , NULL ) ;
} else {
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB10_A2 , 1 , 1 , 0 , GL_RGBA , GL_UNSIGNED_INT_2_10_10_10_REV , NULL ) ;
}
2017-06-09 05:23:50 +02:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , rt - > exposure . color , 0 ) ;
status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_render_target_clear ( rt ) ;
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
}
2017-07-22 19:07:38 +02:00
} else {
rt - > buffers . effects_active = false ;
2016-10-03 21:33:42 +02:00
}
2017-07-22 19:07:38 +02:00
} else {
rt - > buffers . active = false ;
rt - > buffers . effects_active = true ;
2017-06-09 05:23:50 +02:00
}
2017-10-03 22:34:08 +02:00
if ( ! rt - > flags [ RENDER_TARGET_NO_SAMPLING ] & & rt - > width > = 2 & & rt - > height > = 2 ) {
2016-10-30 01:48:09 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
2016-11-29 23:55:12 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( rt - > effects . mip_maps [ i ] . sizes . size ( ) ) ;
int w = rt - > width ;
int h = rt - > height ;
2016-11-29 23:55:12 +01:00
2017-03-05 16:44:50 +01:00
if ( i > 0 ) {
w > > = 1 ;
h > > = 1 ;
2016-11-29 23:55:12 +01:00
}
glGenTextures ( 1 , & rt - > effects . mip_maps [ i ] . color ) ;
glBindTexture ( GL_TEXTURE_2D , rt - > effects . mip_maps [ i ] . color ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
int level = 0 ;
2017-07-26 05:39:41 +02:00
int fb_w = w ;
int fb_h = h ;
2016-11-29 23:55:12 +01:00
2017-03-05 16:44:50 +01:00
while ( true ) {
2016-11-29 23:55:12 +01:00
RenderTarget : : Effects : : MipMaps : : Size mm ;
2017-03-05 16:44:50 +01:00
mm . width = w ;
mm . height = h ;
2016-11-29 23:55:12 +01:00
rt - > effects . mip_maps [ i ] . sizes . push_back ( mm ) ;
2017-03-05 16:44:50 +01:00
w > > = 1 ;
h > > = 1 ;
2016-11-29 23:55:12 +01:00
2017-03-05 16:44:50 +01:00
if ( w < 2 | | h < 2 )
2016-12-08 13:48:38 +01:00
break ;
2016-11-29 23:55:12 +01:00
level + + ;
}
2016-10-03 21:33:42 +02:00
2017-07-26 05:39:41 +02:00
glTexStorage2DCustom ( GL_TEXTURE_2D , level + 1 , color_internal_format , fb_w , fb_h , color_format , color_type ) ;
2017-07-22 19:07:38 +02:00
2016-11-29 23:55:12 +01:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , level ) ;
2017-07-22 19:07:38 +02:00
glDisable ( GL_SCISSOR_TEST ) ;
glColorMask ( 1 , 1 , 1 , 1 ) ;
2018-10-06 22:20:41 +02:00
if ( ! rt - > buffers . active ) {
2017-07-26 05:39:41 +02:00
glDepthMask ( GL_TRUE ) ;
}
2016-11-29 23:55:12 +01:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < rt - > effects . mip_maps [ i ] . sizes . size ( ) ; j + + ) {
2016-11-29 23:55:12 +01:00
2018-07-25 03:11:03 +02:00
RenderTarget : : Effects : : MipMaps : : Size & mm = rt - > effects . mip_maps [ i ] . sizes . write [ j ] ;
2016-11-29 23:55:12 +01:00
glGenFramebuffers ( 1 , & mm . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , mm . fbo ) ;
2017-03-05 16:44:50 +01:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , rt - > effects . mip_maps [ i ] . color , j ) ;
2017-07-22 19:07:38 +02:00
bool used_depth = false ;
2017-08-22 02:36:30 +02:00
if ( j = = 0 & & i = = 0 ) { //use always
2017-07-22 19:07:38 +02:00
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_TEXTURE_2D , rt - > depth , 0 ) ;
used_depth = true ;
}
2016-11-29 23:55:12 +01:00
2017-06-09 05:23:50 +02:00
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
2016-11-29 23:55:12 +01:00
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_render_target_clear ( rt ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
2016-11-29 23:55:12 +01:00
}
2017-03-05 16:44:50 +01:00
float zero [ 4 ] = { 1 , 0 , 1 , 0 } ;
2017-07-22 19:07:38 +02:00
glViewport ( 0 , 0 , rt - > effects . mip_maps [ i ] . sizes [ j ] . width , rt - > effects . mip_maps [ i ] . sizes [ j ] . height ) ;
2017-03-05 16:44:50 +01:00
glClearBufferfv ( GL_COLOR , 0 , zero ) ;
2017-07-22 19:07:38 +02:00
if ( used_depth ) {
2019-02-13 11:58:52 +01:00
glClearDepth ( 1.0 ) ;
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2017-07-22 19:07:38 +02:00
}
2016-11-29 23:55:12 +01:00
}
2017-01-07 09:33:11 +01:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
2017-03-05 16:44:50 +01:00
rt - > effects . mip_maps [ i ] . levels = level ;
2016-11-29 23:55:12 +01:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2016-12-04 16:45:30 +01:00
}
2016-11-29 23:55:12 +01:00
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : render_target_create ( ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
RenderTarget * rt = memnew ( RenderTarget ) ;
2016-10-05 06:26:35 +02:00
2017-03-05 16:44:50 +01:00
Texture * t = memnew ( Texture ) ;
2016-10-05 06:26:35 +02:00
2018-12-29 13:16:04 +01:00
t - > type = VS : : TEXTURE_TYPE_2D ;
2017-03-05 16:44:50 +01:00
t - > flags = 0 ;
t - > width = 0 ;
t - > height = 0 ;
t - > alloc_height = 0 ;
t - > alloc_width = 0 ;
t - > format = Image : : FORMAT_R8 ;
t - > target = GL_TEXTURE_2D ;
t - > gl_format_cache = 0 ;
t - > gl_internal_format_cache = 0 ;
t - > gl_type_cache = 0 ;
t - > data_size = 0 ;
t - > compressed = false ;
t - > srgb = false ;
t - > total_data_size = 0 ;
t - > ignore_mipmaps = false ;
2017-06-09 05:23:50 +02:00
t - > mipmaps = 1 ;
2017-03-05 16:44:50 +01:00
t - > active = true ;
t - > tex_id = 0 ;
2017-06-09 05:23:50 +02:00
t - > render_target = rt ;
2016-10-05 06:26:35 +02:00
2017-03-05 16:44:50 +01:00
rt - > texture = texture_owner . make_rid ( t ) ;
2016-10-05 06:26:35 +02:00
2016-10-03 21:33:42 +02:00
return render_target_owner . make_rid ( rt ) ;
}
2019-05-08 20:25:34 +02:00
void RasterizerStorageGLES3 : : render_target_set_position ( RID p_render_target , int p_x , int p_y ) {
//only used in GLES2
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : render_target_set_size ( RID p_render_target , int p_width , int p_height ) {
2016-10-03 21:33:42 +02:00
RenderTarget * rt = render_target_owner . getornull ( p_render_target ) ;
ERR_FAIL_COND ( ! rt ) ;
2017-03-05 16:44:50 +01:00
if ( rt - > width = = p_width & & rt - > height = = p_height )
2016-10-03 21:33:42 +02:00
return ;
_render_target_clear ( rt ) ;
2017-03-05 16:44:50 +01:00
rt - > width = p_width ;
rt - > height = p_height ;
2016-10-03 21:33:42 +02:00
_render_target_allocate ( rt ) ;
}
2017-03-05 16:44:50 +01:00
RID RasterizerStorageGLES3 : : render_target_get_texture ( RID p_render_target ) const {
2016-10-03 21:33:42 +02:00
RenderTarget * rt = render_target_owner . getornull ( p_render_target ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! rt , RID ( ) ) ;
2016-10-03 21:33:42 +02:00
2019-03-30 14:03:49 +01:00
if ( rt - > external . fbo = = 0 ) {
return rt - > texture ;
} else {
return rt - > external . texture ;
}
}
void RasterizerStorageGLES3 : : render_target_set_external_texture ( RID p_render_target , unsigned int p_texture_id ) {
RenderTarget * rt = render_target_owner . getornull ( p_render_target ) ;
ERR_FAIL_COND ( ! rt ) ;
if ( p_texture_id = = 0 ) {
if ( rt - > external . fbo ! = 0 ) {
// free this
glDeleteFramebuffers ( 1 , & rt - > external . fbo ) ;
// clean up our texture
2019-06-10 17:38:51 +02:00
Texture * t = texture_owner . getornull ( rt - > external . texture ) ;
2019-03-30 14:03:49 +01:00
t - > alloc_height = 0 ;
t - > alloc_width = 0 ;
t - > width = 0 ;
t - > height = 0 ;
t - > active = false ;
texture_owner . free ( rt - > external . texture ) ;
memdelete ( t ) ;
rt - > external . fbo = 0 ;
}
} else {
Texture * t ;
if ( rt - > external . fbo = = 0 ) {
// create our fbo
glGenFramebuffers ( 1 , & rt - > external . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , rt - > external . fbo ) ;
// allocate a texture
t = memnew ( Texture ) ;
t - > type = VS : : TEXTURE_TYPE_2D ;
t - > flags = 0 ;
t - > width = 0 ;
t - > height = 0 ;
t - > alloc_height = 0 ;
t - > alloc_width = 0 ;
t - > format = Image : : FORMAT_RGBA8 ;
t - > target = GL_TEXTURE_2D ;
t - > gl_format_cache = 0 ;
t - > gl_internal_format_cache = 0 ;
t - > gl_type_cache = 0 ;
t - > data_size = 0 ;
t - > compressed = false ;
t - > srgb = false ;
t - > total_data_size = 0 ;
t - > ignore_mipmaps = false ;
t - > mipmaps = 1 ;
t - > active = true ;
t - > tex_id = 0 ;
t - > render_target = rt ;
rt - > external . texture = texture_owner . make_rid ( t ) ;
} else {
// bind our frame buffer
glBindFramebuffer ( GL_FRAMEBUFFER , rt - > external . fbo ) ;
// find our texture
2019-06-10 17:38:51 +02:00
t = texture_owner . getornull ( rt - > external . texture ) ;
2019-03-30 14:03:49 +01:00
}
// set our texture
t - > tex_id = p_texture_id ;
// size shouldn't be different
t - > width = rt - > width ;
t - > height = rt - > height ;
t - > alloc_height = rt - > width ;
t - > alloc_width = rt - > height ;
// is there a point to setting the internal formats? we don't know them..
// set our texture as the destination for our framebuffer
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , p_texture_id , 0 ) ;
// check status and unbind
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
printf ( " framebuffer fail, status: %x \n " , status ) ;
}
ERR_FAIL_COND ( status ! = GL_FRAMEBUFFER_COMPLETE ) ;
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : render_target_set_flag ( RID p_render_target , RenderTargetFlags p_flag , bool p_value ) {
2016-10-03 21:33:42 +02:00
RenderTarget * rt = render_target_owner . getornull ( p_render_target ) ;
ERR_FAIL_COND ( ! rt ) ;
2017-03-05 16:44:50 +01:00
rt - > flags [ p_flag ] = p_value ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
switch ( p_flag ) {
2017-06-09 05:23:50 +02:00
case RENDER_TARGET_HDR :
2016-10-03 21:33:42 +02:00
case RENDER_TARGET_NO_3D :
2017-06-09 05:23:50 +02:00
case RENDER_TARGET_NO_SAMPLING :
case RENDER_TARGET_NO_3D_EFFECTS : {
2016-10-03 21:33:42 +02:00
//must reset for these formats
_render_target_clear ( rt ) ;
_render_target_allocate ( rt ) ;
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2016-10-03 21:33:42 +02:00
}
}
2017-06-17 13:58:57 +02:00
bool RasterizerStorageGLES3 : : render_target_was_used ( RID p_render_target ) {
2016-10-03 21:33:42 +02:00
2017-06-17 13:58:57 +02:00
RenderTarget * rt = render_target_owner . getornull ( p_render_target ) ;
ERR_FAIL_COND_V ( ! rt , false ) ;
return rt - > used_in_frame ;
}
2019-06-24 21:13:06 +02:00
void RasterizerStorageGLES3 : : render_target_set_as_unused ( RID p_render_target ) {
2017-06-17 13:58:57 +02:00
RenderTarget * rt = render_target_owner . getornull ( p_render_target ) ;
ERR_FAIL_COND ( ! rt ) ;
2016-10-03 21:33:42 +02:00
2017-06-17 13:58:57 +02:00
rt - > used_in_frame = false ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : render_target_set_msaa ( RID p_render_target , VS : : ViewportMSAA p_msaa ) {
2017-01-02 02:16:52 +01:00
RenderTarget * rt = render_target_owner . getornull ( p_render_target ) ;
ERR_FAIL_COND ( ! rt ) ;
2017-03-05 16:44:50 +01:00
if ( rt - > msaa = = p_msaa )
2017-01-02 02:16:52 +01:00
return ;
_render_target_clear ( rt ) ;
2017-03-05 16:44:50 +01:00
rt - > msaa = p_msaa ;
2017-01-02 02:16:52 +01:00
_render_target_allocate ( rt ) ;
}
2016-10-03 21:33:42 +02:00
/* CANVAS SHADOW */
RID RasterizerStorageGLES3 : : canvas_light_shadow_buffer_create ( int p_width ) {
2017-03-05 16:44:50 +01:00
CanvasLightShadow * cls = memnew ( CanvasLightShadow ) ;
if ( p_width > config . max_texture_size )
p_width = config . max_texture_size ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
cls - > size = p_width ;
cls - > height = 16 ;
2016-10-03 21:33:42 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
glGenFramebuffers ( 1 , & cls - > fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , cls - > fbo ) ;
glGenRenderbuffers ( 1 , & cls - > depth ) ;
2017-03-05 16:44:50 +01:00
glBindRenderbuffer ( GL_RENDERBUFFER , cls - > depth ) ;
glRenderbufferStorage ( GL_RENDERBUFFER , GL_DEPTH_COMPONENT24 , cls - > size , cls - > height ) ;
2016-10-03 21:33:42 +02:00
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER , cls - > depth ) ;
2017-03-05 16:44:50 +01:00
glBindRenderbuffer ( GL_RENDERBUFFER , 0 ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glGenTextures ( 1 , & cls - > distance ) ;
2016-10-03 21:33:42 +02:00
glBindTexture ( GL_TEXTURE_2D , cls - > distance ) ;
if ( config . use_rgba_2d_shadows ) {
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA8 , cls - > size , cls - > height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , NULL ) ;
} else {
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_R32F , cls - > size , cls - > height , 0 , GL_RED , GL_FLOAT , NULL ) ;
}
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , cls - > distance , 0 ) ;
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
//printf("errnum: %x\n",status);
2017-01-07 09:33:11 +01:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
2016-10-03 21:33:42 +02:00
2018-08-26 03:19:02 +02:00
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
memdelete ( cls ) ;
ERR_FAIL_COND_V ( status ! = GL_FRAMEBUFFER_COMPLETE , RID ( ) ) ;
}
2016-10-03 21:33:42 +02:00
return canvas_light_shadow_owner . make_rid ( cls ) ;
}
/* LIGHT SHADOW MAPPING */
RID RasterizerStorageGLES3 : : canvas_light_occluder_create ( ) {
2017-03-05 16:44:50 +01:00
CanvasOccluder * co = memnew ( CanvasOccluder ) ;
co - > index_id = 0 ;
co - > vertex_id = 0 ;
co - > len = 0 ;
2017-06-13 06:23:04 +02:00
glGenVertexArrays ( 1 , & co - > array_id ) ;
2016-10-03 21:33:42 +02:00
return canvas_occluder_owner . make_rid ( co ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerStorageGLES3 : : canvas_light_occluder_set_polylines ( RID p_occluder , const PoolVector < Vector2 > & p_lines ) {
2016-10-03 21:33:42 +02:00
2019-06-10 17:38:51 +02:00
CanvasOccluder * co = canvas_occluder_owner . getornull ( p_occluder ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! co ) ;
2017-03-05 16:44:50 +01:00
co - > lines = p_lines ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( p_lines . size ( ) ! = co - > len ) {
2016-10-03 21:33:42 +02:00
if ( co - > index_id )
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & co - > index_id ) ;
2016-10-03 21:33:42 +02:00
if ( co - > vertex_id )
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & co - > vertex_id ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
co - > index_id = 0 ;
co - > vertex_id = 0 ;
co - > len = 0 ;
2016-10-03 21:33:42 +02:00
}
if ( p_lines . size ( ) ) {
2017-01-07 22:25:37 +01:00
PoolVector < float > geometry ;
PoolVector < uint16_t > indices ;
2016-10-03 21:33:42 +02:00
int lc = p_lines . size ( ) ;
2017-03-05 16:44:50 +01:00
geometry . resize ( lc * 6 ) ;
indices . resize ( lc * 3 ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
PoolVector < float > : : Write vw = geometry . write ( ) ;
PoolVector < uint16_t > : : Write iw = indices . write ( ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
PoolVector < Vector2 > : : Read lr = p_lines . read ( ) ;
2016-10-03 21:33:42 +02:00
const int POLY_HEIGHT = 16384 ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < lc / 2 ; i + + ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
vw [ i * 12 + 0 ] = lr [ i * 2 + 0 ] . x ;
vw [ i * 12 + 1 ] = lr [ i * 2 + 0 ] . y ;
vw [ i * 12 + 2 ] = POLY_HEIGHT ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
vw [ i * 12 + 3 ] = lr [ i * 2 + 1 ] . x ;
vw [ i * 12 + 4 ] = lr [ i * 2 + 1 ] . y ;
vw [ i * 12 + 5 ] = POLY_HEIGHT ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
vw [ i * 12 + 6 ] = lr [ i * 2 + 1 ] . x ;
vw [ i * 12 + 7 ] = lr [ i * 2 + 1 ] . y ;
vw [ i * 12 + 8 ] = - POLY_HEIGHT ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
vw [ i * 12 + 9 ] = lr [ i * 2 + 0 ] . x ;
vw [ i * 12 + 10 ] = lr [ i * 2 + 0 ] . y ;
vw [ i * 12 + 11 ] = - POLY_HEIGHT ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
iw [ i * 6 + 0 ] = i * 4 + 0 ;
iw [ i * 6 + 1 ] = i * 4 + 1 ;
iw [ i * 6 + 2 ] = i * 4 + 2 ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
iw [ i * 6 + 3 ] = i * 4 + 2 ;
iw [ i * 6 + 4 ] = i * 4 + 3 ;
iw [ i * 6 + 5 ] = i * 4 + 0 ;
2016-10-03 21:33:42 +02:00
}
//if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
if ( ! co - > vertex_id ) {
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & co - > vertex_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , co - > vertex_id ) ;
2017-10-03 22:34:08 +02:00
glBufferData ( GL_ARRAY_BUFFER , lc * 6 * sizeof ( real_t ) , vw . ptr ( ) , GL_STATIC_DRAW ) ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , co - > vertex_id ) ;
glBufferSubData ( GL_ARRAY_BUFFER , 0 , lc * 6 * sizeof ( real_t ) , vw . ptr ( ) ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-03 21:33:42 +02:00
if ( ! co - > index_id ) {
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & co - > index_id ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , co - > index_id ) ;
2017-06-13 06:23:04 +02:00
glBufferData ( GL_ELEMENT_ARRAY_BUFFER , lc * 3 * sizeof ( uint16_t ) , iw . ptr ( ) , GL_DYNAMIC_DRAW ) ;
2016-10-03 21:33:42 +02:00
} else {
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , co - > index_id ) ;
glBufferSubData ( GL_ELEMENT_ARRAY_BUFFER , 0 , lc * 3 * sizeof ( uint16_t ) , iw . ptr ( ) ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
co - > len = lc ;
2017-06-13 06:23:04 +02:00
glBindVertexArray ( co - > array_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , co - > vertex_id ) ;
glEnableVertexAttribArray ( VS : : ARRAY_VERTEX ) ;
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 3 , GL_FLOAT , false , 0 , 0 ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , co - > index_id ) ;
glBindVertexArray ( 0 ) ;
2016-10-03 21:33:42 +02:00
}
}
2016-10-19 16:14:41 +02:00
VS : : InstanceType RasterizerStorageGLES3 : : get_base_type ( RID p_rid ) const {
if ( mesh_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_MESH ;
}
2016-12-20 04:21:07 +01:00
2016-11-22 05:26:56 +01:00
if ( multimesh_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_MULTIMESH ;
}
2016-12-20 04:21:07 +01:00
2016-11-23 11:04:55 +01:00
if ( immediate_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_IMMEDIATE ;
}
2016-12-20 04:21:07 +01:00
2017-04-07 04:36:37 +02:00
if ( particles_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_PARTICLES ;
}
2016-10-27 16:50:26 +02:00
if ( light_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_LIGHT ;
}
2016-12-20 04:21:07 +01:00
2016-11-19 17:23:37 +01:00
if ( reflection_probe_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_REFLECTION_PROBE ;
}
2016-10-19 16:14:41 +02:00
2016-12-20 04:21:07 +01:00
if ( gi_probe_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_GI_PROBE ;
}
2017-12-14 12:59:46 +01:00
if ( lightmap_capture_data_owner . owns ( p_rid ) ) {
return VS : : INSTANCE_LIGHTMAP_CAPTURE ;
}
2016-10-19 16:14:41 +02:00
return VS : : INSTANCE_NONE ;
}
2017-03-05 16:44:50 +01:00
bool RasterizerStorageGLES3 : : free ( RID p_rid ) {
2016-10-03 21:33:42 +02:00
if ( render_target_owner . owns ( p_rid ) ) {
RenderTarget * rt = render_target_owner . getornull ( p_rid ) ;
_render_target_clear ( rt ) ;
2019-06-10 17:38:51 +02:00
Texture * t = texture_owner . getornull ( rt - > texture ) ;
2016-10-05 06:26:35 +02:00
texture_owner . free ( rt - > texture ) ;
memdelete ( t ) ;
2016-10-03 21:33:42 +02:00
render_target_owner . free ( p_rid ) ;
memdelete ( rt ) ;
} else if ( texture_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
Texture * texture = texture_owner . getornull ( p_rid ) ;
2017-03-24 21:45:31 +01:00
ERR_FAIL_COND_V ( texture - > render_target , true ) ; //can't free the render target texture, dude
2017-03-05 16:44:50 +01:00
info . texture_mem - = texture - > total_data_size ;
2016-10-03 21:33:42 +02:00
texture_owner . free ( p_rid ) ;
memdelete ( texture ) ;
2018-06-26 13:59:26 +02:00
2017-05-25 18:53:59 +02:00
} else if ( sky_owner . owns ( p_rid ) ) {
// delete the sky
2019-06-10 17:38:51 +02:00
Sky * sky = sky_owner . getornull ( p_rid ) ;
2017-05-25 18:53:59 +02:00
sky_set_texture ( p_rid , RID ( ) , 256 ) ;
sky_owner . free ( p_rid ) ;
memdelete ( sky ) ;
2016-10-10 23:31:01 +02:00
} else if ( shader_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
Shader * shader = shader_owner . getornull ( p_rid ) ;
2016-10-10 23:31:01 +02:00
2019-01-26 14:39:03 +01:00
if ( shader - > shader & & shader - > custom_code_id )
2016-10-10 23:31:01 +02:00
shader - > shader - > free_custom_shader ( shader - > custom_code_id ) ;
if ( shader - > dirty_list . in_list ( ) )
_shader_dirty_list . remove ( & shader - > dirty_list ) ;
while ( shader - > materials . first ( ) ) {
Material * mat = shader - > materials . first ( ) - > self ( ) ;
2017-03-05 16:44:50 +01:00
mat - > shader = NULL ;
2016-10-10 23:31:01 +02:00
_material_make_dirty ( mat ) ;
2017-03-05 16:44:50 +01:00
shader - > materials . remove ( shader - > materials . first ( ) ) ;
2016-10-10 23:31:01 +02:00
}
//material_shader.free_custom_shader(shader->custom_code_id);
shader_owner . free ( p_rid ) ;
memdelete ( shader ) ;
} else if ( material_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
Material * material = material_owner . getornull ( p_rid ) ;
2016-10-10 23:31:01 +02:00
if ( material - > shader ) {
2017-03-05 16:44:50 +01:00
material - > shader - > materials . remove ( & material - > list ) ;
2016-10-10 23:31:01 +02:00
}
if ( material - > ubo_id ) {
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & material - > ubo_id ) ;
2016-10-10 23:31:01 +02:00
}
2016-11-25 00:46:55 +01:00
//remove from owners
2017-03-05 16:44:50 +01:00
for ( Map < Geometry * , int > : : Element * E = material - > geometry_owners . front ( ) ; E ; E = E - > next ( ) ) {
2016-11-25 00:46:55 +01:00
Geometry * g = E - > key ( ) ;
2017-03-05 16:44:50 +01:00
g - > material = RID ( ) ;
2016-11-25 00:46:55 +01:00
}
2017-03-05 16:44:50 +01:00
for ( Map < RasterizerScene : : InstanceBase * , int > : : Element * E = material - > instance_owners . front ( ) ; E ; E = E - > next ( ) ) {
RasterizerScene : : InstanceBase * ins = E - > key ( ) ;
if ( ins - > material_override = = p_rid ) {
ins - > material_override = RID ( ) ;
2016-11-25 00:46:55 +01:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < ins - > materials . size ( ) ; i + + ) {
if ( ins - > materials [ i ] = = p_rid ) {
2018-07-25 03:11:03 +02:00
ins - > materials . write [ i ] = RID ( ) ;
2016-11-25 00:46:55 +01:00
}
}
}
2016-10-10 23:31:01 +02:00
material_owner . free ( p_rid ) ;
memdelete ( material ) ;
2016-11-21 23:03:39 +01:00
} else if ( skeleton_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
Skeleton * skeleton = skeleton_owner . getornull ( p_rid ) ;
2016-11-21 23:03:39 +01:00
if ( skeleton - > update_list . in_list ( ) ) {
skeleton_update_list . remove ( & skeleton - > update_list ) ;
}
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
for ( Set < RasterizerScene : : InstanceBase * > : : Element * E = skeleton - > instances . front ( ) ; E ; E = E - > next ( ) ) {
E - > get ( ) - > skeleton = RID ( ) ;
2016-11-25 00:46:55 +01:00
}
2017-03-05 16:44:50 +01:00
skeleton_allocate ( p_rid , 0 , false ) ;
2017-03-12 17:08:56 +01:00
2017-03-24 00:14:12 +01:00
glDeleteTextures ( 1 , & skeleton - > texture ) ;
2016-11-21 23:03:39 +01:00
skeleton_owner . free ( p_rid ) ;
memdelete ( skeleton ) ;
2016-10-19 16:14:41 +02:00
} else if ( mesh_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
Mesh * mesh = mesh_owner . getornull ( p_rid ) ;
2016-11-25 03:30:54 +01:00
mesh - > instance_remove_deps ( ) ;
2016-10-19 16:14:41 +02:00
mesh_clear ( p_rid ) ;
2017-03-05 16:44:50 +01:00
while ( mesh - > multimeshes . first ( ) ) {
2017-02-16 12:55:11 +01:00
MultiMesh * multimesh = mesh - > multimeshes . first ( ) - > self ( ) ;
2017-03-05 16:44:50 +01:00
multimesh - > mesh = RID ( ) ;
multimesh - > dirty_aabb = true ;
2017-02-16 12:55:11 +01:00
mesh - > multimeshes . remove ( mesh - > multimeshes . first ( ) ) ;
if ( ! multimesh - > update_list . in_list ( ) ) {
multimesh_update_list . add ( & multimesh - > update_list ) ;
}
}
2016-10-19 16:14:41 +02:00
mesh_owner . free ( p_rid ) ;
memdelete ( mesh ) ;
2016-10-10 23:31:01 +02:00
2016-11-22 05:26:56 +01:00
} else if ( multimesh_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
MultiMesh * multimesh = multimesh_owner . getornull ( p_rid ) ;
2016-11-25 03:30:54 +01:00
multimesh - > instance_remove_deps ( ) ;
2016-11-22 05:26:56 +01:00
2017-02-16 12:55:11 +01:00
if ( multimesh - > mesh . is_valid ( ) ) {
Mesh * mesh = mesh_owner . getornull ( multimesh - > mesh ) ;
if ( mesh ) {
mesh - > multimeshes . remove ( & multimesh - > mesh_list ) ;
}
}
2017-03-05 16:44:50 +01:00
multimesh_allocate ( p_rid , 0 , VS : : MULTIMESH_TRANSFORM_2D , VS : : MULTIMESH_COLOR_NONE ) ; //frees multimesh
2016-11-22 05:26:56 +01:00
update_dirty_multimeshes ( ) ;
multimesh_owner . free ( p_rid ) ;
memdelete ( multimesh ) ;
2016-11-23 11:04:55 +01:00
} else if ( immediate_owner . owns ( p_rid ) ) {
2019-06-10 17:38:51 +02:00
Immediate * immediate = immediate_owner . getornull ( p_rid ) ;
2016-11-25 03:30:54 +01:00
immediate - > instance_remove_deps ( ) ;
2016-11-22 05:26:56 +01:00
2016-11-23 11:04:55 +01:00
immediate_owner . free ( p_rid ) ;
memdelete ( immediate ) ;
2016-10-27 16:50:26 +02:00
} else if ( light_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
Light * light = light_owner . getornull ( p_rid ) ;
2016-11-25 03:30:54 +01:00
light - > instance_remove_deps ( ) ;
2016-10-27 16:50:26 +02:00
light_owner . free ( p_rid ) ;
memdelete ( light ) ;
2016-11-25 03:30:54 +01:00
} else if ( reflection_probe_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
ReflectionProbe * reflection_probe = reflection_probe_owner . getornull ( p_rid ) ;
2016-11-25 03:30:54 +01:00
reflection_probe - > instance_remove_deps ( ) ;
reflection_probe_owner . free ( p_rid ) ;
memdelete ( reflection_probe ) ;
2016-12-20 04:21:07 +01:00
} else if ( gi_probe_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
GIProbe * gi_probe = gi_probe_owner . getornull ( p_rid ) ;
2018-01-06 23:05:34 +01:00
gi_probe - > instance_remove_deps ( ) ;
2016-12-20 04:21:07 +01:00
gi_probe_owner . free ( p_rid ) ;
memdelete ( gi_probe ) ;
} else if ( gi_probe_data_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
GIProbeData * gi_probe_data = gi_probe_data_owner . getornull ( p_rid ) ;
2016-12-20 04:21:07 +01:00
2017-03-05 16:44:50 +01:00
glDeleteTextures ( 1 , & gi_probe_data - > tex_id ) ;
2018-09-29 01:32:40 +02:00
gi_probe_data_owner . free ( p_rid ) ;
2016-12-20 04:21:07 +01:00
memdelete ( gi_probe_data ) ;
2017-12-14 12:59:46 +01:00
} else if ( lightmap_capture_data_owner . owns ( p_rid ) ) {
// delete the texture
2019-06-10 17:38:51 +02:00
LightmapCapture * lightmap_capture = lightmap_capture_data_owner . getornull ( p_rid ) ;
2018-01-06 23:05:34 +01:00
lightmap_capture - > instance_remove_deps ( ) ;
2017-12-14 12:59:46 +01:00
2018-09-29 01:32:40 +02:00
lightmap_capture_data_owner . free ( p_rid ) ;
2017-12-14 12:59:46 +01:00
memdelete ( lightmap_capture ) ;
2016-12-20 04:21:07 +01:00
2016-10-03 21:33:42 +02:00
} else if ( canvas_occluder_owner . owns ( p_rid ) ) {
2019-06-10 17:38:51 +02:00
CanvasOccluder * co = canvas_occluder_owner . getornull ( p_rid ) ;
2016-10-03 21:33:42 +02:00
if ( co - > index_id )
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & co - > index_id ) ;
2016-10-03 21:33:42 +02:00
if ( co - > vertex_id )
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & co - > vertex_id ) ;
2016-10-03 21:33:42 +02:00
2017-06-13 06:23:04 +02:00
glDeleteVertexArrays ( 1 , & co - > array_id ) ;
2016-10-03 21:33:42 +02:00
canvas_occluder_owner . free ( p_rid ) ;
memdelete ( co ) ;
} else if ( canvas_light_shadow_owner . owns ( p_rid ) ) {
2019-06-10 17:38:51 +02:00
CanvasLightShadow * cls = canvas_light_shadow_owner . getornull ( p_rid ) ;
2017-03-05 16:44:50 +01:00
glDeleteFramebuffers ( 1 , & cls - > fbo ) ;
glDeleteRenderbuffers ( 1 , & cls - > depth ) ;
glDeleteTextures ( 1 , & cls - > distance ) ;
2016-10-03 21:33:42 +02:00
canvas_light_shadow_owner . free ( p_rid ) ;
memdelete ( cls ) ;
2017-12-29 18:02:40 +01:00
} else if ( particles_owner . owns ( p_rid ) ) {
2019-06-10 17:38:51 +02:00
Particles * particles = particles_owner . getornull ( p_rid ) ;
2018-01-12 13:11:27 +01:00
particles - > instance_remove_deps ( ) ;
2017-12-29 18:02:40 +01:00
particles_owner . free ( p_rid ) ;
memdelete ( particles ) ;
2016-10-03 21:33:42 +02:00
} else {
return false ;
}
return true ;
}
2017-03-05 16:44:50 +01:00
bool RasterizerStorageGLES3 : : has_os_feature ( const String & p_feature ) const {
2017-02-06 04:38:39 +01:00
2018-08-22 04:56:04 +02:00
if ( p_feature = = " bptc " )
return config . bptc_supported ;
2017-03-05 16:44:50 +01:00
if ( p_feature = = " s3tc " )
2017-02-06 04:38:39 +01:00
return config . s3tc_supported ;
2017-03-05 16:44:50 +01:00
if ( p_feature = = " etc " )
2017-02-06 04:38:39 +01:00
return config . etc_supported ;
2017-03-05 16:44:50 +01:00
if ( p_feature = = " etc2 " )
2017-02-06 04:38:39 +01:00
return config . etc2_supported ;
2017-03-05 16:44:50 +01:00
if ( p_feature = = " pvrtc " )
2017-02-06 04:38:39 +01:00
return config . pvrtc_supported ;
return false ;
}
2016-10-03 21:33:42 +02:00
////////////////////////////////////////////
2017-06-11 20:52:03 +02:00
void RasterizerStorageGLES3 : : set_debug_generate_wireframes ( bool p_generate ) {
config . generate_wireframes = p_generate ;
}
2017-06-11 23:13:04 +02:00
void RasterizerStorageGLES3 : : render_info_begin_capture ( ) {
info . snap = info . render ;
}
void RasterizerStorageGLES3 : : render_info_end_capture ( ) {
info . snap . object_count = info . render . object_count - info . snap . object_count ;
info . snap . draw_call_count = info . render . draw_call_count - info . snap . draw_call_count ;
info . snap . material_switch_count = info . render . material_switch_count - info . snap . material_switch_count ;
info . snap . surface_switch_count = info . render . surface_switch_count - info . snap . surface_switch_count ;
info . snap . shader_rebind_count = info . render . shader_rebind_count - info . snap . shader_rebind_count ;
info . snap . vertices_count = info . render . vertices_count - info . snap . vertices_count ;
}
int RasterizerStorageGLES3 : : get_captured_render_info ( VS : : RenderInfo p_info ) {
switch ( p_info ) {
case VS : : INFO_OBJECTS_IN_FRAME : {
return info . snap . object_count ;
} break ;
case VS : : INFO_VERTICES_IN_FRAME : {
return info . snap . vertices_count ;
} break ;
case VS : : INFO_MATERIAL_CHANGES_IN_FRAME : {
return info . snap . material_switch_count ;
} break ;
case VS : : INFO_SHADER_CHANGES_IN_FRAME : {
return info . snap . shader_rebind_count ;
} break ;
case VS : : INFO_SURFACE_CHANGES_IN_FRAME : {
return info . snap . surface_switch_count ;
} break ;
case VS : : INFO_DRAW_CALLS_IN_FRAME : {
return info . snap . draw_call_count ;
} break ;
default : {
return get_render_info ( p_info ) ;
}
}
}
int RasterizerStorageGLES3 : : get_render_info ( VS : : RenderInfo p_info ) {
switch ( p_info ) {
2017-09-07 21:48:50 +02:00
case VS : : INFO_OBJECTS_IN_FRAME :
2017-06-11 23:13:04 +02:00
return info . render_final . object_count ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_VERTICES_IN_FRAME :
2017-06-11 23:13:04 +02:00
return info . render_final . vertices_count ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_MATERIAL_CHANGES_IN_FRAME :
2017-06-11 23:13:04 +02:00
return info . render_final . material_switch_count ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_SHADER_CHANGES_IN_FRAME :
2017-06-11 23:13:04 +02:00
return info . render_final . shader_rebind_count ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_SURFACE_CHANGES_IN_FRAME :
2017-06-11 23:13:04 +02:00
return info . render_final . surface_switch_count ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_DRAW_CALLS_IN_FRAME :
2017-06-11 23:13:04 +02:00
return info . render_final . draw_call_count ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_USAGE_VIDEO_MEM_TOTAL :
2017-06-11 23:13:04 +02:00
return 0 ; //no idea
2017-09-07 21:48:50 +02:00
case VS : : INFO_VIDEO_MEM_USED :
2017-06-11 23:13:04 +02:00
return info . vertex_mem + info . texture_mem ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_TEXTURE_MEM_USED :
2017-06-11 23:13:04 +02:00
return info . texture_mem ;
2017-09-07 21:48:50 +02:00
case VS : : INFO_VERTEX_MEM_USED :
2017-06-11 23:13:04 +02:00
return info . vertex_mem ;
2017-09-07 21:48:50 +02:00
default :
return 0 ; //no idea either
2017-06-11 23:13:04 +02:00
}
}
2019-09-13 20:08:05 +02:00
String RasterizerStorageGLES3 : : get_video_adapter_name ( ) const {
return ( const char * ) glGetString ( GL_RENDERER ) ;
}
String RasterizerStorageGLES3 : : get_video_adapter_vendor ( ) const {
return ( const char * ) glGetString ( GL_VENDOR ) ;
}
2016-10-03 21:33:42 +02:00
void RasterizerStorageGLES3 : : initialize ( ) {
2017-03-05 16:44:50 +01:00
RasterizerStorageGLES3 : : system_fbo = 0 ;
2016-10-03 21:33:42 +02:00
//// extensions config
///
{
2016-11-23 00:51:56 +01:00
2017-03-05 16:44:50 +01:00
int max_extensions = 0 ;
glGetIntegerv ( GL_NUM_EXTENSIONS , & max_extensions ) ;
for ( int i = 0 ; i < max_extensions ; i + + ) {
const GLubyte * s = glGetStringi ( GL_EXTENSIONS , i ) ;
2016-11-23 00:51:56 +01:00
if ( ! s )
break ;
2017-03-05 16:44:50 +01:00
config . extensions . insert ( ( const char * ) s ) ;
2016-10-03 21:33:42 +02:00
}
}
2017-03-05 16:44:50 +01:00
config . shrink_textures_x2 = false ;
2017-07-19 22:00:46 +02:00
config . use_fast_texture_filter = int ( ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/filters/use_nearest_mipmap_filter " ) ) ;
2017-07-18 02:05:38 +02:00
config . use_anisotropic_filter = config . extensions . has ( " rendering/quality/filters/anisotropic_filter_level " ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
config . etc_supported = config . extensions . has ( " GL_OES_compressed_ETC1_RGB8_texture " ) ;
config . latc_supported = config . extensions . has ( " GL_EXT_texture_compression_latc " ) ;
config . bptc_supported = config . extensions . has ( " GL_ARB_texture_compression_bptc " ) ;
2016-11-23 00:51:56 +01:00
# ifdef GLES_OVER_GL
2017-03-05 16:44:50 +01:00
config . etc2_supported = false ;
2017-08-07 13:59:14 +02:00
config . s3tc_supported = true ;
2017-08-07 11:23:17 +02:00
config . rgtc_supported = true ; //RGTC - core since OpenGL version 3.0
2018-12-24 07:47:41 +01:00
config . texture_float_linear_supported = true ;
2019-02-13 11:13:49 +01:00
config . framebuffer_float_supported = true ;
config . framebuffer_half_float_supported = true ;
2016-10-03 21:33:42 +02:00
# else
2017-03-05 16:44:50 +01:00
config . etc2_supported = true ;
2017-08-07 13:59:14 +02:00
config . s3tc_supported = config . extensions . has ( " GL_EXT_texture_compression_dxt1 " ) | | config . extensions . has ( " GL_EXT_texture_compression_s3tc " ) | | config . extensions . has ( " WEBGL_compressed_texture_s3tc " ) ;
2018-11-27 18:15:41 +01:00
config . rgtc_supported = config . extensions . has ( " GL_EXT_texture_compression_rgtc " ) | | config . extensions . has ( " GL_ARB_texture_compression_rgtc " ) | | config . extensions . has ( " EXT_texture_compression_rgtc " ) ;
2018-12-24 07:47:41 +01:00
config . texture_float_linear_supported = config . extensions . has ( " GL_OES_texture_float_linear " ) ;
2019-02-13 11:13:49 +01:00
config . framebuffer_float_supported = config . extensions . has ( " GL_EXT_color_buffer_float " ) ;
config . framebuffer_half_float_supported = config . extensions . has ( " GL_EXT_color_buffer_half_float " ) | | config . framebuffer_float_supported ;
2016-10-03 21:33:42 +02:00
# endif
2017-05-30 03:11:33 +02:00
2017-03-05 16:44:50 +01:00
config . pvrtc_supported = config . extensions . has ( " GL_IMG_texture_compression_pvrtc " ) ;
config . srgb_decode_supported = config . extensions . has ( " GL_EXT_texture_sRGB_decode " ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
config . anisotropic_level = 1.0 ;
config . use_anisotropic_filter = config . extensions . has ( " GL_EXT_texture_filter_anisotropic " ) ;
2016-10-03 21:33:42 +02:00
if ( config . use_anisotropic_filter ) {
2017-03-05 16:44:50 +01:00
glGetFloatv ( _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT , & config . anisotropic_level ) ;
2017-07-26 15:03:13 +02:00
config . anisotropic_level = MIN ( int ( ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/filters/anisotropic_filter_level " ) ) , config . anisotropic_level ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
frame . clear_request = false ;
2016-10-03 21:33:42 +02:00
shaders . copy . init ( ) ;
{
//default textures
glGenTextures ( 1 , & resources . white_tex ) ;
2017-03-05 16:44:50 +01:00
unsigned char whitetexdata [ 8 * 8 * 3 ] ;
for ( int i = 0 ; i < 8 * 8 * 3 ; i + + ) {
whitetexdata [ i ] = 255 ;
2016-10-03 21:33:42 +02:00
}
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , resources . white_tex ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB , 8 , 8 , 0 , GL_RGB , GL_UNSIGNED_BYTE , whitetexdata ) ;
2016-10-03 21:33:42 +02:00
glGenerateMipmap ( GL_TEXTURE_2D ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2016-10-03 21:33:42 +02:00
glGenTextures ( 1 , & resources . black_tex ) ;
2017-03-05 16:44:50 +01:00
unsigned char blacktexdata [ 8 * 8 * 3 ] ;
for ( int i = 0 ; i < 8 * 8 * 3 ; i + + ) {
blacktexdata [ i ] = 0 ;
2016-10-03 21:33:42 +02:00
}
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , resources . black_tex ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB , 8 , 8 , 0 , GL_RGB , GL_UNSIGNED_BYTE , blacktexdata ) ;
2016-10-03 21:33:42 +02:00
glGenerateMipmap ( GL_TEXTURE_2D ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2016-10-03 21:33:42 +02:00
glGenTextures ( 1 , & resources . normal_tex ) ;
2017-03-05 16:44:50 +01:00
unsigned char normaltexdata [ 8 * 8 * 3 ] ;
for ( int i = 0 ; i < 8 * 8 * 3 ; i + = 3 ) {
normaltexdata [ i + 0 ] = 128 ;
normaltexdata [ i + 1 ] = 128 ;
normaltexdata [ i + 2 ] = 255 ;
2016-10-03 21:33:42 +02:00
}
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , resources . normal_tex ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB , 8 , 8 , 0 , GL_RGB , GL_UNSIGNED_BYTE , normaltexdata ) ;
2016-10-03 21:33:42 +02:00
glGenerateMipmap ( GL_TEXTURE_2D ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2016-11-21 02:49:53 +01:00
glGenTextures ( 1 , & resources . aniso_tex ) ;
2017-03-05 16:44:50 +01:00
unsigned char anisotexdata [ 8 * 8 * 3 ] ;
for ( int i = 0 ; i < 8 * 8 * 3 ; i + = 3 ) {
anisotexdata [ i + 0 ] = 255 ;
anisotexdata [ i + 1 ] = 128 ;
anisotexdata [ i + 2 ] = 0 ;
2016-11-21 02:49:53 +01:00
}
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , resources . aniso_tex ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB , 8 , 8 , 0 , GL_RGB , GL_UNSIGNED_BYTE , anisotexdata ) ;
2016-11-21 02:49:53 +01:00
glGenerateMipmap ( GL_TEXTURE_2D ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2018-06-26 13:59:26 +02:00
glGenTextures ( 1 , & resources . white_tex_3d ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_3D , resources . white_tex_3d ) ;
glTexImage3D ( GL_TEXTURE_3D , 0 , GL_RGB , 2 , 2 , 2 , 0 , GL_RGB , GL_UNSIGNED_BYTE , whitetexdata ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( GL_TEXTURE_3D , GL_TEXTURE_MAX_LEVEL , 0 ) ;
2018-12-23 15:25:46 +01:00
glGenTextures ( 1 , & resources . white_tex_array ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D_ARRAY , resources . white_tex_array ) ;
glTexImage3D ( GL_TEXTURE_2D_ARRAY , 0 , GL_RGB , 8 , 8 , 1 , 0 , GL_RGB , GL_UNSIGNED_BYTE , NULL ) ;
glTexSubImage3D ( GL_TEXTURE_2D_ARRAY , 0 , 0 , 0 , 0 , 8 , 8 , 1 , GL_RGB , GL_UNSIGNED_BYTE , whitetexdata ) ;
glGenerateMipmap ( GL_TEXTURE_2D_ARRAY ) ;
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
glGetIntegerv ( GL_MAX_TEXTURE_IMAGE_UNITS , & config . max_texture_image_units ) ;
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & config . max_texture_size ) ;
2016-10-03 21:33:42 +02:00
2019-07-27 17:05:26 +02:00
config . use_rgba_2d_shadows = ! config . framebuffer_float_supported ;
2016-10-21 12:27:13 +02:00
//generic quadie for copying
{
//quad buffers
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & resources . quadie ) ;
glBindBuffer ( GL_ARRAY_BUFFER , resources . quadie ) ;
2016-10-21 12:27:13 +02:00
{
2017-03-05 16:44:50 +01:00
const float qv [ 16 ] = {
2017-11-17 03:09:00 +01:00
- 1 ,
- 1 ,
0 ,
0 ,
- 1 ,
1 ,
0 ,
1 ,
1 ,
1 ,
1 ,
1 ,
1 ,
- 1 ,
1 ,
0 ,
2016-10-21 12:27:13 +02:00
} ;
2017-03-05 16:44:50 +01:00
glBufferData ( GL_ARRAY_BUFFER , sizeof ( float ) * 16 , qv , GL_STATIC_DRAW ) ;
2016-10-21 12:27:13 +02:00
}
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-21 12:27:13 +02:00
2017-03-05 16:44:50 +01:00
glGenVertexArrays ( 1 , & resources . quadie_array ) ;
2016-10-21 12:27:13 +02:00
glBindVertexArray ( resources . quadie_array ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , resources . quadie ) ;
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 , 0 ) ;
2016-10-21 12:27:13 +02:00
glEnableVertexAttribArray ( 0 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 , CAST_INT_TO_UCHAR_PTR ( 8 ) ) ;
2016-10-30 01:48:09 +02:00
glEnableVertexAttribArray ( 4 ) ;
2016-10-21 12:27:13 +02:00
glBindVertexArray ( 0 ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-21 12:27:13 +02:00
}
2017-05-25 18:53:59 +02:00
//generic quadie for copying without touching sky
2016-11-25 00:46:55 +01:00
{
//transform feedback buffers
2018-07-19 23:58:15 +02:00
uint32_t xf_feedback_size = GLOBAL_DEF_RST ( " rendering/limits/buffers/blend_shape_max_buffer_size_kb " , 4096 ) ;
2018-10-05 18:43:53 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/limits/buffers/blend_shape_max_buffer_size_kb " , PropertyInfo ( Variant : : INT , " rendering/limits/buffers/blend_shape_max_buffer_size_kb " , PROPERTY_HINT_RANGE , " 0,8192,1,or_greater " ) ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 2 ; i + + ) {
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & resources . transform_feedback_buffers [ i ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , resources . transform_feedback_buffers [ i ] ) ;
glBufferData ( GL_ARRAY_BUFFER , xf_feedback_size * 1024 , NULL , GL_STREAM_DRAW ) ;
2016-11-25 00:46:55 +01:00
}
2017-01-14 18:03:38 +01:00
shaders . blend_shapes . init ( ) ;
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
glGenVertexArrays ( 1 , & resources . transform_feedback_array ) ;
2016-11-25 00:46:55 +01:00
}
2016-10-21 12:27:13 +02:00
shaders . cubemap_filter . init ( ) ;
2019-05-26 03:57:32 +02:00
bool ggx_hq = GLOBAL_GET ( " rendering/quality/reflections/high_quality_ggx " ) ;
2017-07-22 19:07:38 +02:00
shaders . cubemap_filter . set_conditional ( CubemapFilterShaderGLES3 : : LOW_QUALITY , ! ggx_hq ) ;
2017-01-02 02:16:52 +01:00
shaders . particles . init ( ) ;
2016-10-30 02:11:05 +01:00
2017-03-15 15:18:20 +01:00
# ifdef GLES_OVER_GL
2016-10-30 02:11:05 +01:00
glEnable ( _EXT_TEXTURE_CUBE_MAP_SEAMLESS ) ;
2017-03-14 14:53:00 +01:00
# endif
2016-11-19 17:23:37 +01:00
2017-03-05 16:44:50 +01:00
frame . count = 0 ;
frame . delta = 0 ;
2017-04-13 20:14:10 +02:00
frame . current_rt = NULL ;
2017-03-05 16:44:50 +01:00
config . keep_original_textures = false ;
2017-06-11 20:52:03 +02:00
config . generate_wireframes = false ;
2017-07-19 22:00:46 +02:00
config . use_texture_array_environment = GLOBAL_GET ( " rendering/quality/reflections/texture_array_reflections " ) ;
2017-07-22 19:07:38 +02:00
config . force_vertex_shading = GLOBAL_GET ( " rendering/quality/shading/force_vertex_shading " ) ;
String renderer = ( const char * ) glGetString ( GL_RENDERER ) ;
2019-03-22 11:09:23 +01:00
config . use_depth_prepass = bool ( GLOBAL_GET ( " rendering/quality/depth_prepass/enable " ) ) ;
if ( config . use_depth_prepass ) {
2017-07-22 19:07:38 +02:00
String vendors = GLOBAL_GET ( " rendering/quality/depth_prepass/disable_for_vendors " ) ;
Vector < String > vendor_match = vendors . split ( " , " ) ;
for ( int i = 0 ; i < vendor_match . size ( ) ; i + + ) {
String v = vendor_match [ i ] . strip_edges ( ) ;
if ( v = = String ( ) )
continue ;
if ( renderer . findn ( v ) ! = - 1 ) {
2019-03-22 11:09:23 +01:00
config . use_depth_prepass = false ;
2017-07-22 19:07:38 +02:00
}
}
}
2016-10-03 21:33:42 +02:00
}
void RasterizerStorageGLES3 : : finalize ( ) {
glDeleteTextures ( 1 , & resources . white_tex ) ;
glDeleteTextures ( 1 , & resources . black_tex ) ;
glDeleteTextures ( 1 , & resources . normal_tex ) ;
}
2017-02-16 12:55:11 +01:00
void RasterizerStorageGLES3 : : update_dirty_resources ( ) {
update_dirty_multimeshes ( ) ;
update_dirty_skeletons ( ) ;
update_dirty_shaders ( ) ;
update_dirty_materials ( ) ;
update_particles ( ) ;
}
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
RasterizerStorageGLES3 : : RasterizerStorageGLES3 ( ) {
2016-10-03 21:33:42 +02:00
}