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
/*************************************************************************/
2018-01-01 14:40:08 +01:00
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 ) ;
2017-03-05 16:44:50 +01:00
glBufferSubData ( GL_UNIFORM_BUFFER , 0 , sizeof ( LightInternal : : UBOData ) , & li - > ubo_data ) ;
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
2017-03-05 16:44:50 +01:00
glClearColor ( storage - > frame . clear_request_color . r , storage - > frame . clear_request_color . g , storage - > frame . clear_request_color . b , storage - > frame . clear_request_color . a ) ;
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 ;
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 ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF5 , false ) ;
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 ) ;
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 ;
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 ) ;
2016-10-03 21:33:42 +02:00
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 ;
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-11-16 13:33:33 +01:00
texture = texture - > get_ptr ( ) ;
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 ( ) ;
}
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-11-16 13:33:33 +01:00
normal_map = normal_map - > get_ptr ( ) ;
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 ( ) ;
}
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
}
2017-06-22 04:37:25 +02:00
void RasterizerCanvasGLES3 : : _set_texture_rect_mode ( bool p_enable , bool p_ninepatch ) {
2016-10-03 21:33:42 +02:00
2017-06-22 04:37:25 +02:00
if ( state . using_texture_rect = = p_enable & & state . using_ninepatch = = p_ninepatch )
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 ) ;
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 ;
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
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
2018-05-04 14:32:40 +02:00
# ifdef DEBUG_ENABLED
ERR_FAIL_COND ( buffer_ofs > data . polygon_buffer_size ) ;
# endif
2017-06-12 23:56:16 +02:00
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 ) ;
2017-06-14 23:43:57 +02:00
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , ( ( uint8_t * ) 0 ) + 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 ) ;
2017-06-14 23:43:57 +02:00
glVertexAttribPointer ( VS : : ARRAY_COLOR , 4 , GL_FLOAT , false , sizeof ( Color ) , ( ( uint8_t * ) 0 ) + 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 ) ;
2017-06-14 23:43:57 +02:00
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , ( ( uint8_t * ) 0 ) + 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);
glVertexAttribIPointer ( VS : : ARRAY_BONES , 4 , GL_UNSIGNED_INT , sizeof ( int ) * 4 , ( ( uint8_t * ) 0 ) + 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 ) ;
glVertexAttribPointer ( VS : : ARRAY_WEIGHTS , 4 , GL_FLOAT , false , sizeof ( float ) * 4 , ( ( uint8_t * ) 0 ) + buffer_ofs ) ;
buffer_ofs + = sizeof ( float ) * 4 * p_vertex_count ;
} else if ( state . using_skeleton ) {
glVertexAttribI4ui ( VS : : ARRAY_BONES , 0 , 0 , 0 , 0 ) ;
glVertexAttrib4f ( VS : : ARRAY_WEIGHTS , 0 , 0 , 0 , 0 ) ;
}
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 ) ;
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
storage - > frame . canvas_draw_commands + + ;
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 ) ;
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 ) ;
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 ) , ( ( uint8_t * ) 0 ) + buffer_ofs ) ;
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
//color
if ( p_singlecolor ) {
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
Color m = * p_colors ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , m . r , m . g , m . b , m . a ) ;
} else if ( ! p_colors ) {
glDisableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
glVertexAttrib4f ( VS : : ARRAY_COLOR , 1 , 1 , 1 , 1 ) ;
} else {
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Color ) * p_vertex_count , p_colors ) ;
glEnableVertexAttribArray ( VS : : ARRAY_COLOR ) ;
glVertexAttribPointer ( VS : : ARRAY_COLOR , 4 , GL_FLOAT , false , sizeof ( Color ) , ( ( uint8_t * ) 0 ) + buffer_ofs ) ;
buffer_ofs + = sizeof ( Color ) * p_vertex_count ;
}
if ( p_uvs ) {
glBufferSubData ( GL_ARRAY_BUFFER , buffer_ofs , sizeof ( Vector2 ) * p_vertex_count , p_uvs ) ;
glEnableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , false , sizeof ( Vector2 ) , ( ( uint8_t * ) 0 ) + buffer_ofs ) ;
buffer_ofs + = sizeof ( Vector2 ) * p_vertex_count ;
} else {
glDisableVertexAttribArray ( VS : : ARRAY_TEX_UV ) ;
}
glDrawArrays ( p_primitive , 0 , p_vertex_count ) ;
storage - > frame . canvas_draw_commands + + ;
glBindVertexArray ( 0 ) ;
}
2017-03-05 16:44:50 +01:00
void RasterizerCanvasGLES3 : : _draw_gui_primitive ( int p_points , const Vector2 * p_vertices , const Color * p_colors , const Vector2 * p_uvs ) {
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 ;
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
}
2017-03-05 16:44:50 +01:00
float b [ ( 2 + 2 + 4 ) * 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
}
}
2017-06-12 23:56:16 +02:00
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
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
storage - > frame . canvas_draw_commands + + ;
}
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
} ;
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 ] = {
Vector2 ( line - > from . x , line - > from . y ) ,
Vector2 ( line - > to . x , line - > to . y )
} ;
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 ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
Vector2 vertsl [ 2 ] = {
verts [ i ] ,
verts [ ( i + 1 ) % 4 ] ,
} ;
_draw_gui_primitive ( 2 , vertsl , NULL , NULL ) ;
}
glDisable ( GL_LINE_SMOOTH ) ;
}
# endif
}
} break ;
case Item : : Command : : TYPE_POLYLINE : {
Item : : CommandPolyLine * pline = static_cast < Item : : CommandPolyLine * > ( c ) ;
_set_texture_rect_mode ( false ) ;
_bind_canvas_texture ( RID ( ) , RID ( ) ) ;
if ( pline - > triangles . size ( ) ) {
_draw_generic ( GL_TRIANGLE_STRIP , pline - > triangles . size ( ) , pline - > triangles . ptr ( ) , NULL , pline - > triangle_colors . ptr ( ) , pline - > triangle_colors . size ( ) = = 1 ) ;
# ifdef GLES_OVER_GL
glEnable ( GL_LINE_SMOOTH ) ;
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_texture_rect_mode ( true ) ;
//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
2017-03-05 16:44:50 +01:00
if ( texture ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
bool untile = false ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01: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 ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
Size2 texpixel_size ( 1.0 / texture - > width , 1.0 / texture - > height ) ;
2017-06-04 00:25:13 +02:00
Rect2 src_rect = ( rect - > flags & CANVAS_RECT_REGION ) ? Rect2 ( rect - > source . position * texpixel_size , rect - > source . size * texpixel_size ) : Rect2 ( 0 , 0 , 1 , 1 ) ;
2017-08-18 12:57:03 +02:00
Rect2 dst_rect = Rect2 ( rect - > rect . position , rect - > rect . size ) ;
2016-10-03 21:33:42 +02:00
2017-09-02 18:58:04 +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 ;
}
2017-03-05 16:44:50 +01:00
if ( rect - > flags & CANVAS_RECT_FLIP_H ) {
src_rect . size . x * = - 1 ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
if ( rect - > flags & CANVAS_RECT_FLIP_V ) {
src_rect . size . y * = - 1 ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
if ( rect - > flags & CANVAS_RECT_TRANSPOSE ) {
2017-08-18 12:57:03 +02:00
dst_rect . size . x * = - 1 ; // Encoding in the dst_rect.z uniform
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : COLOR_TEXPIXEL_SIZE , texpixel_size ) ;
2016-10-03 21:33:42 +02:00
2017-08-18 12:57:03 +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 ) ) ;
2017-06-19 03:55:02 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( src_rect . position . x , src_rect . position . y , src_rect . size . x , src_rect . size . y ) ) ;
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : CLIP_RECT_UV , ( rect - > flags & CANVAS_RECT_CLIP_UV ) ? true : false ) ;
2017-03-05 16:44:50 +01:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ;
2016-10-03 21:33:42 +02:00
if ( untile ) {
2017-03-05 16:44:50 +01:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2016-10-03 21:33:42 +02:00
}
} else {
2017-09-02 18:58:04 +02:00
Rect2 dst_rect = Rect2 ( rect - > rect . position , rect - > rect . size ) ;
2016-10-03 21:33:42 +02:00
2017-09-02 18:58:04 +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 ;
}
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 ) ) ;
2017-06-19 03:55:02 +02:00
state . canvas_shader . set_uniform ( CanvasShaderGLES3 : : SRC_RECT , Color ( 0 , 0 , 1 , 1 ) ) ;
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
}
storage - > frame . canvas_draw_commands + + ;
} break ;
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
storage - > frame . canvas_draw_commands + + ;
} 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
Color c = primitive - > colors [ 0 ] ;
2017-03-05 16:44:50 +01:00
glVertexAttrib4f ( VS : : ARRAY_COLOR , c . r , c . g , c . b , c . 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 ) ;
_draw_generic ( GL_LINE_LOOP , polygon - > points . size ( ) , polygon - > points . ptr ( ) , polygon - > uvs . ptr ( ) , polygon - > colors . ptr ( ) , polygon - > colors . size ( ) = = 1 ) ;
glDisable ( GL_LINE_SMOOTH ) ;
}
# endif
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 ) ;
}
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 ) ;
if ( s - > index_array_len ) {
glDrawElements ( gl_primitive [ s - > primitive ] , s - > index_array_len , ( s - > array_len > = ( 1 < < 16 ) ) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT , 0 ) ;
} else {
glDrawArrays ( gl_primitive [ s - > primitive ] , 0 , s - > array_len ) ;
}
glBindVertexArray ( 0 ) ;
}
}
} 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 ) ;
}
int amount = MAX ( multi_mesh - > size , multi_mesh - > visible_instances ) ;
for ( int j = 0 ; j < mesh_data - > surfaces . size ( ) ; j + + ) {
RasterizerStorageGLES3 : : Surface * s = mesh_data - > surfaces [ j ] ;
// materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing
glBindVertexArray ( s - > instancing_array_id ) ;
glBindBuffer ( GL_ARRAY_BUFFER , multi_mesh - > buffer ) ; //modify the buffer
int stride = ( multi_mesh - > xform_floats + multi_mesh - > color_floats + multi_mesh - > custom_data_floats ) * 4 ;
glEnableVertexAttribArray ( 8 ) ;
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + 0 ) ;
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ;
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + 4 * 4 ) ;
glVertexAttribDivisor ( 9 , 1 ) ;
int color_ofs ;
if ( multi_mesh - > transform_format = = VS : : MULTIMESH_TRANSFORM_3D ) {
glEnableVertexAttribArray ( 10 ) ;
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + 8 * 4 ) ;
glVertexAttribDivisor ( 10 , 1 ) ;
color_ofs = 12 * 4 ;
} else {
glDisableVertexAttribArray ( 10 ) ;
glVertexAttrib4f ( 10 , 0 , 0 , 1 , 0 ) ;
color_ofs = 8 * 4 ;
}
int custom_data_ofs = color_ofs ;
switch ( multi_mesh - > color_format ) {
case VS : : MULTIMESH_COLOR_NONE : {
glDisableVertexAttribArray ( 11 ) ;
glVertexAttrib4f ( 11 , 1 , 1 , 1 , 1 ) ;
} break ;
case VS : : MULTIMESH_COLOR_8BIT : {
glEnableVertexAttribArray ( 11 ) ;
glVertexAttribPointer ( 11 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , stride , ( ( uint8_t * ) NULL ) + color_ofs ) ;
glVertexAttribDivisor ( 11 , 1 ) ;
custom_data_ofs + = 4 ;
} break ;
case VS : : MULTIMESH_COLOR_FLOAT : {
glEnableVertexAttribArray ( 11 ) ;
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + color_ofs ) ;
glVertexAttribDivisor ( 11 , 1 ) ;
custom_data_ofs + = 4 * 4 ;
} break ;
}
switch ( multi_mesh - > custom_data_format ) {
case VS : : MULTIMESH_CUSTOM_DATA_NONE : {
glDisableVertexAttribArray ( 12 ) ;
glVertexAttrib4f ( 12 , 1 , 1 , 1 , 1 ) ;
} break ;
case VS : : MULTIMESH_CUSTOM_DATA_8BIT : {
glEnableVertexAttribArray ( 12 ) ;
glVertexAttribPointer ( 12 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , stride , ( ( uint8_t * ) NULL ) + custom_data_ofs ) ;
glVertexAttribDivisor ( 12 , 1 ) ;
} break ;
case VS : : MULTIMESH_CUSTOM_DATA_FLOAT : {
glEnableVertexAttribArray ( 12 ) ;
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + custom_data_ofs ) ;
glVertexAttribDivisor ( 12 , 1 ) ;
} break ;
}
if ( s - > index_array_len ) {
glDrawElementsInstanced ( gl_primitive [ s - > primitive ] , s - > index_array_len , ( s - > array_len > = ( 1 < < 16 ) ) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT , 0 , amount ) ;
} else {
glDrawArraysInstanced ( gl_primitive [ s - > primitive ] , 0 , s - > array_len , amount ) ;
}
glBindVertexArray ( 0 ) ;
}
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCE_CUSTOM , false ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCING , false ) ;
state . using_texture_rect = true ;
_set_texture_rect_mode ( false ) ;
} break ;
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
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 3 ) ;
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ; //xform y
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 4 ) ;
glVertexAttribDivisor ( 9 , 1 ) ;
glEnableVertexAttribArray ( 10 ) ; //xform z
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 5 ) ;
glVertexAttribDivisor ( 10 , 1 ) ;
glEnableVertexAttribArray ( 11 ) ; //color
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + 0 ) ;
glVertexAttribDivisor ( 11 , 1 ) ;
glEnableVertexAttribArray ( 12 ) ; //custom
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 2 ) ;
glVertexAttribDivisor ( 12 , 1 ) ;
glDrawArraysInstanced ( GL_TRIANGLE_FAN , 0 , 4 , amount ) ;
} else {
//split
int stride = sizeof ( float ) * 4 * 6 ;
int split = int ( Math : : ceil ( particles - > phase * particles - > amount ) ) ;
if ( amount - split > 0 ) {
glEnableVertexAttribArray ( 8 ) ; //xform x
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + stride * split + sizeof ( float ) * 4 * 3 ) ;
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ; //xform y
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + stride * split + sizeof ( float ) * 4 * 4 ) ;
glVertexAttribDivisor ( 9 , 1 ) ;
glEnableVertexAttribArray ( 10 ) ; //xform z
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + stride * split + sizeof ( float ) * 4 * 5 ) ;
glVertexAttribDivisor ( 10 , 1 ) ;
glEnableVertexAttribArray ( 11 ) ; //color
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + stride * split + 0 ) ;
glVertexAttribDivisor ( 11 , 1 ) ;
glEnableVertexAttribArray ( 12 ) ; //custom
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + stride * split + sizeof ( float ) * 4 * 2 ) ;
glVertexAttribDivisor ( 12 , 1 ) ;
glDrawArraysInstanced ( GL_TRIANGLE_FAN , 0 , 4 , amount - split ) ;
}
if ( split > 0 ) {
glEnableVertexAttribArray ( 8 ) ; //xform x
glVertexAttribPointer ( 8 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 3 ) ;
glVertexAttribDivisor ( 8 , 1 ) ;
glEnableVertexAttribArray ( 9 ) ; //xform y
glVertexAttribPointer ( 9 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 4 ) ;
glVertexAttribDivisor ( 9 , 1 ) ;
glEnableVertexAttribArray ( 10 ) ; //xform z
glVertexAttribPointer ( 10 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 5 ) ;
glVertexAttribDivisor ( 10 , 1 ) ;
glEnableVertexAttribArray ( 11 ) ; //color
glVertexAttribPointer ( 11 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + 0 ) ;
glVertexAttribDivisor ( 11 , 1 ) ;
glEnableVertexAttribArray ( 12 ) ; //custom
glVertexAttribPointer ( 12 , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + sizeof ( float ) * 4 * 2 ) ;
glVertexAttribDivisor ( 12 , 1 ) ;
glDrawArraysInstanced ( GL_TRIANGLE_FAN , 0 , 4 , split ) ;
}
}
glBindVertexArray ( 0 ) ;
state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : USE_INSTANCE_CUSTOM , false ) ;
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
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < numpoints ; i + + ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
points [ i ] = circle - > pos + Vector2 ( Math : : sin ( i * Math_PI * 2.0 / numpoints ) , Math : : cos ( i * Math_PI * 2.0 / numpoints ) ) * circle - > radius ;
indices [ i * 3 + 0 ] = i ;
indices [ i * 3 + 1 ] = ( i + 1 ) % numpoints ;
indices [ i * 3 + 2 ] = numpoints ;
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 ) {
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 ;
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 ) {
glActiveTexture ( GL_TEXTURE0 + storage - > config . max_texture_image_units - 1 ) ;
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-11-16 13:33:33 +01:00
t = t - > get_ptr ( ) ;
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 ( ) ;
}
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
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 ) ;
switch ( light - > shadow_filter ) {
case VS : : CANVAS_LIGHT_FILTER_NONE : state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_NEAREST , true ) ; break ;
case VS : : CANVAS_LIGHT_FILTER_PCF3 : state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF3 , true ) ; break ;
case VS : : CANVAS_LIGHT_FILTER_PCF5 : state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF5 , true ) ; break ;
2017-09-01 15:01:24 +02:00
case VS : : CANVAS_LIGHT_FILTER_PCF7 : state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF7 , true ) ; break ;
2017-03-05 16:44:50 +01:00
case VS : : CANVAS_LIGHT_FILTER_PCF9 : state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF9 , true ) ; break ;
case VS : : CANVAS_LIGHT_FILTER_PCF13 : state . canvas_shader . set_conditional ( CanvasShaderGLES3 : : SHADOW_FILTER_PCF13 , true ) ; break ;
2016-10-03 21:33:42 +02:00
}
}
bool light_rebind = state . canvas_shader . bind ( ) ;
if ( light_rebind ) {
2016-10-10 23:31:01 +02:00
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 ( ) ) ;
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
}
}
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
RasterizerStorageGLES3 : : CanvasOccluder * cc = storage - > canvas_occluder_owner . get ( 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 ) ;
if ( cull ! = instance - > cull_cache ) {
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
cull = instance - > cull_cache ;
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 ) ;
glBufferSubData ( GL_UNIFORM_BUFFER , 0 , sizeof ( CanvasItemUBO ) , & state . canvas_item_ubo_data ) ;
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 ;
glBindFramebuffer ( GL_FRAMEBUFFER , storage - > system_fbo ) ;
glViewport ( 0 , 0 , window_size . width , window_size . height ) ;
canvas_begin ( ) ;
if ( black_image [ MARGIN_LEFT ] . is_valid ( ) ) {
_bind_canvas_texture ( black_image [ MARGIN_LEFT ] , RID ( ) ) ;
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_LEFT ] ) , storage - > texture_get_height ( black_image [ MARGIN_LEFT ] ) ) ;
draw_generic_textured_rect ( Rect2 ( 0 , 0 , black_margin [ MARGIN_LEFT ] , window_h ) , Rect2 ( 0 , 0 , sz . x , sz . y ) ) ;
} else if ( black_margin [ MARGIN_LEFT ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( 0 , 0 , black_margin [ MARGIN_LEFT ] , window_h ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
if ( black_image [ MARGIN_RIGHT ] . is_valid ( ) ) {
_bind_canvas_texture ( black_image [ MARGIN_RIGHT ] , RID ( ) ) ;
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_RIGHT ] ) , storage - > texture_get_height ( black_image [ MARGIN_RIGHT ] ) ) ;
draw_generic_textured_rect ( Rect2 ( window_w - black_margin [ MARGIN_RIGHT ] , 0 , black_margin [ MARGIN_RIGHT ] , window_h ) , Rect2 ( 0 , 0 , sz . x , sz . y ) ) ;
} else if ( black_margin [ MARGIN_RIGHT ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( window_w - black_margin [ MARGIN_RIGHT ] , 0 , black_margin [ MARGIN_RIGHT ] , window_h ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
if ( black_image [ MARGIN_TOP ] . is_valid ( ) ) {
_bind_canvas_texture ( black_image [ MARGIN_TOP ] , RID ( ) ) ;
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_TOP ] ) , storage - > texture_get_height ( black_image [ MARGIN_TOP ] ) ) ;
draw_generic_textured_rect ( Rect2 ( 0 , 0 , window_w , black_margin [ MARGIN_TOP ] ) , Rect2 ( 0 , 0 , sz . x , sz . y ) ) ;
} else if ( black_margin [ MARGIN_TOP ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( 0 , 0 , window_w , black_margin [ MARGIN_TOP ] ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
if ( black_image [ MARGIN_BOTTOM ] . is_valid ( ) ) {
_bind_canvas_texture ( black_image [ MARGIN_BOTTOM ] , RID ( ) ) ;
Size2 sz ( storage - > texture_get_width ( black_image [ MARGIN_BOTTOM ] ) , storage - > texture_get_height ( black_image [ MARGIN_BOTTOM ] ) ) ;
draw_generic_textured_rect ( Rect2 ( 0 , window_h - black_margin [ MARGIN_BOTTOM ] , window_w , black_margin [ MARGIN_BOTTOM ] ) , Rect2 ( 0 , 0 , sz . x , sz . y ) ) ;
} else if ( black_margin [ MARGIN_BOTTOM ] ) {
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , storage - > resources . black_tex ) ;
draw_generic_textured_rect ( Rect2 ( 0 , window_h - black_margin [ MARGIN_BOTTOM ] , window_w , black_margin [ MARGIN_BOTTOM ] ) , Rect2 ( 0 , 0 , 1 , 1 ) ) ;
}
}
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 ) ;
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , GL_FALSE , sizeof ( float ) * 4 , ( float * ) 0 + 2 ) ;
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
poly_size = MAX ( poly_size , ( 2 + 2 + 4 ) * 4 * sizeof ( float ) ) ;
glGenBuffers ( 1 , & data . polygon_buffer ) ;
glBindBuffer ( GL_ARRAY_BUFFER , data . polygon_buffer ) ;
glBufferData ( GL_ARRAY_BUFFER , poly_size , NULL , GL_DYNAMIC_DRAW ) ; //allocate max size
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
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; 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 ;
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
}
glEnableVertexAttribArray ( VS : : ARRAY_VERTEX ) ;
2017-03-05 16:44:50 +01:00
glVertexAttribPointer ( VS : : ARRAY_VERTEX , 2 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + 0 ) ;
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 ) ;
2017-03-05 16:44:50 +01:00
glVertexAttribPointer ( VS : : ARRAY_COLOR , 4 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + 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 ) ;
2017-03-05 16:44:50 +01:00
glVertexAttribPointer ( VS : : ARRAY_TEX_UV , 2 , GL_FLOAT , GL_FALSE , stride , ( ( uint8_t * ) NULL ) + uv_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 ) ;
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 ( ) {
2016-10-03 21:33:42 +02:00
}