2017-03-05 15:47:28 +01:00
/*************************************************************************/
/* rasterizer_canvas_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_canvas_gles3.h"
2018-09-11 18:13:45 +02:00
# include "core/os/os.h"
# include "core/project_settings.h"
2017-06-27 03:58:03 +02:00
# include "rasterizer_scene_gles3.h"
# include "servers/visual/visual_server_raster.h"
2018-09-11 18:13:45 +02:00
2017-01-31 03:46:30 +01:00
# ifndef GLES_OVER_GL
2017-01-07 09:33:11 +01:00
# define glClearDepth glClearDepthf
# endif
2017-03-05 16:44:50 +01:00
static _FORCE_INLINE_ void store_transform2d ( const Transform2D & p_mtx , float * p_array ) {
p_array [ 0 ] = p_mtx . elements [ 0 ] [ 0 ] ;
p_array [ 1 ] = p_mtx . elements [ 0 ] [ 1 ] ;
p_array [ 2 ] = 0 ;
p_array [ 3 ] = 0 ;
p_array [ 4 ] = p_mtx . elements [ 1 ] [ 0 ] ;
p_array [ 5 ] = p_mtx . elements [ 1 ] [ 1 ] ;
p_array [ 6 ] = 0 ;
p_array [ 7 ] = 0 ;
p_array [ 8 ] = 0 ;
p_array [ 9 ] = 0 ;
p_array [ 10 ] = 1 ;
p_array [ 11 ] = 0 ;
p_array [ 12 ] = p_mtx . elements [ 2 ] [ 0 ] ;
p_array [ 13 ] = p_mtx . elements [ 2 ] [ 1 ] ;
p_array [ 14 ] = 0 ;
p_array [ 15 ] = 1 ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
static _FORCE_INLINE_ void store_transform ( const Transform & p_mtx , float * p_array ) {
p_array [ 0 ] = p_mtx . basis . elements [ 0 ] [ 0 ] ;
p_array [ 1 ] = p_mtx . basis . elements [ 1 ] [ 0 ] ;
p_array [ 2 ] = p_mtx . basis . elements [ 2 ] [ 0 ] ;
p_array [ 3 ] = 0 ;
p_array [ 4 ] = p_mtx . basis . elements [ 0 ] [ 1 ] ;
p_array [ 5 ] = p_mtx . basis . elements [ 1 ] [ 1 ] ;
p_array [ 6 ] = p_mtx . basis . elements [ 2 ] [ 1 ] ;
p_array [ 7 ] = 0 ;
p_array [ 8 ] = p_mtx . basis . elements [ 0 ] [ 2 ] ;
p_array [ 9 ] = p_mtx . basis . elements [ 1 ] [ 2 ] ;
p_array [ 10 ] = p_mtx . basis . elements [ 2 ] [ 2 ] ;
p_array [ 11 ] = 0 ;
p_array [ 12 ] = p_mtx . origin . x ;
p_array [ 13 ] = p_mtx . origin . y ;
p_array [ 14 ] = p_mtx . origin . z ;
p_array [ 15 ] = 1 ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
static _FORCE_INLINE_ void store_camera ( const CameraMatrix & p_mtx , float * p_array ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
for ( int j = 0 ; j < 4 ; j + + ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
p_array [ i * 4 + j ] = p_mtx . matrix [ i ] [ j ] ;
2016-10-03 21:33:42 +02:00
}
}
}
RID RasterizerCanvasGLES3 : : light_internal_create ( ) {
2017-03-05 16:44:50 +01:00
LightInternal * li = memnew ( LightInternal ) ;
2016-10-03 21:33:42 +02:00
glGenBuffers ( 1 , & li - > ubo ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , li - > ubo ) ;
glBufferData ( GL_UNIFORM_BUFFER , sizeof ( LightInternal : : UBOData ) , & state . canvas_item_ubo_data , GL_DYNAMIC_DRAW ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
return light_internal_owner . make_rid ( li ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : light_internal_update ( RID p_rid , Light * p_light ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
LightInternal * li = light_internal_owner . getornull ( p_rid ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! li ) ;
2017-03-05 16:44:50 +01:00
store_transform2d ( p_light - > light_shader_xform , li - > ubo_data . light_matrix ) ;
store_transform2d ( p_light - > xform_cache . affine_inverse ( ) , li - > ubo_data . local_matrix ) ;
store_camera ( p_light - > shadow_matrix_cache , li - > ubo_data . shadow_matrix ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
li - > ubo_data . color [ i ] = p_light - > color [ i ] * p_light - > energy ;
li - > ubo_data . shadow_color [ i ] = p_light - > shadow_color [ i ] ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
li - > ubo_data . light_pos [ 0 ] = p_light - > light_shader_pos . x ;
li - > ubo_data . light_pos [ 1 ] = p_light - > light_shader_pos . y ;
2017-06-13 06:23:04 +02:00
li - > ubo_data . shadowpixel_size = ( 1.0 / p_light - > shadow_buffer_size ) * ( 1.0 + p_light - > shadow_smooth ) ;
2017-03-05 16:44:50 +01:00
li - > ubo_data . light_outside_alpha = p_light - > mode = = VS : : CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0 ;
li - > ubo_data . light_height = p_light - > height ;
if ( p_light - > radius_cache = = 0 )
li - > ubo_data . shadow_gradient = 0 ;
2016-10-03 21:33:42 +02:00
else
2017-03-05 16:44:50 +01:00
li - > ubo_data . shadow_gradient = p_light - > shadow_gradient_length / ( p_light - > radius_cache * 1.1 ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
li - > ubo_data . shadow_distance_mult = ( p_light - > radius_cache * 1.1 ) ;
2016-10-03 21:33:42 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , li - > ubo ) ;
2019-11-10 19:51:56 +01:00
glBufferData ( GL_UNIFORM_BUFFER , sizeof ( LightInternal : : UBOData ) , & li - > ubo_data , GL_DYNAMIC_DRAW ) ;
2016-10-03 21:33:42 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
}
void RasterizerCanvasGLES3 : : light_internal_free ( RID p_rid ) {
2017-03-05 16:44:50 +01:00
LightInternal * li = light_internal_owner . getornull ( p_rid ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! li ) ;
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & li - > ubo ) ;
2016-10-03 21:33:42 +02:00
light_internal_owner . free ( p_rid ) ;
memdelete ( li ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : canvas_begin ( ) {
2016-10-03 21:33:42 +02:00
2016-10-05 06:26:35 +02:00
if ( storage - > frame . current_rt & & storage - > frame . clear_request ) {
// a clear request may be pending, so do it
2019-01-27 19:47:17 +01:00
bool transparent = storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ;
2016-10-05 06:26:35 +02:00
2019-01-27 19:47:17 +01:00
glClearColor ( storage - > frame . clear_request_color . r ,
storage - > frame . clear_request_color . g ,
storage - > frame . clear_request_color . b ,
transparent ? storage - > frame . clear_request_color . a : 1.0 ) ;
2016-10-05 06:26:35 +02:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
2017-03-05 16:44:50 +01:00
storage - > frame . clear_request = false ;
2019-01-27 19:47:17 +01:00
glColorMask ( 1 , 1 , 1 , transparent ? 1 : 0 ) ;
2016-10-05 06:26:35 +02:00
}
2016-10-03 21:33:42 +02:00
reset_canvas ( ) ;
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_TEXTURE_RECT , true ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_LIGHTING , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_SHADOWS , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_NEAREST , false ) ;
2019-01-17 14:40:36 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF3 , false ) ;
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF5 , false ) ;
2019-01-17 14:40:36 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF7 , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF9 , false ) ;
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF13 , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_DISTANCE_FIELD , false ) ;
2017-06-22 04:37:25 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_NINEPATCH , false ) ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_LIGHT_ANGLE , false ) ;
2018-05-03 22:29:15 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_SKELETON , false ) ;
2016-10-03 21:33:42 +02:00
2016-10-10 23:31:01 +02:00
state . canvas_shader . set_custom_shader ( 0 ) ;
2016-10-03 21:33:42 +02:00
state . canvas_shader . bind ( ) ;
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : FINAL_MODULATE , Color ( 1 , 1 , 1 , 1 ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , Transform2D ( ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : EXTRA_MATRIX , Transform2D ( ) ) ;
2017-06-27 03:58:03 +02:00
if ( storage - > frame . current_rt ) {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 / storage - > frame . current_rt - > width , 1.0 / storage - > frame . current_rt - > height ) ) ;
} else {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 , 1.0 ) ) ;
}
2016-10-03 21:33:42 +02:00
2017-01-14 12:26:56 +01:00
//state.canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,state.vp);
2016-10-03 21:33:42 +02:00
//state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Transform());
//state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Transform());
2017-03-05 16:44:50 +01:00
glBindBufferBase ( GL_UNIFORM_BUFFER , 0 , state . canvas_item_ubo ) ;
2016-10-03 21:33:42 +02:00
glBindVertexArray ( data . canvas_quad_array ) ;
2017-03-05 16:44:50 +01:00
state . using_texture_rect = true ;
2017-06-22 04:37:25 +02:00
state . using_ninepatch = false ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
state . using_light_angle = false ;
2018-05-03 22:29:15 +02:00
state . using_skeleton = false ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : canvas_end ( ) {
2016-10-03 21:33:42 +02:00
glBindVertexArray ( 0 ) ;
2017-03-05 16:44:50 +01:00
glBindBufferBase ( GL_UNIFORM_BUFFER , 0 , 0 ) ;
2019-01-27 19:47:17 +01:00
glColorMask ( 1 , 1 , 1 , 1 ) ;
2016-10-03 21:33:42 +02:00
2019-08-10 15:08:37 +02:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
2017-03-05 16:44:50 +01:00
state . using_texture_rect = false ;
2017-06-22 04:37:25 +02:00
state . using_ninepatch = false ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
state . using_light_angle = false ;
2016-10-03 21:33:42 +02:00
}
2018-05-15 13:35:46 +02:00
RasterizerStorageGLES3 : : Texture * RasterizerCanvasGLES3 : : _bind_canvas_texture ( const RID & p_texture , const RID & p_normal_map , bool p_force ) {
2016-10-03 21:33:42 +02:00
2017-06-18 04:26:49 +02:00
RasterizerStorageGLES3 : : Texture * tex_return = NULL ;
2016-10-03 21:33:42 +02:00
2018-05-15 13:35:46 +02:00
if ( p_texture = = state . current_tex & & ! p_force ) {
2017-06-18 04:26:49 +02:00
tex_return = state . current_tex_ptr ;
} else if ( p_texture . is_valid ( ) ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
RasterizerStorageGLES3 : : Texture * texture = storage - > texture_owner . getornull ( p_texture ) ;
2016-10-03 21:33:42 +02:00
if ( ! texture ) {
2017-03-05 16:44:50 +01:00
state . current_tex = RID ( ) ;
state . current_tex_ptr = NULL ;
2017-06-18 04:26:49 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . white_tex ) ;
2016-10-03 21:33:42 +02:00
2017-06-18 04:26:49 +02:00
} else {
2016-10-03 21:33:42 +02:00
2018-07-16 16:43:26 +02:00
if ( texture - > redraw_if_visible ) { //check before proxy, because this is usually used with proxies
VisualServerRaster : : redraw_request ( ) ;
}
2019-03-03 17:43:54 +01:00
texture = texture - > get_ptr ( ) ;
2017-06-18 04:26:49 +02:00
if ( texture - > render_target )
texture - > render_target - > used_in_frame = true ;
2016-10-03 21:33:42 +02:00
2017-06-18 04:26:49 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , texture - > tex_id ) ;
state . current_tex = p_texture ;
state . current_tex_ptr = texture ;
tex_return = texture ;
}
2016-10-03 21:33:42 +02:00
} else {
2017-06-18 04:26:49 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . white_tex ) ;
state . current_tex = RID ( ) ;
state . current_tex_ptr = NULL ;
2016-10-03 21:33:42 +02:00
}
2018-05-15 13:35:46 +02:00
if ( p_normal_map = = state . current_normal & & ! p_force ) {
2017-06-18 04:26:49 +02:00
//do none
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : USE_DEFAULT_NORMAL , state . current_normal . is_valid ( ) ) ;
} else if ( p_normal_map . is_valid ( ) ) {
RasterizerStorageGLES3 : : Texture * normal_map = storage - > texture_owner . getornull ( p_normal_map ) ;
if ( ! normal_map ) {
state . current_normal = RID ( ) ;
glActiveTexture ( GL_TEXTURE1 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . normal_tex ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : USE_DEFAULT_NORMAL , false ) ;
} else {
2018-07-16 16:43:26 +02:00
if ( normal_map - > redraw_if_visible ) { //check before proxy, because this is usually used with proxies
VisualServerRaster : : redraw_request ( ) ;
}
2019-03-03 17:43:54 +01:00
normal_map = normal_map - > get_ptr ( ) ;
2017-06-18 04:26:49 +02:00
glActiveTexture ( GL_TEXTURE1 ) ;
glBindTexture ( GL_TEXTURE_2D , normal_map - > tex_id ) ;
state . current_normal = p_normal_map ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : USE_DEFAULT_NORMAL , true ) ;
}
} else {
state . current_normal = RID ( ) ;
glActiveTexture ( GL_TEXTURE1 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . normal_tex ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : USE_DEFAULT_NORMAL , false ) ;
}
return tex_return ;
2016-10-03 21:33:42 +02:00
}
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
void RasterizerCanvasGLES3 : : _set_texture_rect_mode ( bool p_enable , bool p_ninepatch , bool p_light_angle ) {
2016-10-03 21:33:42 +02:00
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
if ( state . using_texture_rect = = p_enable & & state . using_ninepatch = = p_ninepatch & & state . using_light_angle = = p_light_angle )
2016-10-03 21:33:42 +02:00
return ;
if ( p_enable ) {
glBindVertexArray ( data . canvas_quad_array ) ;
} else {
glBindVertexArray ( 0 ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
2016-10-03 21:33:42 +02:00
}
2017-06-22 04:37:25 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_NINEPATCH , p_ninepatch & & p_enable ) ;
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_TEXTURE_RECT , p_enable ) ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_LIGHT_ANGLE , p_light_angle ) ;
2016-10-03 21:33:42 +02:00
state . canvas_shader . bind ( ) ;
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : FINAL_MODULATE , state . canvas_item_modulate ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , state . final_transform ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : EXTRA_MATRIX , state . extra_matrix ) ;
2018-05-03 22:29:15 +02:00
if ( state . using_skeleton ) {
2018-05-04 14:32:40 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SKELETON_TRANSFORM , state . skeleton_transform ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SKELETON_TRANSFORM_INVERSE , state . skeleton_transform_inverse ) ;
2018-05-03 22:29:15 +02:00
}
2017-06-27 03:58:03 +02:00
if ( storage - > frame . current_rt ) {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 / storage - > frame . current_rt - > width , 1.0 / storage - > frame . current_rt - > height ) ) ;
} else {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 , 1.0 ) ) ;
}
2017-03-05 16:44:50 +01:00
state . using_texture_rect = p_enable ;
2017-06-22 04:37:25 +02:00
state . using_ninepatch = p_ninepatch ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
state . using_light_angle = p_light_angle ;
2016-10-03 21:33:42 +02:00
}
2018-05-03 22:29:15 +02:00
void RasterizerCanvasGLES3 : : _draw_polygon ( const int * p_indices , int p_index_count , int p_vertex_count , const Vector2 * p_vertices , const Vector2 * p_uvs , const Color * p_colors , bool p_singlecolor , const int * p_bones , const float * p_weights ) {
2016-10-03 21:33:42 +02:00
2017-06-12 23:56:16 +02:00
glBindVertexArray ( data . polygon_buffer_pointer_array ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
2016-10-03 21:33:42 +02:00
2019-11-10 19:51:56 +01:00
# ifndef GLES_OVER_GL
2019-12-03 16:54:25 +01:00
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
2019-11-10 19:51:56 +01:00
glBufferData ( GL_ARRAY_BUFFER , data . polygon_buffer_size , NULL , GL_DYNAMIC_DRAW ) ;
# endif
2017-06-12 23:56:16 +02:00
uint32_t buffer_ofs = 0 ;
2016-10-03 21:33:42 +02:00
2017-06-12 23:56:16 +02:00
//vertex
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Vector2 ) * p_vertex_count , p_vertices ) ;
2016-10-03 21:33:42 +02:00
glEnableVertexAttribArray ( VS : : ARRAY_VERTEX ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2017-06-12 23:56:16 +02:00
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
//color
2018-05-04 14:32:40 +02:00
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
2016-10-03 21:33:42 +02:00
2017-06-12 23:56:16 +02:00
if ( p_singlecolor ) {
2016-10-03 21:33:42 +02:00
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
2017-06-12 23:56:16 +02:00
Color m = * p_colors ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , m . r , m . g , m . b , m . a ) ;
} else if ( ! p_colors ) {
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
2016-10-03 21:33:42 +02:00
} else {
2017-06-12 23:56:16 +02:00
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Color ) * p_vertex_count , p_colors ) ;
2016-10-03 21:33:42 +02:00
glEnableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_COLOR , 4 , GL_FLOAT , false , sizeof ( Color ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2017-06-12 23:56:16 +02:00
buffer_ofs + = sizeof ( Color ) * p_vertex_count ;
2016-10-03 21:33:42 +02:00
}
2018-05-04 14:32:40 +02:00
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
2016-10-03 21:33:42 +02:00
if ( p_uvs ) {
2017-06-12 23:56:16 +02:00
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Vector2 ) * p_vertex_count , p_uvs ) ;
2016-10-03 21:33:42 +02:00
glEnableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2017-06-12 23:56:16 +02:00
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
2016-10-03 21:33:42 +02:00
} else {
glDisableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
}
2018-05-04 14:32:40 +02:00
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
2018-05-03 22:29:15 +02:00
if ( p_bones & & p_weights ) {
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( int ) * 4 * p_vertex_count , p_bones ) ;
glEnableVertexAttribArray ( VS : : ARRAY_BONES ) ;
2018-05-04 14:32:40 +02:00
//glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs);
2019-02-27 10:07:30 +01:00
glVertexAttribIPointer ( VS : : ARRAY_BONES , 4 , GL_UNSIGNED_INT , sizeof ( int ) * 4 , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2018-05-03 22:29:15 +02:00
buffer_ofs + = sizeof ( int ) * 4 * p_vertex_count ;
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( float ) * 4 * p_vertex_count , p_weights ) ;
glEnableVertexAttribArray ( VS : : ARRAY_WEIGHTS ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_WEIGHTS , 4 , GL_FLOAT , false , sizeof ( float ) * 4 , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2018-05-03 22:29:15 +02:00
buffer_ofs + = sizeof ( float ) * 4 * p_vertex_count ;
} else if ( state . using_skeleton ) {
glVertexAttribI4ui ( VS : : ARRAY_BONES , 0 , 0 , 0 , 0 ) ;
glVertexAttrib4f ( VS : : ARRAY_WEIGHTS , 0 , 0 , 0 , 0 ) ;
}
2018-05-04 14:32:40 +02:00
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
2016-10-03 21:33:42 +02:00
//bind the indices buffer.
2017-06-12 23:56:16 +02:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , data . polygon_index_buffer ) ;
2019-12-03 16:54:25 +01:00
# ifndef GLES_OVER_GL
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
glBufferData ( GL_ELEMENT_ARRAY_BUFFER , data . polygon_index_buffer_size , NULL , GL_DYNAMIC_DRAW ) ;
# endif
2017-06-12 23:56:16 +02:00
glBufferSubData ( GL_ELEMENT_ARRAY_BUFFER , 0 , sizeof ( int ) * p_index_count , p_indices ) ;
2016-10-03 21:33:42 +02:00
//draw the triangles.
2017-06-12 23:56:16 +02:00
glDrawElements ( GL_TRIANGLES , p_index_count , GL_UNSIGNED_INT , 0 ) ;
2016-10-03 21:33:42 +02:00
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2017-06-12 23:56:16 +02:00
2018-05-03 22:29:15 +02:00
if ( p_bones & & p_weights ) {
//not used so often, so disable when used
glDisableVertexAttribArray ( VS : : ARRAY_BONES ) ;
glDisableVertexAttribArray ( VS : : ARRAY_WEIGHTS ) ;
}
2017-06-12 23:56:16 +02:00
glBindVertexArray ( 0 ) ;
2019-12-09 09:25:02 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2016-10-03 21:33:42 +02:00
}
2017-07-01 02:30:17 +02:00
void RasterizerCanvasGLES3 : : _draw_generic ( GLuint p_primitive , int p_vertex_count , const Vector2 * p_vertices , const Vector2 * p_uvs , const Color * p_colors , bool p_singlecolor ) {
glBindVertexArray ( data . polygon_buffer_pointer_array ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
2019-11-10 19:51:56 +01:00
# ifndef GLES_OVER_GL
2019-12-03 16:54:25 +01:00
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
2019-11-10 19:51:56 +01:00
glBufferData ( GL_ARRAY_BUFFER , data . polygon_buffer_size , NULL , GL_DYNAMIC_DRAW ) ;
# endif
2017-07-01 02:30:17 +02:00
uint32_t buffer_ofs = 0 ;
//vertex
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Vector2 ) * p_vertex_count , p_vertices ) ;
glEnableVertexAttribArray ( VS : : ARRAY_VERTEX ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2017-07-01 02:30:17 +02:00
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
//color
if ( p_singlecolor ) {
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
Color m = * p_colors ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , m . r , m . g , m . b , m . a ) ;
} else if ( ! p_colors ) {
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
} else {
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Color ) * p_vertex_count , p_colors ) ;
glEnableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_COLOR , 4 , GL_FLOAT , false , sizeof ( Color ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2017-07-01 02:30:17 +02:00
buffer_ofs + = sizeof ( Color ) * p_vertex_count ;
}
if ( p_uvs ) {
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Vector2 ) * p_vertex_count , p_uvs ) ;
glEnableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
2017-07-01 02:30:17 +02:00
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
} else {
glDisableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
}
glDrawArrays ( p_primitive , 0 , p_vertex_count ) ;
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2017-07-01 02:30:17 +02:00
glBindVertexArray ( 0 ) ;
2019-12-09 09:25:02 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2017-07-01 02:30:17 +02:00
}
2019-11-24 11:00:02 +01:00
void RasterizerCanvasGLES3 : : _draw_generic_indices ( GLuint p_primitive , const int * p_indices , int p_index_count , int p_vertex_count , const Vector2 * p_vertices , const Vector2 * p_uvs , const Color * p_colors , bool p_singlecolor ) {
glBindVertexArray ( data . polygon_buffer_pointer_array ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
# ifndef GLES_OVER_GL
2019-12-04 12:16:50 +01:00
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
2019-11-24 11:00:02 +01:00
glBufferData ( GL_ARRAY_BUFFER , data . polygon_buffer_size , NULL , GL_DYNAMIC_DRAW ) ;
# endif
uint32_t buffer_ofs = 0 ;
//vertex
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Vector2 ) * p_vertex_count , p_vertices ) ;
glEnableVertexAttribArray ( VS : : ARRAY_VERTEX ) ;
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
//color
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
if ( p_singlecolor ) {
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
Color m = * p_colors ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , m . r , m . g , m . b , m . a ) ;
} else if ( ! p_colors ) {
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
} else {
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Color ) * p_vertex_count , p_colors ) ;
glEnableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
glVertexAttribPointer ( VS : : ARRAY_COLOR , 4 , GL_FLOAT , false , sizeof ( Color ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
buffer_ofs + = sizeof ( Color ) * p_vertex_count ;
}
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
if ( p_uvs ) {
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Vector2 ) * p_vertex_count , p_uvs ) ;
glEnableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , CAST_INT_TO_UCHAR_PTR ( buffer_ofs ) ) ;
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
} else {
glDisableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
}
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
//bind the indices buffer.
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , data . polygon_index_buffer ) ;
2019-12-04 12:16:50 +01:00
# ifndef GLES_OVER_GL
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
glBufferData ( GL_ELEMENT_ARRAY_BUFFER , data . polygon_index_buffer_size , NULL , GL_DYNAMIC_DRAW ) ;
# endif
2019-11-24 11:00:02 +01:00
glBufferSubData ( GL_ELEMENT_ARRAY_BUFFER , 0 , sizeof ( int ) * p_index_count , p_indices ) ;
//draw the triangles.
glDrawElements ( p_primitive , p_index_count , GL_UNSIGNED_INT , 0 ) ;
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2019-11-24 11:00:02 +01:00
glBindVertexArray ( 0 ) ;
2019-12-09 09:25:02 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2019-11-24 11:00:02 +01:00
}
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
void RasterizerCanvasGLES3 : : _draw_gui_primitive ( int p_points , const Vector2 * p_vertices , const Color * p_colors , const Vector2 * p_uvs , const float * p_light_angles ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
static const GLenum prim [ 5 ] = { GL_POINTS , GL_POINTS , GL_LINES , GL_TRIANGLES , GL_TRIANGLE_FAN } ;
2016-10-03 21:33:42 +02:00
//#define GLES_USE_PRIMITIVE_BUFFER
2017-03-05 16:44:50 +01:00
int version = 0 ;
int color_ofs = 0 ;
int uv_ofs = 0 ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
int light_angle_ofs = 0 ;
2017-03-05 16:44:50 +01:00
int stride = 2 ;
2016-10-03 21:33:42 +02:00
2016-11-23 00:51:56 +01:00
if ( p_colors ) { //color
2017-03-05 16:44:50 +01:00
version | = 1 ;
color_ofs = stride ;
stride + = 4 ;
2016-10-03 21:33:42 +02:00
}
2016-11-23 00:51:56 +01:00
if ( p_uvs ) { //uv
2017-03-05 16:44:50 +01:00
version | = 2 ;
uv_ofs = stride ;
stride + = 2 ;
2016-10-03 21:33:42 +02:00
}
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
if ( p_light_angles ) { //light_angles
version | = 4 ;
light_angle_ofs = stride ;
stride + = 1 ;
}
float b [ ( 2 + 2 + 4 + 1 ) * 4 ] ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_points ; i + + ) {
b [ stride * i + 0 ] = p_vertices [ i ] . x ;
b [ stride * i + 1 ] = p_vertices [ i ] . y ;
2016-10-03 21:33:42 +02:00
}
if ( p_colors ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_points ; i + + ) {
b [ stride * i + color_ofs + 0 ] = p_colors [ i ] . r ;
b [ stride * i + color_ofs + 1 ] = p_colors [ i ] . g ;
b [ stride * i + color_ofs + 2 ] = p_colors [ i ] . b ;
b [ stride * i + color_ofs + 3 ] = p_colors [ i ] . a ;
2016-10-03 21:33:42 +02:00
}
}
if ( p_uvs ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_points ; i + + ) {
b [ stride * i + uv_ofs + 0 ] = p_uvs [ i ] . x ;
b [ stride * i + uv_ofs + 1 ] = p_uvs [ i ] . y ;
2016-10-03 21:33:42 +02:00
}
}
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
if ( p_light_angles ) {
for ( int i = 0 ; i < p_points ; i + + ) {
b [ stride * i + light_angle_ofs ] = p_light_angles [ i ] ;
}
}
2017-06-12 23:56:16 +02:00
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
2019-11-10 19:51:56 +01:00
# ifndef GLES_OVER_GL
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
glBufferData ( GL_ARRAY_BUFFER , data . polygon_buffer_size , NULL , GL_DYNAMIC_DRAW ) ;
# endif
//TODO the below call may need to be replaced with: glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), &b[0]);
2017-03-05 16:44:50 +01:00
glBufferSubData ( GL_ARRAY_BUFFER , 0 , p_points * stride * 4 , & b [ 0 ] ) ;
2017-06-12 23:56:16 +02:00
glBindVertexArray ( data . polygon_buffer_quad_arrays [ version ] ) ;
2017-03-05 16:44:50 +01:00
glDrawArrays ( prim [ p_points ] , 0 , p_points ) ;
2016-11-23 00:51:56 +01:00
glBindVertexArray ( 0 ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2016-10-03 21:33:42 +02:00
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2016-10-03 21:33:42 +02:00
}
2018-02-21 13:38:21 +01:00
static const GLenum gl_primitive [ ] = {
GL_POINTS ,
GL_LINES ,
GL_LINE_STRIP ,
GL_LINE_LOOP ,
GL_TRIANGLES ,
GL_TRIANGLE_STRIP ,
GL_TRIANGLE_FAN
} ;
2020-05-05 17:25:45 +02:00
void RasterizerCanvasGLES3 : : render_rect_nvidia_workaround ( const Item : : CommandRect * p_rect , const RasterizerStorageGLES3 : : Texture * p_texture ) {
if ( p_texture ) {
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
bool send_light_angles = false ;
// only need to use light angles when normal mapping
// otherwise we can use the default shader
if ( state . current_normal ! = RID ( ) ) {
send_light_angles = true ;
}
// we don't want to use texture rect, and we want to send light angles if we are using normal mapping
_set_texture_rect_mode ( false , false , send_light_angles ) ;
2020-05-05 17:25:45 +02:00
bool untile = false ;
if ( p_rect - > flags & CANVAS_RECT_TILE & & ! ( p_texture - > flags & VS : : TEXTURE_FLAG_REPEAT ) ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
untile = true ;
}
Size2 texpixel_size ( 1.0 / p_texture - > width , 1.0 / p_texture - > height ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : CLIP_RECT_UV , p_rect - > flags & CANVAS_RECT_CLIP_UV ) ;
Vector2 points [ 4 ] = {
p_rect - > rect . position ,
p_rect - > rect . position + Vector2 ( p_rect - > rect . size . x , 0.0 ) ,
p_rect - > rect . position + p_rect - > rect . size ,
p_rect - > rect . position + Vector2 ( 0.0 , p_rect - > rect . size . y ) ,
} ;
if ( p_rect - > rect . size . x < 0 ) {
SWAP ( points [ 0 ] , points [ 1 ] ) ;
SWAP ( points [ 2 ] , points [ 3 ] ) ;
}
if ( p_rect - > rect . size . y < 0 ) {
SWAP ( points [ 0 ] , points [ 3 ] ) ;
SWAP ( points [ 1 ] , points [ 2 ] ) ;
}
Rect2 src_rect = ( p_rect - > flags & CANVAS_RECT_REGION ) ? Rect2 ( p_rect - > source . position * texpixel_size , p_rect - > source . size * texpixel_size ) : Rect2 ( 0 , 0 , 1 , 1 ) ;
Vector2 uvs [ 4 ] = {
src_rect . position ,
src_rect . position + Vector2 ( src_rect . size . x , 0.0 ) ,
src_rect . position + src_rect . size ,
src_rect . position + Vector2 ( 0.0 , src_rect . size . y ) ,
} ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
// for encoding in light angle
bool flip_h = false ;
bool flip_v = false ;
2020-05-05 17:25:45 +02:00
if ( p_rect - > flags & CANVAS_RECT_TRANSPOSE ) {
SWAP ( uvs [ 1 ] , uvs [ 3 ] ) ;
}
if ( p_rect - > flags & CANVAS_RECT_FLIP_H ) {
SWAP ( uvs [ 0 ] , uvs [ 1 ] ) ;
SWAP ( uvs [ 2 ] , uvs [ 3 ] ) ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
flip_h = true ;
flip_v = ! flip_v ;
2020-05-05 17:25:45 +02:00
}
if ( p_rect - > flags & CANVAS_RECT_FLIP_V ) {
SWAP ( uvs [ 0 ] , uvs [ 3 ] ) ;
SWAP ( uvs [ 1 ] , uvs [ 2 ] ) ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
flip_v = ! flip_v ;
2020-05-05 17:25:45 +02:00
}
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
if ( send_light_angles ) {
// for single rects, there is no need to fully utilize the light angle,
// we only need it to encode flips (horz and vert). But the shader can be reused with
// batching in which case the angle encodes the transform as well as
// the flips.
// Note transpose is NYI. I don't think it worked either with the non-nvidia method.
// if horizontal flip, angle is 180
float angle = 0.0f ;
if ( flip_h )
angle = Math_PI ;
// add 1 (to take care of zero floating point error with sign)
angle + = 1.0f ;
// flip if necessary
if ( flip_v )
angle * = - 1.0f ;
// light angle must be sent for each vert, instead as a single uniform in the uniform draw method
// this has the benefit of enabling batching with light angles.
float light_angles [ 4 ] = { angle , angle , angle , angle } ;
_draw_gui_primitive ( 4 , points , NULL , uvs , light_angles ) ;
} else {
_draw_gui_primitive ( 4 , points , NULL , uvs ) ;
}
2020-05-05 17:25:45 +02:00
if ( untile ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
}
} else {
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
_set_texture_rect_mode ( false ) ;
2020-05-05 17:25:45 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : CLIP_RECT_UV , false ) ;
Vector2 points [ 4 ] = {
p_rect - > rect . position ,
p_rect - > rect . position + Vector2 ( p_rect - > rect . size . x , 0.0 ) ,
p_rect - > rect . position + p_rect - > rect . size ,
p_rect - > rect . position + Vector2 ( 0.0 , p_rect - > rect . size . y ) ,
} ;
_draw_gui_primitive ( 4 , points , NULL , nullptr ) ;
}
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : _canvas_item_render_commands ( Item * p_item , Item * current_clip , bool & reclip ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
int cc = p_item - > commands . size ( ) ;
2017-11-25 04:07:54 +01:00
Item : : Command * * commands = p_item - > commands . ptrw ( ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < cc ; i + + ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Item : : Command * c = commands [ i ] ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
switch ( c - > type ) {
2016-10-03 21:33:42 +02:00
case Item : : Command : : TYPE_LINE : {
2017-03-05 16:44:50 +01:00
Item : : CommandLine * line = static_cast < Item : : CommandLine * > ( c ) ;
2016-10-03 21:33:42 +02:00
_set_texture_rect_mode ( false ) ;
2017-06-18 04:26:49 +02:00
_bind_canvas_texture ( RID ( ) , RID ( ) ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , line - > color . r , line - > color . g , line - > color . b , line - > color . a ) ;
2016-10-03 21:33:42 +02:00
2017-07-01 02:30:17 +02:00
if ( line - > width < = 1 ) {
Vector2 verts [ 2 ] = {
2019-11-07 15:37:18 +01:00
Vector2 ( line - > from . x , line - > from . y ) ,
Vector2 ( line - > to . x , line - > to . y )
2017-07-01 02:30:17 +02:00
} ;
2016-10-03 21:33:42 +02:00
2016-11-23 00:51:56 +01:00
# ifdef GLES_OVER_GL
2017-07-01 02:30:17 +02:00
if ( line - > antialiased )
glEnable ( GL_LINE_SMOOTH ) ;
2016-10-03 21:33:42 +02:00
# endif
2017-07-01 02:30:17 +02:00
//glLineWidth(line->width);
_draw_gui_primitive ( 2 , verts , NULL , NULL ) ;
2016-10-03 21:33:42 +02:00
2016-11-23 00:51:56 +01:00
# ifdef GLES_OVER_GL
2017-07-01 02:30:17 +02:00
if ( line - > antialiased )
glDisable ( GL_LINE_SMOOTH ) ;
# endif
} else {
//thicker line
Vector2 t = ( line - > from - line - > to ) . normalized ( ) . tangent ( ) * line - > width * 0.5 ;
Vector2 verts [ 4 ] = {
line - > from - t ,
line - > from + t ,
line - > to + t ,
line - > to - t ,
} ;
//glLineWidth(line->width);
_draw_gui_primitive ( 4 , verts , NULL , NULL ) ;
# ifdef GLES_OVER_GL
if ( line - > antialiased ) {
glEnable ( GL_LINE_SMOOTH ) ;
2019-02-12 21:10:08 +01:00
for ( int j = 0 ; j < 4 ; j + + ) {
2017-07-01 02:30:17 +02:00
Vector2 vertsl [ 2 ] = {
2019-02-12 21:10:08 +01:00
verts [ j ] ,
verts [ ( j + 1 ) % 4 ] ,
2017-07-01 02:30:17 +02:00
} ;
_draw_gui_primitive ( 2 , vertsl , NULL , NULL ) ;
}
glDisable ( GL_LINE_SMOOTH ) ;
}
# endif
}
} break ;
case Item : : Command : : TYPE_POLYLINE : {
Item : : CommandPolyLine * pline = static_cast < Item : : CommandPolyLine * > ( c ) ;
_set_texture_rect_mode ( false ) ;
_bind_canvas_texture ( RID ( ) , RID ( ) ) ;
if ( pline - > triangles . size ( ) ) {
_draw_generic ( GL_TRIANGLE_STRIP , pline - > triangles . size ( ) , pline - > triangles . ptr ( ) , NULL , pline - > triangle_colors . ptr ( ) , pline - > triangle_colors . size ( ) = = 1 ) ;
# ifdef GLES_OVER_GL
glEnable ( GL_LINE_SMOOTH ) ;
2017-12-09 18:11:26 +01:00
if ( pline - > multiline ) {
//needs to be different
} else {
2017-07-01 02:30:17 +02:00
_draw_generic ( GL_LINE_LOOP , pline - > lines . size ( ) , pline - > lines . ptr ( ) , NULL , pline - > line_colors . ptr ( ) , pline - > line_colors . size ( ) = = 1 ) ;
}
2016-10-03 21:33:42 +02:00
glDisable ( GL_LINE_SMOOTH ) ;
# endif
2017-07-01 02:30:17 +02:00
} else {
# ifdef GLES_OVER_GL
if ( pline - > antialiased )
glEnable ( GL_LINE_SMOOTH ) ;
# endif
2017-12-09 18:11:26 +01:00
if ( pline - > multiline ) {
int todo = pline - > lines . size ( ) / 2 ;
int max_per_call = data . polygon_buffer_size / ( sizeof ( real_t ) * 4 ) ;
int offset = 0 ;
while ( todo ) {
int to_draw = MIN ( max_per_call , todo ) ;
_draw_generic ( GL_LINES , to_draw * 2 , & pline - > lines . ptr ( ) [ offset ] , NULL , pline - > line_colors . size ( ) = = 1 ? pline - > line_colors . ptr ( ) : & pline - > line_colors . ptr ( ) [ offset ] , pline - > line_colors . size ( ) = = 1 ) ;
todo - = to_draw ;
offset + = to_draw * 2 ;
}
} else {
2018-03-01 05:00:13 +01:00
_draw_generic ( GL_LINE_STRIP , pline - > lines . size ( ) , pline - > lines . ptr ( ) , NULL , pline - > line_colors . ptr ( ) , pline - > line_colors . size ( ) = = 1 ) ;
2017-12-09 18:11:26 +01:00
}
2017-07-01 02:30:17 +02:00
# ifdef GLES_OVER_GL
if ( pline - > antialiased )
glDisable ( GL_LINE_SMOOTH ) ;
# endif
}
2016-10-03 21:33:42 +02:00
} break ;
case Item : : Command : : TYPE_RECT : {
2017-03-05 16:44:50 +01:00
Item : : CommandRect * rect = static_cast < Item : : CommandRect * > ( c ) ;
2016-10-03 21:33:42 +02:00
//set color
2017-03-05 16:44:50 +01:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , rect - > modulate . r , rect - > modulate . g , rect - > modulate . b , rect - > modulate . a ) ;
2016-10-03 21:33:42 +02:00
2017-06-18 04:26:49 +02:00
RasterizerStorageGLES3 : : Texture * texture = _bind_canvas_texture ( rect - > texture , rect - > normal_map ) ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( use_nvidia_rect_workaround ) {
render_rect_nvidia_workaround ( rect , texture ) ;
} else {
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
_set_texture_rect_mode ( true ) ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( texture ) {
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
bool untile = false ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( rect - > flags & CANVAS_RECT_TILE & & ! ( texture - > flags & VS : : TEXTURE_FLAG_REPEAT ) ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
untile = true ;
}
2017-09-02 18:58:04 +02:00
2020-05-05 17:25:45 +02:00
Size2 texpixel_size ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
Rect2 src_rect = ( rect - > flags & CANVAS_RECT_REGION ) ? Rect2 ( rect - > source . position * texpixel_size , rect - > source . size * texpixel_size ) : Rect2 ( 0 , 0 , 1 , 1 ) ;
Rect2 dst_rect = Rect2 ( rect - > rect . position , rect - > rect . size ) ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( dst_rect . size . width < 0 ) {
dst_rect . position . x + = dst_rect . size . width ;
dst_rect . size . width * = - 1 ;
}
if ( dst_rect . size . height < 0 ) {
dst_rect . position . y + = dst_rect . size . height ;
dst_rect . size . height * = - 1 ;
}
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( rect - > flags & CANVAS_RECT_FLIP_H ) {
src_rect . size . x * = - 1 ;
}
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( rect - > flags & CANVAS_RECT_FLIP_V ) {
src_rect . size . y * = - 1 ;
}
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( rect - > flags & CANVAS_RECT_TRANSPOSE ) {
dst_rect . size . x * = - 1 ; // Encoding in the dst_rect.z uniform
}
2017-06-19 03:55:02 +02:00
2020-05-05 17:25:45 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : DST_RECT , Color ( dst_rect . position . x , dst_rect . position . y , dst_rect . size . x , dst_rect . size . y ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( src_rect . position . x , src_rect . position . y , src_rect . size . x , src_rect . size . y ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : CLIP_RECT_UV , rect - > flags & CANVAS_RECT_CLIP_UV ) ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
storage - > info . render . _2d_draw_call_count + + ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( untile ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
}
2017-09-02 18:58:04 +02:00
2020-05-05 17:25:45 +02:00
} else {
Rect2 dst_rect = Rect2 ( rect - > rect . position , rect - > rect . size ) ;
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
if ( dst_rect . size . width < 0 ) {
dst_rect . position . x + = dst_rect . size . width ;
dst_rect . size . width * = - 1 ;
}
if ( dst_rect . size . height < 0 ) {
dst_rect . position . y + = dst_rect . size . height ;
dst_rect . size . height * = - 1 ;
}
2016-10-03 21:33:42 +02:00
2020-05-05 17:25:45 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : DST_RECT , Color ( dst_rect . position . x , dst_rect . position . y , dst_rect . size . x , dst_rect . size . y ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( 0 , 0 , 1 , 1 ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : CLIP_RECT_UV , false ) ;
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
storage - > info . render . _2d_draw_call_count + + ;
}
} // if not use nvidia workaround
} break ;
2016-10-03 21:33:42 +02:00
case Item : : Command : : TYPE_NINEPATCH : {
2017-03-05 16:44:50 +01:00
Item : : CommandNinePatch * np = static_cast < Item : : CommandNinePatch * > ( c ) ;
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
_set_texture_rect_mode ( true , true ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , np - > color . r , np - > color . g , np - > color . b , np - > color . a ) ;
2016-10-03 21:33:42 +02:00
2017-06-18 04:26:49 +02:00
RasterizerStorageGLES3 : : Texture * texture = _bind_canvas_texture ( np - > texture , np - > normal_map ) ;
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
Size2 texpixel_size ;
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
if ( ! texture ) {
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
texpixel_size = Size2 ( 1 , 1 ) ;
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( 0 , 0 , 1 , 1 ) ) ;
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
} else {
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
if ( np - > source ! = Rect2 ( ) ) {
texpixel_size = Size2 ( 1.0 / np - > source . size . width , 1.0 / np - > source . size . height ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( np - > source . position . x / texture - > width , np - > source . position . y / texture - > height , np - > source . size . x / texture - > width , np - > source . size . y / texture - > height ) ) ;
} else {
texpixel_size = Size2 ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( 0 , 0 , 1 , 1 ) ) ;
}
}
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : CLIP_RECT_UV , false ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : NP_REPEAT_H , int ( np - > axis_x ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : NP_REPEAT_V , int ( np - > axis_y ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : NP_DRAW_CENTER , np - > draw_center ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : NP_MARGINS , Color ( np - > margin [ MARGIN_LEFT ] , np - > margin [ MARGIN_TOP ] , np - > margin [ MARGIN_RIGHT ] , np - > margin [ MARGIN_BOTTOM ] ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : DST_RECT , Color ( np - > rect . position . x , np - > rect . position . y , np - > rect . size . x , np - > rect . size . y ) ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
2016-10-03 21:33:42 +02:00
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2016-10-03 21:33:42 +02:00
} break ;
case Item : : Command : : TYPE_PRIMITIVE : {
2017-03-05 16:44:50 +01:00
Item : : CommandPrimitive * primitive = static_cast < Item : : CommandPrimitive * > ( c ) ;
2016-10-03 21:33:42 +02:00
_set_texture_rect_mode ( false ) ;
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( primitive - > points . size ( ) < 1 ) ;
2016-10-03 21:33:42 +02:00
2017-06-18 04:26:49 +02:00
RasterizerStorageGLES3 : : Texture * texture = _bind_canvas_texture ( primitive - > texture , primitive - > normal_map ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( texture ) {
Size2 texpixel_size ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
2016-10-10 23:31:01 +02:00
}
2017-03-05 16:44:50 +01:00
if ( primitive - > colors . size ( ) = = 1 & & primitive - > points . size ( ) > 1 ) {
2016-10-03 21:33:42 +02:00
2019-02-12 21:10:08 +01:00
Color col = primitive - > colors [ 0 ] ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , col . r , col . g , col . b , col . a ) ;
2016-10-03 21:33:42 +02:00
} else if ( primitive - > colors . empty ( ) ) {
2017-03-05 16:44:50 +01:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
_draw_gui_primitive ( primitive - > points . size ( ) , primitive - > points . ptr ( ) , primitive - > colors . ptr ( ) , primitive - > uvs . ptr ( ) ) ;
2016-10-03 21:33:42 +02:00
} break ;
case Item : : Command : : TYPE_POLYGON : {
2017-03-05 16:44:50 +01:00
Item : : CommandPolygon * polygon = static_cast < Item : : CommandPolygon * > ( c ) ;
2016-10-03 21:33:42 +02:00
_set_texture_rect_mode ( false ) ;
2016-10-10 23:31:01 +02:00
2017-06-18 04:26:49 +02:00
RasterizerStorageGLES3 : : Texture * texture = _bind_canvas_texture ( polygon - > texture , polygon - > normal_map ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
if ( texture ) {
Size2 texpixel_size ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
2016-10-10 23:31:01 +02:00
}
2018-05-03 22:29:15 +02:00
_draw_polygon ( polygon - > indices . ptr ( ) , polygon - > count , polygon - > points . size ( ) , polygon - > points . ptr ( ) , polygon - > uvs . ptr ( ) , polygon - > colors . ptr ( ) , polygon - > colors . size ( ) = = 1 , polygon - > bones . ptr ( ) , polygon - > weights . ptr ( ) ) ;
2017-08-19 18:14:04 +02:00
# ifdef GLES_OVER_GL
if ( polygon - > antialiased ) {
glEnable ( GL_LINE_SMOOTH ) ;
2020-01-01 11:39:07 +01:00
if ( polygon - > antialiasing_use_indices ) {
_draw_generic_indices ( GL_LINE_STRIP , polygon - > indices . ptr ( ) , polygon - > count , polygon - > points . size ( ) , polygon - > points . ptr ( ) , polygon - > uvs . ptr ( ) , polygon - > colors . ptr ( ) , polygon - > colors . size ( ) = = 1 ) ;
} else {
_draw_generic ( GL_LINE_LOOP , polygon - > points . size ( ) , polygon - > points . ptr ( ) , polygon - > uvs . ptr ( ) , polygon - > colors . ptr ( ) , polygon - > colors . size ( ) = = 1 ) ;
}
2017-08-19 18:14:04 +02:00
glDisable ( GL_LINE_SMOOTH ) ;
}
# endif
2016-10-03 21:33:42 +02:00
2017-06-21 21:25:45 +02:00
} break ;
2018-02-21 13:38:21 +01:00
case Item : : Command : : TYPE_MESH : {
Item : : CommandMesh * mesh = static_cast < Item : : CommandMesh * > ( c ) ;
_set_texture_rect_mode ( false ) ;
RasterizerStorageGLES3 : : Texture * texture = _bind_canvas_texture ( mesh - > texture , mesh - > normal_map ) ;
if ( texture ) {
Size2 texpixel_size ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
}
2019-04-19 20:54:33 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , state . final_transform * mesh - > transform ) ;
2018-02-21 13:38:21 +01:00
RasterizerStorageGLES3 : : Mesh * mesh_data = storage - > mesh_owner . getornull ( mesh - > mesh ) ;
if ( mesh_data ) {
for ( int j = 0 ; j < mesh_data - > surfaces . size ( ) ; j + + ) {
RasterizerStorageGLES3 : : Surface * s = mesh_data - > surfaces [ j ] ;
// materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing
glBindVertexArray ( s - > array_id ) ;
2019-04-19 20:54:33 +02:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , mesh - > modulate . r , mesh - > modulate . g , mesh - > modulate . b , mesh - > modulate . a ) ;
2019-03-07 17:54:03 +01:00
2018-02-21 13:38:21 +01:00
if ( s - > index_array_len ) {
glDrawElements ( gl_primitive [ s - > primitive ] , s - > index_array_len , ( s - > array_len > = ( 1 < < 16 ) ) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT , 0 ) ;
} else {
glDrawArrays ( gl_primitive [ s - > primitive ] , 0 , s - > array_len ) ;
}
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2018-02-21 13:38:21 +01:00
glBindVertexArray ( 0 ) ;
}
}
2019-04-19 20:54:33 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , state . final_transform ) ;
2018-02-21 13:38:21 +01:00
} break ;
2018-08-29 21:48:32 +02:00
case Item : : Command : : TYPE_MULTIMESH : {
Item : : CommandMultiMesh * mmesh = static_cast < Item : : CommandMultiMesh * > ( c ) ;
RasterizerStorageGLES3 : : MultiMesh * multi_mesh = storage - > multimesh_owner . getornull ( mmesh - > multimesh ) ;
if ( ! multi_mesh )
break ;
RasterizerStorageGLES3 : : Mesh * mesh_data = storage - > mesh_owner . getornull ( multi_mesh - > mesh ) ;
if ( ! mesh_data )
break ;
RasterizerStorageGLES3 : : Texture * texture = _bind_canvas_texture ( mmesh - > texture , mmesh - > normal_map ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCE_CUSTOM , multi_mesh - > custom_data_format ! = VS : : MULTIMESH_CUSTOM_DATA_NONE ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCING , true ) ;
//reset shader and force rebind
state . using_texture_rect = true ;
_set_texture_rect_mode ( false ) ;
if ( texture ) {
Size2 texpixel_size ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
}
2018-12-28 00:39:00 +01:00
int amount = MIN ( multi_mesh - > size , multi_mesh - > visible_instances ) ;
if ( amount = = - 1 ) {
amount = multi_mesh - > size ;
}
2018-08-29 21:48:32 +02:00
for ( int j = 0 ; j < mesh_data - > surfaces . size ( ) ; j + + ) {
RasterizerStorageGLES3 : : Surface * s = mesh_data - > surfaces [ j ] ;
// materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing
glBindVertexArray ( s - > instancing_array_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , multi_mesh - > buffer ) ; //modify the buffer
int stride = ( multi_mesh - > xform_floats + multi_mesh - > color_floats + multi_mesh - > custom_data_floats ) * 4 ;
glEnableVertexAttribArray ( 8 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( 0 ) ) ;
2018-08-29 21:48:32 +02:00
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( 4 * 4 ) ) ;
2018-08-29 21:48:32 +02:00
glVertexAttribDivisor ( 9 , 1 ) ;
int color_ofs ;
if ( multi_mesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_3D ) {
glEnableVertexAttribArray ( 10 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( 8 * 4 ) ) ;
2018-08-29 21:48:32 +02:00
glVertexAttribDivisor ( 10 , 1 ) ;
color_ofs = 12 * 4 ;
} else {
glDisableVertexAttribArray ( 10 ) ;
glVertexAttrib4f ( 10 , 0 , 0 , 1 , 0 ) ;
color_ofs = 8 * 4 ;
}
int custom_data_ofs = color_ofs ;
switch ( multi_mesh - > color_format ) {
2020-01-16 19:58:45 +01:00
case VS : : MULTIMESH_COLOR_MAX :
2018-08-29 21:48:32 +02:00
case VS : : MULTIMESH_COLOR_NONE : {
glDisableVertexAttribArray ( 11 ) ;
glVertexAttrib4f ( 11 , 1 , 1 , 1 , 1 ) ;
} break ;
case VS : : MULTIMESH_COLOR_8BIT : {
glEnableVertexAttribArray ( 11 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 11 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , stride , CAST_INT_TO_UCHAR_PTR ( color_ofs ) ) ;
2018-08-29 21:48:32 +02:00
glVertexAttribDivisor ( 11 , 1 ) ;
custom_data_ofs + = 4 ;
} break ;
case VS : : MULTIMESH_COLOR_FLOAT : {
glEnableVertexAttribArray ( 11 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( color_ofs ) ) ;
2018-08-29 21:48:32 +02:00
glVertexAttribDivisor ( 11 , 1 ) ;
custom_data_ofs + = 4 * 4 ;
} break ;
}
switch ( multi_mesh - > custom_data_format ) {
2020-01-16 19:58:45 +01:00
case VS : : MULTIMESH_CUSTOM_DATA_MAX :
2018-08-29 21:48:32 +02:00
case VS : : MULTIMESH_CUSTOM_DATA_NONE : {
glDisableVertexAttribArray ( 12 ) ;
glVertexAttrib4f ( 12 , 1 , 1 , 1 , 1 ) ;
} break ;
case VS : : MULTIMESH_CUSTOM_DATA_8BIT : {
glEnableVertexAttribArray ( 12 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 12 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , stride , CAST_INT_TO_UCHAR_PTR ( custom_data_ofs ) ) ;
2018-08-29 21:48:32 +02:00
glVertexAttribDivisor ( 12 , 1 ) ;
} break ;
case VS : : MULTIMESH_CUSTOM_DATA_FLOAT : {
glEnableVertexAttribArray ( 12 ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( custom_data_ofs ) ) ;
2018-08-29 21:48:32 +02:00
glVertexAttribDivisor ( 12 , 1 ) ;
} break ;
}
if ( s - > index_array_len ) {
glDrawElementsInstanced ( gl_primitive [ s - > primitive ] , s - > index_array_len , ( s - > array_len > = ( 1 < < 16 ) ) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT , 0 , amount ) ;
} else {
glDrawArraysInstanced ( gl_primitive [ s - > primitive ] , 0 , s - > array_len , amount ) ;
}
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2018-08-29 21:48:32 +02:00
glBindVertexArray ( 0 ) ;
}
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCE_CUSTOM , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCING , false ) ;
state . using_texture_rect = true ;
_set_texture_rect_mode ( false ) ;
} break ;
2017-06-21 21:25:45 +02:00
case Item : : Command : : TYPE_PARTICLES : {
Item : : CommandParticles * particles_cmd = static_cast < Item : : CommandParticles * > ( c ) ;
RasterizerStorageGLES3 : : Particles * particles = storage - > particles_owner . getornull ( particles_cmd - > particles ) ;
if ( ! particles )
break ;
2018-06-20 22:44:11 +02:00
if ( particles - > inactive & & ! particles - > emitting )
break ;
2017-06-21 21:25:45 +02:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ; //not used, so keep white
VisualServerRaster : : redraw_request ( ) ;
storage - > particles_request_process ( particles_cmd - > particles ) ;
//enable instancing
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCE_CUSTOM , true ) ;
2018-11-13 18:19:16 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_PARTICLES , true ) ;
2017-06-21 21:25:45 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCING , true ) ;
//reset shader and force rebind
state . using_texture_rect = true ;
_set_texture_rect_mode ( false ) ;
RasterizerStorageGLES3 : : Texture * texture = _bind_canvas_texture ( particles_cmd - > texture , particles_cmd - > normal_map ) ;
if ( texture ) {
2018-09-27 13:05:57 +02:00
Size2 texpixel_size ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
2017-06-21 21:25:45 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
2018-11-13 18:19:16 +01:00
} else {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , Vector2 ( 1.0 , 1.0 ) ) ;
2017-06-21 21:25:45 +02:00
}
if ( ! particles - > use_local_coords ) {
Transform2D inv_xf ;
inv_xf . set_axis ( 0 , Vector2 ( particles - > emission_transform . basis . get_axis ( 0 ) . x , particles - > emission_transform . basis . get_axis ( 0 ) . y ) ) ;
inv_xf . set_axis ( 1 , Vector2 ( particles - > emission_transform . basis . get_axis ( 1 ) . x , particles - > emission_transform . basis . get_axis ( 1 ) . y ) ) ;
inv_xf . set_origin ( Vector2 ( particles - > emission_transform . get_origin ( ) . x , particles - > emission_transform . get_origin ( ) . y ) ) ;
inv_xf . affine_invert ( ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , state . final_transform * inv_xf ) ;
}
glBindVertexArray ( data . particle_quad_array ) ; //use particle quad array
glBindBuffer ( GL_ARRAY_BUFFER , particles - > particle_buffers [ 0 ] ) ; //bind particle buffer
int stride = sizeof ( float ) * 4 * 6 ;
int amount = particles - > amount ;
if ( particles - > draw_order ! = VS : : PARTICLES_DRAW_ORDER_LIFETIME ) {
glEnableVertexAttribArray ( 8 ) ; //xform x
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 3 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ; //xform y
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 4 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 9 , 1 ) ;
glEnableVertexAttribArray ( 10 ) ; //xform z
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 5 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 10 , 1 ) ;
glEnableVertexAttribArray ( 11 ) ; //color
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , NULL ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 11 , 1 ) ;
glEnableVertexAttribArray ( 12 ) ; //custom
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 2 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 12 , 1 ) ;
glDrawArraysInstanced ( GL_TRIANGLE_FAN , 0 , 4 , amount ) ;
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2017-06-21 21:25:45 +02:00
} else {
//split
int split = int ( Math : : ceil ( particles - > phase * particles - > amount ) ) ;
if ( amount - split > 0 ) {
glEnableVertexAttribArray ( 8 ) ; //xform x
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( stride * split + sizeof ( float ) * 4 * 3 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ; //xform y
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( stride * split + sizeof ( float ) * 4 * 4 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 9 , 1 ) ;
glEnableVertexAttribArray ( 10 ) ; //xform z
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( stride * split + sizeof ( float ) * 4 * 5 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 10 , 1 ) ;
glEnableVertexAttribArray ( 11 ) ; //color
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( stride * split + 0 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 11 , 1 ) ;
glEnableVertexAttribArray ( 12 ) ; //custom
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( stride * split + sizeof ( float ) * 4 * 2 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 12 , 1 ) ;
glDrawArraysInstanced ( GL_TRIANGLE_FAN , 0 , 4 , amount - split ) ;
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2017-06-21 21:25:45 +02:00
}
if ( split > 0 ) {
glEnableVertexAttribArray ( 8 ) ; //xform x
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 3 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ; //xform y
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 4 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 9 , 1 ) ;
glEnableVertexAttribArray ( 10 ) ; //xform z
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 5 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 10 , 1 ) ;
glEnableVertexAttribArray ( 11 ) ; //color
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , NULL ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 11 , 1 ) ;
glEnableVertexAttribArray ( 12 ) ; //custom
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( sizeof ( float ) * 4 * 2 ) ) ;
2017-06-21 21:25:45 +02:00
glVertexAttribDivisor ( 12 , 1 ) ;
glDrawArraysInstanced ( GL_TRIANGLE_FAN , 0 , 4 , split ) ;
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_draw_call_count + + ;
2017-06-21 21:25:45 +02:00
}
}
glBindVertexArray ( 0 ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCE_CUSTOM , false ) ;
2018-11-13 18:19:16 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_PARTICLES , false ) ;
2017-06-21 21:25:45 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCING , false ) ;
state . using_texture_rect = true ;
_set_texture_rect_mode ( false ) ;
2016-10-03 21:33:42 +02:00
} break ;
case Item : : Command : : TYPE_CIRCLE : {
_set_texture_rect_mode ( false ) ;
2017-03-05 16:44:50 +01:00
Item : : CommandCircle * circle = static_cast < Item : : CommandCircle * > ( c ) ;
static const int numpoints = 32 ;
Vector2 points [ numpoints + 1 ] ;
points [ numpoints ] = circle - > pos ;
int indices [ numpoints * 3 ] ;
2016-10-03 21:33:42 +02:00
2019-02-12 21:10:08 +01:00
for ( int j = 0 ; j < numpoints ; j + + ) {
2016-10-03 21:33:42 +02:00
2019-02-12 21:10:08 +01:00
points [ j ] = circle - > pos + Vector2 ( Math : : sin ( j * Math_PI * 2.0 / numpoints ) , Math : : cos ( j * Math_PI * 2.0 / numpoints ) ) * circle - > radius ;
indices [ j * 3 + 0 ] = j ;
indices [ j * 3 + 1 ] = ( j + 1 ) % numpoints ;
indices [ j * 3 + 2 ] = numpoints ;
2016-10-03 21:33:42 +02:00
}
2017-06-12 23:56:16 +02:00
2017-06-18 04:26:49 +02:00
_bind_canvas_texture ( RID ( ) , RID ( ) ) ;
2018-05-03 22:29:15 +02:00
_draw_polygon ( indices , numpoints * 3 , numpoints + 1 , points , NULL , & circle - > color , true , NULL , NULL ) ;
2017-06-12 23:56:16 +02:00
2017-02-13 02:51:16 +01:00
//_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true);
2016-10-03 21:33:42 +02:00
//canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1);
} break ;
case Item : : Command : : TYPE_TRANSFORM : {
2017-03-05 16:44:50 +01:00
Item : : CommandTransform * transform = static_cast < Item : : CommandTransform * > ( c ) ;
state . extra_matrix = transform - > xform ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : EXTRA_MATRIX , state . extra_matrix ) ;
2016-10-03 21:33:42 +02:00
} break ;
case Item : : Command : : TYPE_CLIP_IGNORE : {
2017-03-05 16:44:50 +01:00
Item : : CommandClipIgnore * ci = static_cast < Item : : CommandClipIgnore * > ( c ) ;
2016-10-03 21:33:42 +02:00
if ( current_clip ) {
2017-03-05 16:44:50 +01:00
if ( ci - > ignore ! = reclip ) {
2016-10-03 21:33:42 +02:00
if ( ci - > ignore ) {
glDisable ( GL_SCISSOR_TEST ) ;
2017-03-05 16:44:50 +01:00
reclip = true ;
} else {
2016-10-03 21:33:42 +02:00
glEnable ( GL_SCISSOR_TEST ) ;
//glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),
//current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height);
2017-06-04 00:25:13 +02:00
int y = storage - > frame . current_rt - > height - ( current_clip - > final_clip_rect . position . y + current_clip - > final_clip_rect . size . y ) ;
2018-06-16 22:55:21 +02:00
if ( storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_VFLIP ] )
y = current_clip - > final_clip_rect . position . y ;
2016-10-03 21:33:42 +02:00
2018-06-16 22:55:21 +02:00
glScissor ( current_clip - > final_clip_rect . position . x , y , current_clip - > final_clip_rect . size . x , current_clip - > final_clip_rect . size . y ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
reclip = false ;
2016-10-03 21:33:42 +02:00
}
}
}
} break ;
}
}
}
2017-06-27 03:58:03 +02:00
void RasterizerCanvasGLES3 : : _copy_texscreen ( const Rect2 & p_rect ) {
2019-08-15 04:57:49 +02:00
ERR_FAIL_COND_MSG ( storage - > frame . current_rt - > effects . mip_maps [ 0 ] . sizes . size ( ) = = 0 , " Can't use screen texture copying in a render target configured without copy buffers. " ) ;
2019-01-15 19:13:58 +01:00
2017-08-07 23:06:57 +02:00
glDisable ( GL_BLEND ) ;
2017-06-27 03:58:03 +02:00
state . canvas_texscreen_used = true ;
//blur diffuse into effect mipmaps using separatable convolution
//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
Vector2 wh ( storage - > frame . current_rt - > width , storage - > frame . current_rt - > height ) ;
Color blur_section ( p_rect . position . x / wh . x , p_rect . position . y / wh . y , p_rect . size . x / wh . x , p_rect . size . y / wh . y ) ;
if ( p_rect ! = Rect2 ( ) ) {
scene_render - > state . effect_blur_shader . set_conditional ( EffectBlurShaderGLES3 : : USE_BLUR_SECTION , true ) ;
storage - > shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_COPY_SECTION , true ) ;
}
glBindFramebuffer ( GL_FRAMEBUFFER , storage - > frame . current_rt - > effects . mip_maps [ 0 ] . sizes [ 0 ] . fbo ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > frame . current_rt - > color ) ;
storage - > shaders . copy . bind ( ) ;
storage - > shaders . copy . set_uniform ( CopyShaderGLES3 : : COPY_SECTION , blur_section ) ;
scene_render - > _copy_screen ( ) ;
for ( int i = 0 ; i < storage - > frame . current_rt - > effects . mip_maps [ 1 ] . sizes . size ( ) ; i + + ) {
int vp_w = storage - > frame . current_rt - > effects . mip_maps [ 1 ] . sizes [ i ] . width ;
int vp_h = storage - > frame . current_rt - > effects . mip_maps [ 1 ] . sizes [ i ] . height ;
glViewport ( 0 , 0 , vp_w , vp_h ) ;
//horizontal pass
scene_render - > state . effect_blur_shader . set_conditional ( EffectBlurShaderGLES3 : : GAUSSIAN_HORIZONTAL , true ) ;
scene_render - > state . effect_blur_shader . bind ( ) ;
scene_render - > state . effect_blur_shader . set_uniform ( EffectBlurShaderGLES3 : : PIXEL_SIZE , Vector2 ( 1.0 / vp_w , 1.0 / vp_h ) ) ;
scene_render - > state . effect_blur_shader . set_uniform ( EffectBlurShaderGLES3 : : LOD , float ( i ) ) ;
scene_render - > state . effect_blur_shader . set_uniform ( EffectBlurShaderGLES3 : : BLUR_SECTION , blur_section ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > frame . current_rt - > effects . mip_maps [ 0 ] . color ) ; //previous level, since mipmaps[0] starts one level bigger
glBindFramebuffer ( GL_FRAMEBUFFER , storage - > frame . current_rt - > effects . mip_maps [ 1 ] . sizes [ i ] . fbo ) ;
scene_render - > _copy_screen ( ) ;
scene_render - > state . effect_blur_shader . set_conditional ( EffectBlurShaderGLES3 : : GAUSSIAN_HORIZONTAL , false ) ;
//vertical pass
scene_render - > state . effect_blur_shader . set_conditional ( EffectBlurShaderGLES3 : : GAUSSIAN_VERTICAL , true ) ;
scene_render - > state . effect_blur_shader . bind ( ) ;
scene_render - > state . effect_blur_shader . set_uniform ( EffectBlurShaderGLES3 : : PIXEL_SIZE , Vector2 ( 1.0 / vp_w , 1.0 / vp_h ) ) ;
scene_render - > state . effect_blur_shader . set_uniform ( EffectBlurShaderGLES3 : : LOD , float ( i ) ) ;
scene_render - > state . effect_blur_shader . set_uniform ( EffectBlurShaderGLES3 : : BLUR_SECTION , blur_section ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > frame . current_rt - > effects . mip_maps [ 1 ] . color ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , storage - > frame . current_rt - > effects . mip_maps [ 0 ] . sizes [ i + 1 ] . fbo ) ; //next level, since mipmaps[0] starts one level bigger
scene_render - > _copy_screen ( ) ;
scene_render - > state . effect_blur_shader . set_conditional ( EffectBlurShaderGLES3 : : GAUSSIAN_VERTICAL , false ) ;
}
scene_render - > state . effect_blur_shader . set_conditional ( EffectBlurShaderGLES3 : : USE_BLUR_SECTION , false ) ;
storage - > shaders . copy . set_conditional ( CopyShaderGLES3 : : USE_COPY_SECTION , false ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , storage - > frame . current_rt - > fbo ) ; //back to front
glViewport ( 0 , 0 , storage - > frame . current_rt - > width , storage - > frame . current_rt - > height ) ;
2017-08-07 23:06:57 +02:00
2018-02-19 20:52:47 +01:00
// back to canvas, force rebind
state . using_texture_rect = true ;
_set_texture_rect_mode ( false ) ;
2017-06-27 03:58:03 +02:00
2018-05-15 13:35:46 +02:00
_bind_canvas_texture ( state . current_tex , state . current_normal , true ) ;
2017-08-07 23:06:57 +02:00
glEnable ( GL_BLEND ) ;
2017-06-27 03:58:03 +02:00
}
2018-02-21 21:23:27 +01:00
void RasterizerCanvasGLES3 : : canvas_render_items ( Item * p_item_list , int p_z , const Color & p_modulate , Light * p_light , const Transform2D & p_transform ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Item * current_clip = NULL ;
RasterizerStorageGLES3 : : Shader * shader_cache = NULL ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
bool rebind_shader = true ;
2016-10-03 21:33:42 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , state . canvas_item_ubo ) ;
glBufferData ( GL_UNIFORM_BUFFER , sizeof ( CanvasItemUBO ) , & state . canvas_item_ubo_data , GL_DYNAMIC_DRAW ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
2017-03-05 16:44:50 +01:00
state . current_tex = RID ( ) ;
state . current_tex_ptr = NULL ;
2017-06-18 04:26:49 +02:00
state . current_normal = RID ( ) ;
2016-10-03 21:33:42 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . white_tex ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
int last_blend_mode = - 1 ;
2016-10-10 23:31:01 +02:00
2016-10-03 21:33:42 +02:00
RID canvas_last_material ;
2017-03-05 16:44:50 +01:00
bool prev_distance_field = false ;
2018-05-03 22:29:15 +02:00
bool prev_use_skeleton = false ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
while ( p_item_list ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Item * ci = p_item_list ;
2020-05-07 11:16:07 +02:00
storage - > info . render . _2d_item_count + + ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( prev_distance_field ! = ci - > distance_field ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_DISTANCE_FIELD , ci - > distance_field ) ;
prev_distance_field = ci - > distance_field ;
rebind_shader = true ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
if ( current_clip ! = ci - > final_clip_owner ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
current_clip = ci - > final_clip_owner ;
2016-10-03 21:33:42 +02:00
//setup clip
if ( current_clip ) {
glEnable ( GL_SCISSOR_TEST ) ;
2018-06-16 22:55:21 +02:00
int y = storage - > frame . current_rt - > height - ( current_clip - > final_clip_rect . position . y + current_clip - > final_clip_rect . size . y ) ;
if ( storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_VFLIP ] )
y = current_clip - > final_clip_rect . position . y ;
glScissor ( current_clip - > final_clip_rect . position . x , y , current_clip - > final_clip_rect . size . x , current_clip - > final_clip_rect . size . y ) ;
2016-10-03 21:33:42 +02:00
} else {
glDisable ( GL_SCISSOR_TEST ) ;
}
}
2017-06-27 03:58:03 +02:00
if ( ci - > copy_back_buffer ) {
2016-10-03 21:33:42 +02:00
if ( ci - > copy_back_buffer - > full ) {
2017-06-27 03:58:03 +02:00
_copy_texscreen ( Rect2 ( ) ) ;
2016-10-03 21:33:42 +02:00
} else {
2017-06-27 03:58:03 +02:00
_copy_texscreen ( ci - > copy_back_buffer - > rect ) ;
2016-10-03 21:33:42 +02:00
}
}
2018-05-03 22:29:15 +02:00
RasterizerStorageGLES3 : : Skeleton * skeleton = NULL ;
{
//skeleton handling
2018-08-24 15:15:16 +02:00
if ( ci - > skeleton . is_valid ( ) & & storage - > skeleton_owner . owns ( ci - > skeleton ) ) {
skeleton = storage - > skeleton_owner . get ( ci - > skeleton ) ;
2018-05-03 22:29:15 +02:00
if ( ! skeleton - > use_2d ) {
skeleton = NULL ;
} else {
2018-05-04 14:32:40 +02:00
state . skeleton_transform = p_transform * skeleton - > base_transform_2d ;
state . skeleton_transform_inverse = state . skeleton_transform . affine_inverse ( ) ;
2018-05-03 22:29:15 +02:00
}
}
bool use_skeleton = skeleton ! = NULL ;
if ( prev_use_skeleton ! = use_skeleton ) {
rebind_shader = true ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_SKELETON , use_skeleton ) ;
prev_use_skeleton = use_skeleton ;
}
if ( skeleton ) {
2019-12-23 01:00:18 +01:00
glActiveTexture ( GL_TEXTURE0 + storage - > config . max_texture_image_units - 4 ) ;
2018-05-03 22:29:15 +02:00
glBindTexture ( GL_TEXTURE_2D , skeleton - > texture ) ;
state . using_skeleton = true ;
} else {
state . using_skeleton = false ;
}
}
2016-10-03 21:33:42 +02:00
//begin rect
2017-03-05 16:44:50 +01:00
Item * material_owner = ci - > material_owner ? ci - > material_owner : ci ;
2016-10-03 21:33:42 +02:00
RID material = material_owner - > material ;
2017-03-05 16:44:50 +01:00
if ( material ! = canvas_last_material | | rebind_shader ) {
2016-10-10 23:31:01 +02:00
RasterizerStorageGLES3 : : Material * material_ptr = storage - > material_owner . getornull ( material ) ;
RasterizerStorageGLES3 : : Shader * shader_ptr = NULL ;
if ( material_ptr ) {
shader_ptr = material_ptr - > shader ;
2017-03-05 16:44:50 +01:00
if ( shader_ptr & & shader_ptr - > mode ! = VS : : SHADER_CANVAS_ITEM ) {
shader_ptr = NULL ; //do not use non canvasitem shader
2016-10-03 21:33:42 +02:00
}
}
2017-12-26 19:13:00 +01:00
if ( shader_ptr ) {
2016-10-10 23:31:01 +02:00
2017-06-27 03:58:03 +02:00
if ( shader_ptr - > canvas_item . uses_screen_texture & & ! state . canvas_texscreen_used ) {
//copy if not copied before
_copy_texscreen ( Rect2 ( ) ) ;
2018-05-07 13:24:29 +02:00
// blend mode will have been enabled so make sure we disable it again later on
last_blend_mode = last_blend_mode ! = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_DISABLED ? last_blend_mode : - 1 ;
2017-06-27 03:58:03 +02:00
}
2018-11-18 20:34:20 +01:00
if ( shader_ptr ! = shader_cache | | rebind_shader ) {
2017-12-26 19:13:00 +01:00
if ( shader_ptr - > canvas_item . uses_time ) {
VisualServerRaster : : redraw_request ( ) ;
}
2017-09-05 05:30:39 +02:00
2017-12-26 19:13:00 +01:00
state . canvas_shader . set_custom_shader ( shader_ptr - > custom_code_id ) ;
state . canvas_shader . bind ( ) ;
}
2016-10-10 23:31:01 +02:00
if ( material_ptr - > ubo_id ) {
2017-03-05 16:44:50 +01:00
glBindBufferBase ( GL_UNIFORM_BUFFER , 2 , material_ptr - > ubo_id ) ;
2016-10-10 23:31:01 +02:00
}
int tc = material_ptr - > textures . size ( ) ;
2017-11-25 04:07:54 +01:00
RID * textures = material_ptr - > textures . ptrw ( ) ;
ShaderLanguage : : ShaderNode : : Uniform : : Hint * texture_hints = shader_ptr - > texture_hints . ptrw ( ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < tc ; i + + ) {
2016-10-10 23:31:01 +02:00
2017-06-18 04:26:49 +02:00
glActiveTexture ( GL_TEXTURE2 + i ) ;
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
RasterizerStorageGLES3 : : Texture * t = storage - > texture_owner . getornull ( textures [ i ] ) ;
2016-10-10 23:31:01 +02:00
if ( ! t ) {
2016-10-30 01:48:09 +02:00
2017-03-05 16:44:50 +01:00
switch ( texture_hints [ i ] ) {
2016-11-21 02:49:53 +01:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_BLACK_ALBEDO :
2016-10-30 01:48:09 +02:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_BLACK : {
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
2016-10-30 01:48:09 +02:00
} break ;
2016-11-21 02:49:53 +01:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_ANISO : {
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . aniso_tex ) ;
2016-11-21 02:49:53 +01:00
} break ;
2016-10-30 01:48:09 +02:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_NORMAL : {
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . normal_tex ) ;
2016-10-30 01:48:09 +02:00
} break ;
default : {
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . white_tex ) ;
2016-10-30 01:48:09 +02:00
} break ;
}
2016-10-10 23:31:01 +02:00
//check hints
2016-10-30 01:48:09 +02:00
2016-10-10 23:31:01 +02:00
continue ;
}
2018-07-16 16:43:26 +02:00
if ( t - > redraw_if_visible ) { //check before proxy, because this is usually used with proxies
VisualServerRaster : : redraw_request ( ) ;
}
2019-03-03 17:43:54 +01:00
t = t - > get_ptr ( ) ;
2016-10-30 01:48:09 +02:00
if ( storage - > config . srgb_decode_supported & & t - > using_srgb ) {
//no srgb in 2D
2017-03-05 16:44:50 +01:00
glTexParameteri ( t - > target , _TEXTURE_SRGB_DECODE_EXT , _SKIP_DECODE_EXT ) ;
t - > using_srgb = false ;
2016-10-30 01:48:09 +02:00
}
2017-03-05 16:44:50 +01:00
glBindTexture ( t - > target , t - > tex_id ) ;
2016-10-10 23:31:01 +02:00
}
2017-12-26 19:56:18 +01:00
} else {
2016-10-10 23:31:01 +02:00
state . canvas_shader . set_custom_shader ( 0 ) ;
state . canvas_shader . bind ( ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
shader_cache = shader_ptr ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
canvas_last_material = material ;
rebind_shader = false ;
2016-10-03 21:33:42 +02:00
}
2016-10-10 23:31:01 +02:00
int blend_mode = shader_cache ? shader_cache - > canvas_item . blend_mode : RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_MIX ;
2018-05-07 13:24:29 +02:00
if ( blend_mode = = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_DISABLED & & ( ! storage - > frame . current_rt | | ! storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) ) {
blend_mode = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_MIX ;
}
2018-09-08 03:40:06 +02:00
bool unshaded = shader_cache & & ( shader_cache - > canvas_item . light_mode = = RasterizerStorageGLES3 : : Shader : : CanvasItem : : LIGHT_MODE_UNSHADED | | ( blend_mode ! = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_MIX & & blend_mode ! = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_PMALPHA ) ) ;
2017-03-05 16:44:50 +01:00
bool reclip = false ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( last_blend_mode ! = blend_mode ) {
2018-05-07 13:24:29 +02:00
if ( last_blend_mode = = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_DISABLED ) {
// re-enable it
glEnable ( GL_BLEND ) ;
} else if ( blend_mode = = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_DISABLED ) {
// disable it
glDisable ( GL_BLEND ) ;
}
2016-10-10 23:31:01 +02:00
2017-03-05 16:44:50 +01:00
switch ( blend_mode ) {
2016-10-03 21:33:42 +02:00
2018-05-07 13:24:29 +02:00
case RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_DISABLED : {
// nothing to do here
} break ;
2017-03-05 16:44:50 +01:00
case RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_MIX : {
2018-05-07 13:24:29 +02:00
2016-10-03 21:33:42 +02:00
glBlendEquation ( GL_FUNC_ADD ) ;
2016-10-10 23:31:01 +02:00
if ( storage - > frame . current_rt & & storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) {
2016-10-03 21:33:42 +02:00
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA , GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
2017-03-05 16:44:50 +01:00
} else {
2018-01-11 23:38:03 +01:00
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA , GL_ZERO , GL_ONE ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
} break ;
case RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_ADD : {
2016-10-03 21:33:42 +02:00
glBlendEquation ( GL_FUNC_ADD ) ;
2018-01-11 23:38:03 +01:00
if ( storage - > frame . current_rt & & storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) {
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE , GL_SRC_ALPHA , GL_ONE ) ;
} else {
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE , GL_ZERO , GL_ONE ) ;
}
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
} break ;
case RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_SUB : {
2016-10-03 21:33:42 +02:00
glBlendEquation ( GL_FUNC_REVERSE_SUBTRACT ) ;
2018-01-11 23:38:03 +01:00
if ( storage - > frame . current_rt & & storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) {
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE , GL_SRC_ALPHA , GL_ONE ) ;
} else {
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE , GL_ZERO , GL_ONE ) ;
}
2017-03-05 16:44:50 +01:00
} break ;
2016-10-10 23:31:01 +02:00
case RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_MUL : {
2016-10-03 21:33:42 +02:00
glBlendEquation ( GL_FUNC_ADD ) ;
2018-01-11 23:38:03 +01:00
if ( storage - > frame . current_rt & & storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) {
glBlendFuncSeparate ( GL_DST_COLOR , GL_ZERO , GL_DST_ALPHA , GL_ZERO ) ;
} else {
glBlendFuncSeparate ( GL_DST_COLOR , GL_ZERO , GL_ZERO , GL_ONE ) ;
}
2016-10-03 21:33:42 +02:00
} break ;
2016-10-10 23:31:01 +02:00
case RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_PMALPHA : {
2016-10-03 21:33:42 +02:00
glBlendEquation ( GL_FUNC_ADD ) ;
2018-01-11 23:38:03 +01:00
if ( storage - > frame . current_rt & & storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) {
glBlendFuncSeparate ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA , GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
} else {
glBlendFuncSeparate ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA , GL_ZERO , GL_ONE ) ;
}
2016-10-03 21:33:42 +02:00
} break ;
}
2017-03-05 16:44:50 +01:00
last_blend_mode = blend_mode ;
2016-10-03 21:33:42 +02:00
}
2017-08-18 12:57:03 +02:00
state . canvas_item_modulate = unshaded ? ci - > final_modulate : Color ( ci - > final_modulate . r * p_modulate . r , ci - > final_modulate . g * p_modulate . g , ci - > final_modulate . b * p_modulate . b , ci - > final_modulate . a * p_modulate . a ) ;
2016-10-03 21:33:42 +02:00
state . final_transform = ci - > final_transform ;
2017-03-05 16:44:50 +01:00
state . extra_matrix = Transform2D ( ) ;
2016-10-03 21:33:42 +02:00
2019-12-23 19:40:48 +01:00
if ( state . using_skeleton ) {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SKELETON_TRANSFORM , state . skeleton_transform ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SKELETON_TRANSFORM_INVERSE , state . skeleton_transform_inverse ) ;
}
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : FINAL_MODULATE , state . canvas_item_modulate ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , state . final_transform ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : EXTRA_MATRIX , state . extra_matrix ) ;
2017-06-27 03:58:03 +02:00
if ( storage - > frame . current_rt ) {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 / storage - > frame . current_rt - > width , 1.0 / storage - > frame . current_rt - > height ) ) ;
} else {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 , 1.0 ) ) ;
}
2017-03-05 16:44:50 +01:00
if ( unshaded | | ( state . canvas_item_modulate . a > 0.001 & & ( ! shader_cache | | shader_cache - > canvas_item . light_mode ! = RasterizerStorageGLES3 : : Shader : : CanvasItem : : LIGHT_MODE_LIGHT_ONLY ) & & ! ci - > light_masked ) )
_canvas_item_render_commands ( ci , current_clip , reclip ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( ( blend_mode = = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_MIX | | blend_mode = = RasterizerStorageGLES3 : : Shader : : CanvasItem : : BLEND_MODE_PMALPHA ) & & p_light & & ! unshaded ) {
2016-10-03 21:33:42 +02:00
Light * light = p_light ;
2017-03-05 16:44:50 +01:00
bool light_used = false ;
VS : : CanvasLightMode mode = VS : : CANVAS_LIGHT_MODE_ADD ;
state . canvas_item_modulate = ci - > final_modulate ; // remove the canvas modulate
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
while ( light ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( ci - > light_mask & light - > item_mask & & p_z > = light - > z_min & & p_z < = light - > z_max & & ci - > global_rect_cache . intersects_transformed ( light - > xform_cache , light - > rect_cache ) ) {
2016-10-03 21:33:42 +02:00
//intersects this light
2017-03-05 16:44:50 +01:00
if ( ! light_used | | mode ! = light - > mode ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
mode = light - > mode ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
switch ( mode ) {
2016-10-03 21:33:42 +02:00
case VS : : CANVAS_LIGHT_MODE_ADD : {
glBlendEquation ( GL_FUNC_ADD ) ;
2017-03-05 16:44:50 +01:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE ) ;
2016-10-03 21:33:42 +02:00
} break ;
case VS : : CANVAS_LIGHT_MODE_SUB : {
glBlendEquation ( GL_FUNC_REVERSE_SUBTRACT ) ;
2017-03-05 16:44:50 +01:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE ) ;
2016-10-03 21:33:42 +02:00
} break ;
case VS : : CANVAS_LIGHT_MODE_MIX :
case VS : : CANVAS_LIGHT_MODE_MASK : {
glBlendEquation ( GL_FUNC_ADD ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
} break ;
}
}
if ( ! light_used ) {
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_LIGHTING , true ) ;
light_used = true ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
bool has_shadow = light - > shadow_buffer . is_valid ( ) & & ci - > light_mask & light - > item_shadow_mask ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_SHADOWS , has_shadow ) ;
2016-10-03 21:33:42 +02:00
if ( has_shadow ) {
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_USE_GRADIENT , light - > shadow_gradient_length > 0 ) ;
2019-01-17 14:40:36 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_NEAREST , light - > shadow_filter = = VS : : CANVAS_LIGHT_FILTER_NONE ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF3 , light - > shadow_filter = = VS : : CANVAS_LIGHT_FILTER_PCF3 ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF5 , light - > shadow_filter = = VS : : CANVAS_LIGHT_FILTER_PCF5 ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF7 , light - > shadow_filter = = VS : : CANVAS_LIGHT_FILTER_PCF7 ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF9 , light - > shadow_filter = = VS : : CANVAS_LIGHT_FILTER_PCF9 ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF13 , light - > shadow_filter = = VS : : CANVAS_LIGHT_FILTER_PCF13 ) ;
2016-10-03 21:33:42 +02:00
}
bool light_rebind = state . canvas_shader . bind ( ) ;
if ( light_rebind ) {
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : FINAL_MODULATE , state . canvas_item_modulate ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , state . final_transform ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : EXTRA_MATRIX , Transform2D ( ) ) ;
2019-07-30 22:32:36 +02:00
if ( storage - > frame . current_rt ) {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 / storage - > frame . current_rt - > width , 1.0 / storage - > frame . current_rt - > height ) ) ;
} else {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SCREEN_PIXEL_SIZE , Vector2 ( 1.0 , 1.0 ) ) ;
}
2019-12-23 01:00:18 +01:00
if ( state . using_skeleton ) {
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SKELETON_TRANSFORM , state . skeleton_transform ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SKELETON_TRANSFORM_INVERSE , state . skeleton_transform_inverse ) ;
}
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
glBindBufferBase ( GL_UNIFORM_BUFFER , 1 , static_cast < LightInternal * > ( light - > light_internal . get_data ( ) ) - > ubo ) ;
2016-10-03 21:33:42 +02:00
if ( has_shadow ) {
RasterizerStorageGLES3 : : CanvasLightShadow * cls = storage - > canvas_light_shadow_owner . get ( light - > shadow_buffer ) ;
2017-03-05 16:44:50 +01:00
glActiveTexture ( GL_TEXTURE0 + storage - > config . max_texture_image_units - 2 ) ;
glBindTexture ( GL_TEXTURE_2D , cls - > distance ) ;
2016-10-03 21:33:42 +02:00
/*canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_MATRIX,light->shadow_matrix_cache);
canvas_shader . set_uniform ( CanvasShaderGLES3 : : SHADOW_ESM_MULTIPLIER , light - > shadow_esm_mult ) ;
canvas_shader . set_uniform ( CanvasShaderGLES3 : : LIGHT_SHADOW_COLOR , light - > shadow_color ) ; */
}
2017-03-05 16:44:50 +01:00
glActiveTexture ( GL_TEXTURE0 + storage - > config . max_texture_image_units - 1 ) ;
2016-10-03 21:33:42 +02:00
RasterizerStorageGLES3 : : Texture * t = storage - > texture_owner . getornull ( light - > texture ) ;
if ( ! t ) {
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . white_tex ) ;
2016-10-03 21:33:42 +02:00
} else {
2018-09-06 22:26:38 +02:00
t = t - > get_ptr ( ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glBindTexture ( t - > target , t - > tex_id ) ;
2016-10-03 21:33:42 +02:00
}
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
_canvas_item_render_commands ( ci , current_clip , reclip ) ; //redraw using light
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
light = light - > next_ptr ;
2016-10-03 21:33:42 +02:00
}
if ( light_used ) {
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_LIGHTING , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_SHADOWS , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_NEAREST , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF3 , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF5 , false ) ;
2017-09-01 15:01:24 +02:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF7 , false ) ;
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF9 , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF13 , false ) ;
2016-10-03 21:33:42 +02:00
state . canvas_shader . bind ( ) ;
2017-03-05 16:44:50 +01:00
last_blend_mode = - 1 ;
2016-10-10 23:31:01 +02:00
/*
//this is set again, so it should not be needed anyway?
2016-10-03 21:33:42 +02:00
state . canvas_item_modulate = unshaded ? ci - > final_modulate : Color (
ci - > final_modulate . r * p_modulate . r ,
ci - > final_modulate . g * p_modulate . g ,
ci - > final_modulate . b * p_modulate . b ,
ci - > final_modulate . a * p_modulate . a ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : MODELVIEW_MATRIX , state . final_transform ) ;
2017-01-13 08:34:32 +01:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : EXTRA_MATRIX , Transform2D ( ) ) ;
2016-10-03 21:33:42 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : FINAL_MODULATE , state . canvas_item_modulate ) ;
glBlendEquation ( GL_FUNC_ADD ) ;
if ( storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) {
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA , GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
} else {
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
}
//@TODO RESET canvas_blend_mode
2016-10-10 23:31:01 +02:00
*/
2016-10-03 21:33:42 +02:00
}
}
if ( reclip ) {
glEnable ( GL_SCISSOR_TEST ) ;
2018-06-16 22:55:21 +02:00
int y = storage - > frame . current_rt - > height - ( current_clip - > final_clip_rect . position . y + current_clip - > final_clip_rect . size . y ) ;
if ( storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_VFLIP ] )
y = current_clip - > final_clip_rect . position . y ;
glScissor ( current_clip - > final_clip_rect . position . x , y , current_clip - > final_clip_rect . size . width , current_clip - > final_clip_rect . size . height ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
p_item_list = p_item_list - > next ;
2016-10-03 21:33:42 +02:00
}
if ( current_clip ) {
glDisable ( GL_SCISSOR_TEST ) ;
}
2018-11-18 20:34:20 +01:00
//disable states that may have been used
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_DISTANCE_FIELD , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_SKELETON , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCE_CUSTOM , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_PARTICLES , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCING , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_LIGHTING , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_SHADOWS , false ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : canvas_debug_viewport_shadows ( Light * p_lights_with_shadow ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Light * light = p_lights_with_shadow ;
2016-10-03 21:33:42 +02:00
canvas_begin ( ) ; //reset
2017-03-05 16:44:50 +01:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
2016-10-03 21:33:42 +02:00
int h = 10 ;
int w = storage - > frame . current_rt - > width ;
int ofs = h ;
glDisable ( GL_BLEND ) ;
2017-03-05 16:44:50 +01:00
while ( light ) {
2016-10-03 21:33:42 +02:00
if ( light - > shadow_buffer . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
RasterizerStorageGLES3 : : CanvasLightShadow * sb = storage - > canvas_light_shadow_owner . get ( light - > shadow_buffer ) ;
2016-10-03 21:33:42 +02:00
if ( sb ) {
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , sb - > distance ) ;
draw_generic_textured_rect ( Rect2 ( h , ofs , w - h * 2 , h ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
ofs + = h * 2 ;
2016-10-03 21:33:42 +02:00
}
}
2017-03-05 16:44:50 +01:00
light = light - > shadows_next_ptr ;
2016-10-03 21:33:42 +02:00
}
2019-02-12 18:33:57 +01:00
canvas_end ( ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : canvas_light_shadow_buffer_update ( RID p_buffer , const Transform2D & p_light_xform , int p_light_mask , float p_near , float p_far , LightOccluderInstance * p_occluders , CameraMatrix * p_xform_cache ) {
2016-10-03 21:33:42 +02:00
RasterizerStorageGLES3 : : CanvasLightShadow * cls = storage - > canvas_light_shadow_owner . get ( p_buffer ) ;
ERR_FAIL_COND ( ! cls ) ;
glDisable ( GL_BLEND ) ;
glDisable ( GL_SCISSOR_TEST ) ;
glDisable ( GL_DITHER ) ;
glDisable ( GL_CULL_FACE ) ;
glDepthFunc ( GL_LEQUAL ) ;
glEnable ( GL_DEPTH_TEST ) ;
glDepthMask ( true ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , cls - > fbo ) ;
state . canvas_shadow_shader . bind ( ) ;
2017-03-05 16:44:50 +01:00
glViewport ( 0 , 0 , cls - > size , cls - > height ) ;
2016-10-03 21:33:42 +02:00
glClearDepth ( 1.0f ) ;
2017-03-05 16:44:50 +01:00
glClearColor ( 1 , 1 , 1 , 1 ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
VS : : CanvasOccluderPolygonCullMode cull = VS : : CANVAS_OCCLUDER_POLYGON_CULL_DISABLED ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
2016-10-03 21:33:42 +02:00
//make sure it remains orthogonal, makes easy to read angle later
Transform light ;
2017-03-05 16:44:50 +01:00
light . origin [ 0 ] = p_light_xform [ 2 ] [ 0 ] ;
light . origin [ 1 ] = p_light_xform [ 2 ] [ 1 ] ;
light . basis [ 0 ] [ 0 ] = p_light_xform [ 0 ] [ 0 ] ;
light . basis [ 0 ] [ 1 ] = p_light_xform [ 1 ] [ 0 ] ;
light . basis [ 1 ] [ 0 ] = p_light_xform [ 0 ] [ 1 ] ;
light . basis [ 1 ] [ 1 ] = p_light_xform [ 1 ] [ 1 ] ;
2016-10-03 21:33:42 +02:00
//light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
2017-01-14 12:26:56 +01:00
//p_near=1;
2016-10-03 21:33:42 +02:00
CameraMatrix projection ;
{
2017-03-05 16:44:50 +01:00
real_t fov = 90 ;
2016-12-21 06:29:58 +01:00
real_t nearp = p_near ;
real_t farp = p_far ;
2016-10-03 21:33:42 +02:00
real_t aspect = 1.0 ;
2017-03-05 16:44:50 +01:00
real_t ymax = nearp * Math : : tan ( Math : : deg2rad ( fov * 0.5 ) ) ;
real_t ymin = - ymax ;
2016-10-03 21:33:42 +02:00
real_t xmin = ymin * aspect ;
real_t xmax = ymax * aspect ;
2017-03-05 16:44:50 +01:00
projection . set_frustum ( xmin , xmax , ymin , ymax , nearp , farp ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
Vector3 cam_target = Basis ( Vector3 ( 0 , 0 , Math_PI * 2 * ( i / 4.0 ) ) ) . xform ( Vector3 ( 0 , 1 , 0 ) ) ;
projection = projection * CameraMatrix ( Transform ( ) . looking_at ( cam_target , Vector3 ( 0 , 0 , - 1 ) ) . affine_inverse ( ) ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
state . canvas_shadow_shader . set_uniform ( CanvasShadowShaderGLES3 : : PROJECTION_MATRIX , projection ) ;
state . canvas_shadow_shader . set_uniform ( CanvasShadowShaderGLES3 : : LIGHT_MATRIX , light ) ;
state . canvas_shadow_shader . set_uniform ( CanvasShadowShaderGLES3 : : DISTANCE_NORM , 1.0 / p_far ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( i = = 0 )
* p_xform_cache = projection ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glViewport ( 0 , ( cls - > height / 4 ) * i , cls - > size , cls - > height / 4 ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
LightOccluderInstance * instance = p_occluders ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
while ( instance ) {
2016-10-03 21:33:42 +02:00
2020-01-08 11:29:15 +01:00
RasterizerStorageGLES3 : : CanvasOccluder * cc = storage - > canvas_occluder_owner . getornull ( instance - > polygon_buffer ) ;
2017-03-05 16:44:50 +01:00
if ( ! cc | | cc - > len = = 0 | | ! ( p_light_mask & instance - > light_mask ) ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
instance = instance - > next ;
2016-10-03 21:33:42 +02:00
continue ;
}
2017-03-05 16:44:50 +01:00
state . canvas_shadow_shader . set_uniform ( CanvasShadowShaderGLES3 : : WORLD_MATRIX , instance - > xform_cache ) ;
2016-10-03 21:33:42 +02:00
2019-12-10 23:05:15 +01:00
VS : : CanvasOccluderPolygonCullMode transformed_cull_cache = instance - > cull_cache ;
if ( transformed_cull_cache ! = VS : : CANVAS_OCCLUDER_POLYGON_CULL_DISABLED & &
( p_light_xform . basis_determinant ( ) * instance - > xform_cache . basis_determinant ( ) ) < 0 ) {
transformed_cull_cache =
transformed_cull_cache = = VS : : CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE ?
VS : : CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE :
VS : : CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE ;
}
if ( cull ! = transformed_cull_cache ) {
cull = transformed_cull_cache ;
2017-03-05 16:44:50 +01:00
switch ( cull ) {
2016-10-03 21:33:42 +02:00
case VS : : CANVAS_OCCLUDER_POLYGON_CULL_DISABLED : {
glDisable ( GL_CULL_FACE ) ;
} break ;
case VS : : CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE : {
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_FRONT ) ;
} break ;
case VS : : CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE : {
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_BACK ) ;
} break ;
}
}
2018-08-24 09:35:07 +02:00
2017-06-13 06:23:04 +02:00
glBindVertexArray ( cc - > array_id ) ;
2017-03-05 16:44:50 +01:00
glDrawElements ( GL_TRIANGLES , cc - > len * 3 , GL_UNSIGNED_SHORT , 0 ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
instance = instance - > next ;
2016-10-03 21:33:42 +02:00
}
}
2017-06-13 06:23:04 +02:00
glBindVertexArray ( 0 ) ;
2016-10-03 21:33:42 +02:00
}
void RasterizerCanvasGLES3 : : reset_canvas ( ) {
if ( storage - > frame . current_rt ) {
2016-11-29 23:55:12 +01:00
glBindFramebuffer ( GL_FRAMEBUFFER , storage - > frame . current_rt - > fbo ) ;
2017-03-05 16:44:50 +01:00
glColorMask ( 1 , 1 , 1 , 1 ) ; //don't touch alpha
2016-10-03 21:33:42 +02:00
}
glBindVertexArray ( 0 ) ;
glDisable ( GL_CULL_FACE ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_SCISSOR_TEST ) ;
2017-11-17 01:40:00 +01:00
glDisable ( GL_DITHER ) ;
2016-10-03 21:33:42 +02:00
glEnable ( GL_BLEND ) ;
glBlendEquation ( GL_FUNC_ADD ) ;
if ( storage - > frame . current_rt & & storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_TRANSPARENT ] ) {
glBlendFuncSeparate ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA , GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
2017-03-05 16:44:50 +01:00
} else {
2016-10-03 21:33:42 +02:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
}
//glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
2016-11-23 00:51:56 +01:00
//glLineWidth(1.0);
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
2016-10-03 21:33:42 +02:00
2017-06-27 03:58:03 +02:00
//use for reading from screen
2017-12-16 23:38:02 +01:00
if ( storage - > frame . current_rt & & ! storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_NO_SAMPLING ] ) {
2017-06-27 03:58:03 +02:00
glActiveTexture ( GL_TEXTURE0 + storage - > config . max_texture_image_units - 3 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > frame . current_rt - > effects . mip_maps [ 0 ] . color ) ;
}
2016-10-03 21:33:42 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2017-03-05 16:44:50 +01:00
glBindTexture ( GL_TEXTURE_2D , storage - > resources . white_tex ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
2016-10-03 21:33:42 +02:00
Transform canvas_transform ;
if ( storage - > frame . current_rt ) {
float csy = 1.0 ;
if ( storage - > frame . current_rt & & storage - > frame . current_rt - > flags [ RasterizerStorage : : RENDER_TARGET_VFLIP ] ) {
csy = - 1.0 ;
}
canvas_transform . translate ( - ( storage - > frame . current_rt - > width / 2.0f ) , - ( storage - > frame . current_rt - > height / 2.0f ) , 0.0f ) ;
2017-03-05 16:44:50 +01:00
canvas_transform . scale ( Vector3 ( 2.0f / storage - > frame . current_rt - > width , csy * - 2.0f / storage - > frame . current_rt - > height , 1.0f ) ) ;
2016-10-03 21:33:42 +02:00
} else {
Vector2 ssize = OS : : get_singleton ( ) - > get_window_size ( ) ;
canvas_transform . translate ( - ( ssize . width / 2.0f ) , - ( ssize . height / 2.0f ) , 0.0f ) ;
2017-03-05 16:44:50 +01:00
canvas_transform . scale ( Vector3 ( 2.0f / ssize . width , - 2.0f / ssize . height , 1.0f ) ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
state . vp = canvas_transform ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
store_transform ( canvas_transform , state . canvas_item_ubo_data . projection_matrix ) ;
2017-06-16 13:29:43 +02:00
state . canvas_item_ubo_data . time = storage - > frame . time [ 0 ] ;
2016-10-03 21:33:42 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , state . canvas_item_ubo ) ;
2019-11-10 19:51:56 +01:00
glBufferData ( GL_UNIFORM_BUFFER , sizeof ( CanvasItemUBO ) , & state . canvas_item_ubo_data , GL_DYNAMIC_DRAW ) ;
2016-10-03 21:33:42 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
2017-03-05 16:44:50 +01:00
state . canvas_texscreen_used = false ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : draw_generic_textured_rect ( const Rect2 & p_rect , const Rect2 & p_src ) {
2016-10-03 21:33:42 +02:00
2017-06-19 03:55:02 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : DST_RECT , Color ( p_rect . position . x , p_rect . position . y , p_rect . size . x , p_rect . size . y ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( p_src . position . x , p_src . position . y , p_src . size . x , p_src . size . y ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : CLIP_RECT_UV , false ) ;
2017-03-05 16:44:50 +01:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
2016-10-03 21:33:42 +02:00
}
2018-09-30 22:51:50 +02:00
void RasterizerCanvasGLES3 : : draw_lens_distortion_rect ( const Rect2 & p_rect , float p_k1 , float p_k2 , const Vector2 & p_eye_center , float p_oversample ) {
Vector2 half_size ;
if ( storage - > frame . current_rt ) {
half_size = Vector2 ( storage - > frame . current_rt - > width , storage - > frame . current_rt - > height ) ;
} else {
half_size = OS : : get_singleton ( ) - > get_window_size ( ) ;
}
half_size * = 0.5 ;
Vector2 offset ( ( p_rect . position . x - half_size . x ) / half_size . x , ( p_rect . position . y - half_size . y ) / half_size . y ) ;
Vector2 scale ( p_rect . size . x / half_size . x , p_rect . size . y / half_size . y ) ;
float aspect_ratio = p_rect . size . x / p_rect . size . y ;
// setup our lens shader
state . lens_shader . bind ( ) ;
state . lens_shader . set_uniform ( LensDistortedShaderGLES3 : : OFFSET , offset ) ;
state . lens_shader . set_uniform ( LensDistortedShaderGLES3 : : SCALE , scale ) ;
state . lens_shader . set_uniform ( LensDistortedShaderGLES3 : : K1 , p_k1 ) ;
state . lens_shader . set_uniform ( LensDistortedShaderGLES3 : : K2 , p_k2 ) ;
state . lens_shader . set_uniform ( LensDistortedShaderGLES3 : : EYE_CENTER , p_eye_center ) ;
state . lens_shader . set_uniform ( LensDistortedShaderGLES3 : : UPSCALE , p_oversample ) ;
state . lens_shader . set_uniform ( LensDistortedShaderGLES3 : : ASPECT_RATIO , aspect_ratio ) ;
glBindBufferBase ( GL_UNIFORM_BUFFER , 0 , state . canvas_item_ubo ) ;
glBindVertexArray ( data . canvas_quad_array ) ;
// and draw
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
glBindVertexArray ( 0 ) ;
glBindBufferBase ( GL_UNIFORM_BUFFER , 0 , 0 ) ;
}
2017-08-07 23:06:57 +02:00
void RasterizerCanvasGLES3 : : draw_window_margins ( int * black_margin , RID * black_image ) {
Vector2 window_size = OS : : get_singleton ( ) - > get_window_size ( ) ;
int window_h = window_size . height ;
int window_w = window_size . width ;
2019-06-26 15:08:25 +02:00
glBindFramebuffer ( GL_FRAMEBUFFER , RasterizerStorageGLES3 : : system_fbo ) ;
2017-08-07 23:06:57 +02:00
glViewport ( 0 , 0 , window_size . width , window_size . height ) ;
canvas_begin ( ) ;
if ( black_image [ MARGIN_LEFT ] . is_valid ( ) ) {
2020-07-06 20:54:45 +02:00
_bind_canvas_texture ( black_image [ MARGIN_LEFT ] , RID ( ) , true ) ;
2017-08-07 23:06:57 +02:00
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_LEFT ] ) , storage - > texture_get_height ( black_image [ MARGIN_LEFT ] ) ) ;
2020-06-03 23:33:33 +02:00
draw_generic_textured_rect ( Rect2 ( 0 , 0 , black_margin [ MARGIN_LEFT ] , window_h ) ,
Rect2 ( 0 , 0 , ( float ) black_margin [ MARGIN_LEFT ] / sz . x , ( float ) ( window_h ) / sz . y ) ) ;
2017-08-07 23:06:57 +02:00
} else if ( black_margin [ MARGIN_LEFT ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( 0 , 0 , black_margin [ MARGIN_LEFT ] , window_h ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
if ( black_image [ MARGIN_RIGHT ] . is_valid ( ) ) {
2020-07-06 20:54:45 +02:00
_bind_canvas_texture ( black_image [ MARGIN_RIGHT ] , RID ( ) , true ) ;
2017-08-07 23:06:57 +02:00
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_RIGHT ] ) , storage - > texture_get_height ( black_image [ MARGIN_RIGHT ] ) ) ;
2020-06-03 23:33:33 +02:00
draw_generic_textured_rect ( Rect2 ( window_w - black_margin [ MARGIN_RIGHT ] , 0 , black_margin [ MARGIN_RIGHT ] , window_h ) ,
Rect2 ( 0 , 0 , ( float ) black_margin [ MARGIN_RIGHT ] / sz . x , ( float ) window_h / sz . y ) ) ;
2017-08-07 23:06:57 +02:00
} else if ( black_margin [ MARGIN_RIGHT ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( window_w - black_margin [ MARGIN_RIGHT ] , 0 , black_margin [ MARGIN_RIGHT ] , window_h ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
if ( black_image [ MARGIN_TOP ] . is_valid ( ) ) {
2020-07-06 20:54:45 +02:00
_bind_canvas_texture ( black_image [ MARGIN_TOP ] , RID ( ) , true ) ;
2017-08-07 23:06:57 +02:00
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_TOP ] ) , storage - > texture_get_height ( black_image [ MARGIN_TOP ] ) ) ;
2020-06-03 23:33:33 +02:00
draw_generic_textured_rect ( Rect2 ( 0 , 0 , window_w , black_margin [ MARGIN_TOP ] ) ,
Rect2 ( 0 , 0 , ( float ) window_w / sz . x , ( float ) black_margin [ MARGIN_TOP ] / sz . y ) ) ;
2017-08-07 23:06:57 +02:00
} else if ( black_margin [ MARGIN_TOP ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( 0 , 0 , window_w , black_margin [ MARGIN_TOP ] ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
if ( black_image [ MARGIN_BOTTOM ] . is_valid ( ) ) {
2020-07-06 20:54:45 +02:00
_bind_canvas_texture ( black_image [ MARGIN_BOTTOM ] , RID ( ) , true ) ;
2017-08-07 23:06:57 +02:00
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_BOTTOM ] ) , storage - > texture_get_height ( black_image [ MARGIN_BOTTOM ] ) ) ;
2020-06-03 23:33:33 +02:00
draw_generic_textured_rect ( Rect2 ( 0 , window_h - black_margin [ MARGIN_BOTTOM ] , window_w , black_margin [ MARGIN_BOTTOM ] ) ,
Rect2 ( 0 , 0 , ( float ) window_w / sz . x , ( float ) black_margin [ MARGIN_BOTTOM ] / sz . y ) ) ;
2017-08-07 23:06:57 +02:00
} else if ( black_margin [ MARGIN_BOTTOM ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( 0 , window_h - black_margin [ MARGIN_BOTTOM ] , window_w , black_margin [ MARGIN_BOTTOM ] ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
}
2016-10-03 21:33:42 +02:00
void RasterizerCanvasGLES3 : : initialize ( ) {
{
//quad buffers
2017-03-05 16:44:50 +01:00
glGenBuffers ( 1 , & data . canvas_quad_vertices ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . canvas_quad_vertices ) ;
2016-10-03 21:33:42 +02:00
{
2017-03-05 16:44:50 +01:00
const float qv [ 8 ] = {
0 , 0 ,
0 , 1 ,
1 , 1 ,
1 , 0
2016-10-03 21:33:42 +02:00
} ;
2017-03-05 16:44:50 +01:00
glBufferData ( GL_ARRAY_BUFFER , sizeof ( float ) * 8 , qv , GL_STATIC_DRAW ) ;
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
2017-03-05 16:44:50 +01:00
glGenVertexArrays ( 1 , & data . canvas_quad_array ) ;
2016-10-03 21:33:42 +02:00
glBindVertexArray ( data . canvas_quad_array ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , data . canvas_quad_vertices ) ;
glVertexAttribPointer ( 0 , 2 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 2 , 0 ) ;
2016-10-03 21:33:42 +02:00
glEnableVertexAttribArray ( 0 ) ;
glBindVertexArray ( 0 ) ;
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
2016-10-03 21:33:42 +02:00
}
2017-06-21 21:25:45 +02:00
{
//particle quad buffers
glGenBuffers ( 1 , & data . particle_quad_vertices ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . particle_quad_vertices ) ;
{
//quad of size 1, with pivot on the center for particles, then regular UVS. Color is general plus fetched from particle
const float qv [ 16 ] = {
- 0.5 , - 0.5 ,
0.0 , 0.0 ,
- 0.5 , 0.5 ,
0.0 , 1.0 ,
0.5 , 0.5 ,
1.0 , 1.0 ,
0.5 , - 0.5 ,
1.0 , 0.0
} ;
glBufferData ( GL_ARRAY_BUFFER , sizeof ( float ) * 16 , qv , GL_STATIC_DRAW ) ;
}
2016-10-03 21:33:42 +02:00
2017-06-21 21:25:45 +02:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
glGenVertexArrays ( 1 , & data . particle_quad_array ) ;
glBindVertexArray ( data . particle_quad_array ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . particle_quad_vertices ) ;
glEnableVertexAttribArray ( VS : : ARRAY_VERTEX ) ;
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 , 0 ) ;
glEnableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
2019-04-06 21:01:49 +02:00
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 , CAST_INT_TO_UCHAR_PTR ( 8 ) ) ;
2017-06-21 21:25:45 +02:00
glBindVertexArray ( 0 ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ; //unbind
}
2016-11-23 00:51:56 +01:00
{
2018-07-19 23:58:15 +02:00
uint32_t poly_size = GLOBAL_DEF_RST ( " rendering/limits/buffers/canvas_polygon_buffer_size_kb " , 128 ) ;
2018-10-05 18:43:53 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/limits/buffers/canvas_polygon_buffer_size_kb " , PropertyInfo ( Variant : : INT , " rendering/limits/buffers/canvas_polygon_buffer_size_kb " , PROPERTY_HINT_RANGE , " 0,256,1,or_greater " ) ) ;
2017-06-12 23:56:16 +02:00
poly_size * = 1024 ; //kb
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
poly_size = MAX ( poly_size , ( 2 + 2 + 4 + 1 ) * 4 * sizeof ( float ) ) ;
2017-06-12 23:56:16 +02:00
glGenBuffers ( 1 , & data . polygon_buffer ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
glBufferData ( GL_ARRAY_BUFFER , poly_size , NULL , GL_DYNAMIC_DRAW ) ; //allocate max size
2017-03-05 16:44:50 +01:00
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2017-12-09 18:11:26 +01:00
data . polygon_buffer_size = poly_size ;
2016-11-23 00:51:56 +01:00
2017-06-12 23:56:16 +02:00
//quad arrays
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
for ( int i = 0 ; i < Data : : NUM_QUAD_ARRAY_VARIATIONS ; i + + ) {
2017-06-12 23:56:16 +02:00
glGenVertexArrays ( 1 , & data . polygon_buffer_quad_arrays [ i ] ) ;
glBindVertexArray ( data . polygon_buffer_quad_arrays [ i ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
int uv_ofs = 0 ;
int color_ofs = 0 ;
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
int light_angle_ofs = 0 ;
2017-03-05 16:44:50 +01:00
int stride = 2 * 4 ;
2016-11-23 00:51:56 +01:00
2017-03-05 16:44:50 +01:00
if ( i & 1 ) { //color
color_ofs = stride ;
stride + = 4 * 4 ;
2016-11-23 00:51:56 +01:00
}
2017-03-05 16:44:50 +01:00
if ( i & 2 ) { //uv
uv_ofs = stride ;
stride + = 2 * 4 ;
2016-11-23 00:51:56 +01:00
}
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
if ( i & 4 ) { //light_angle
light_angle_ofs = stride ;
stride + = 1 * 4 ;
}
2016-11-23 00:51:56 +01:00
glEnableVertexAttribArray ( VS : : ARRAY_VERTEX ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , GL_FALSE , stride , NULL ) ;
2016-11-23 00:51:56 +01:00
2017-03-05 16:44:50 +01:00
if ( i & 1 ) {
2016-11-23 00:51:56 +01:00
glEnableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_COLOR , 4 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( color_ofs ) ) ;
2016-11-23 00:51:56 +01:00
}
2017-03-05 16:44:50 +01:00
if ( i & 2 ) {
2016-11-23 00:51:56 +01:00
glEnableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
2019-02-27 10:07:30 +01:00
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( uv_ofs ) ) ;
2016-11-23 00:51:56 +01:00
}
GLES3 fix normal map flipping with nvidia workaround
When not using TEXTURE_RECT path, flips have to sent via another method to the shader, to ensure that normal maps are correctly adjusted for direction. This PR adds an extra vertex attribute, LIGHT_ANGLE.
For nvidia workarounds, where the shader still has access to the final transform and extra matrix, the LIGHT_ANGLE can be 0 (no adjustment), 180 degrees for a horizontal flip, and negative indicates a vertical flip.
For batching path, the LIGHT_ANGLE can be used to directly specify the light angle for normal mapping, even when the final transform and extra matrix have been baked into vertex positions, so the same shader can be used for both.
2020-08-02 08:49:03 +02:00
if ( i & 4 ) {
// reusing tangent for light_angle
glEnableVertexAttribArray ( VS : : ARRAY_TANGENT ) ;
glVertexAttribPointer ( VS : : ARRAY_TANGENT , 1 , GL_FLOAT , GL_FALSE , stride , CAST_INT_TO_UCHAR_PTR ( light_angle_ofs ) ) ;
}
2016-11-23 00:51:56 +01:00
glBindVertexArray ( 0 ) ;
}
2017-06-12 23:56:16 +02:00
glGenVertexArrays ( 1 , & data . polygon_buffer_pointer_array ) ;
2018-07-19 23:58:15 +02:00
uint32_t index_size = GLOBAL_DEF_RST ( " rendering/limits/buffers/canvas_polygon_index_buffer_size_kb " , 128 ) ;
2018-10-05 18:43:53 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/limits/buffers/canvas_polygon_index_buffer_size_kb " , PropertyInfo ( Variant : : INT , " rendering/limits/buffers/canvas_polygon_index_buffer_size_kb " , PROPERTY_HINT_RANGE , " 0,256,1,or_greater " ) ) ;
2017-06-12 23:56:16 +02:00
index_size * = 1024 ; //kb
glGenBuffers ( 1 , & data . polygon_index_buffer ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , data . polygon_index_buffer ) ;
glBufferData ( GL_ELEMENT_ARRAY_BUFFER , index_size , NULL , GL_DYNAMIC_DRAW ) ; //allocate max size
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
2019-11-10 19:51:56 +01:00
data . polygon_index_buffer_size = index_size ;
2016-11-23 00:51:56 +01:00
}
2017-03-05 16:44:50 +01:00
store_transform ( Transform ( ) , state . canvas_item_ubo_data . projection_matrix ) ;
2016-10-03 21:33:42 +02:00
glGenBuffers ( 1 , & state . canvas_item_ubo ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , state . canvas_item_ubo ) ;
glBufferData ( GL_UNIFORM_BUFFER , sizeof ( CanvasItemUBO ) , & state . canvas_item_ubo_data , GL_DYNAMIC_DRAW ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
state . canvas_shader . init ( ) ;
2017-06-27 03:58:03 +02:00
state . canvas_shader . set_base_material_tex_index ( 2 ) ;
2016-10-03 21:33:42 +02:00
state . canvas_shadow_shader . init ( ) ;
2018-09-30 22:51:50 +02:00
state . lens_shader . init ( ) ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_RGBA_SHADOWS , storage - > config . use_rgba_2d_shadows ) ;
state . canvas_shadow_shader . set_conditional ( CanvasShadowShaderGLES3 : : USE_RGBA_SHADOWS , storage - > config . use_rgba_2d_shadows ) ;
2017-12-19 18:18:07 +01:00
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_PIXEL_SNAP , GLOBAL_DEF ( " rendering/quality/2d/use_pixel_snap " , false ) ) ;
2016-10-03 21:33:42 +02:00
}
void RasterizerCanvasGLES3 : : finalize ( ) {
2017-03-05 16:44:50 +01:00
glDeleteBuffers ( 1 , & data . canvas_quad_vertices ) ;
glDeleteVertexArrays ( 1 , & data . canvas_quad_array ) ;
2017-06-12 23:56:16 +02:00
2017-06-21 21:25:45 +02:00
glDeleteBuffers ( 1 , & data . canvas_quad_vertices ) ;
glDeleteVertexArrays ( 1 , & data . canvas_quad_array ) ;
2017-06-12 23:56:16 +02:00
glDeleteVertexArrays ( 1 , & data . polygon_buffer_pointer_array ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
RasterizerCanvasGLES3 : : RasterizerCanvasGLES3 ( ) {
2020-05-05 17:25:45 +02:00
// Not needed (a priori) on GLES devices
use_nvidia_rect_workaround = false ;
# ifdef GLES_OVER_GL
use_nvidia_rect_workaround = GLOBAL_GET ( " rendering/quality/2d/use_nvidia_rect_flicker_workaround " ) ;
# endif
2016-10-03 21:33:42 +02:00
}