mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-04 07:31:16 +00:00 
			
		
		
		
	Merge pull request #16687 from karroffel/gles2-2d-pr
add GLES 2 renderer for 2D
This commit is contained in:
		
						commit
						29215b229b
					
				
					 41 changed files with 12286 additions and 719 deletions
				
			
		
							
								
								
									
										12
									
								
								SConstruct
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								SConstruct
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -145,7 +145,7 @@ opts = Variables(customs, ARGUMENTS)
 | 
			
		|||
 | 
			
		||||
# Target build options
 | 
			
		||||
opts.Add('arch', "Platform-dependent architecture (arm/arm64/x86/x64/mips/etc)", '')
 | 
			
		||||
opts.Add(EnumVariable('bits', "Target platform bits", 'default', ('default', '32', '64')))
 | 
			
		||||
opts.Add(EnumVariable('bits', "Target platform bits", 'default', ('default', '32', '64', 'fat')))
 | 
			
		||||
opts.Add('p', "Platform (alias for 'platform')", '')
 | 
			
		||||
opts.Add('platform', "Target platform (%s)" % ('|'.join(platform_list), ), '')
 | 
			
		||||
opts.Add(EnumVariable('target', "Compilation target", 'debug', ('debug', 'release_debug', 'release')))
 | 
			
		||||
| 
						 | 
				
			
			@ -161,11 +161,11 @@ opts.Add(BoolVariable('xml', "XML format support for resources", True))
 | 
			
		|||
 | 
			
		||||
# Advanced options
 | 
			
		||||
opts.Add(BoolVariable('disable_3d', "Disable 3D nodes for smaller executable", False))
 | 
			
		||||
opts.Add(BoolVariable('disable_advanced_gui', "Disable advanced 3D gui nodes and behaviors", False))
 | 
			
		||||
opts.Add(BoolVariable('disable_advanced_gui', "Disable advance 3D gui nodes and behaviors", False))
 | 
			
		||||
opts.Add('extra_suffix', "Custom extra suffix added to the base filename of all generated binary files", '')
 | 
			
		||||
opts.Add('unix_global_settings_path', "UNIX-specific path to system-wide settings. Currently only used for templates", '')
 | 
			
		||||
opts.Add(BoolVariable('verbose', "Enable verbose output for the compilation", False))
 | 
			
		||||
opts.Add(BoolVariable('vsproj', "Generate Visual Studio Project", False))
 | 
			
		||||
opts.Add(BoolVariable('vsproj', "Generate Visual Studio Project.", False))
 | 
			
		||||
opts.Add(EnumVariable('warnings', "Set the level of warnings emitted during compilation", 'no', ('extra', 'all', 'moderate', 'no')))
 | 
			
		||||
opts.Add(BoolVariable('progress', "Show a progress indicator during build", True))
 | 
			
		||||
opts.Add(BoolVariable('dev', "If yes, alias for verbose=yes warnings=all", False))
 | 
			
		||||
| 
						 | 
				
			
			@ -353,7 +353,6 @@ if selected_platform in platform_list:
 | 
			
		|||
            env.Append(CCFLAGS=['-Wall', '-Wno-unused'])
 | 
			
		||||
        else: # 'no'
 | 
			
		||||
            env.Append(CCFLAGS=['-w'])
 | 
			
		||||
        env.Append(CCFLAGS=['-Werror=return-type'])
 | 
			
		||||
 | 
			
		||||
    #env['platform_libsuffix'] = env['LIBSUFFIX']
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -383,6 +382,8 @@ if selected_platform in platform_list:
 | 
			
		|||
        suffix += ".32"
 | 
			
		||||
    elif (env["bits"] == "64"):
 | 
			
		||||
        suffix += ".64"
 | 
			
		||||
    elif (env["bits"] == "fat"):
 | 
			
		||||
        suffix += ".fat"
 | 
			
		||||
 | 
			
		||||
    suffix += env.extra_suffix
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -445,7 +446,8 @@ if selected_platform in platform_list:
 | 
			
		|||
        methods.no_verbose(sys, env)
 | 
			
		||||
 | 
			
		||||
    if (not env["platform"] == "server"): # FIXME: detect GLES3
 | 
			
		||||
        env.Append( BUILDERS = { 'GLES3_GLSL' : env.Builder(action = methods.build_gles3_headers, suffix = 'glsl.gen.h',src_suffix = '.glsl') } )
 | 
			
		||||
        env.Append( BUILDERS = { 'GLES3_GLSL' : env.Builder(action = methods.build_gles3_headers, suffix = 'glsl.gen.h', src_suffix = '.glsl') } )
 | 
			
		||||
        env.Append( BUILDERS = { 'GLES2_GLSL' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.gen.h', src_suffix = '.glsl') } )
 | 
			
		||||
 | 
			
		||||
    scons_cache_path = os.environ.get("SCONS_CACHE")
 | 
			
		||||
    if scons_cache_path != None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								drivers/SCsub
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								drivers/SCsub
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -24,6 +24,7 @@ if env['xaudio2']:
 | 
			
		|||
# Graphics drivers
 | 
			
		||||
if (env["platform"] != "server"):
 | 
			
		||||
    SConscript('gles3/SCsub')
 | 
			
		||||
    SConscript('gles2/SCsub')
 | 
			
		||||
    SConscript('gl_context/SCsub')
 | 
			
		||||
else:
 | 
			
		||||
    SConscript('dummy/SCsub')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								drivers/gles2/SCsub
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								drivers/gles2/SCsub
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
Import('env')
 | 
			
		||||
 | 
			
		||||
env.add_source_files(env.drivers_sources,"*.cpp")
 | 
			
		||||
 | 
			
		||||
SConscript("shaders/SCsub")
 | 
			
		||||
							
								
								
									
										1145
									
								
								drivers/gles2/rasterizer_canvas_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1145
									
								
								drivers/gles2/rasterizer_canvas_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										129
									
								
								drivers/gles2/rasterizer_canvas_gles2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								drivers/gles2/rasterizer_canvas_gles2.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  rasterizer_canvas_gles2.h                                            */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#ifndef RASTERIZERCANVASGLES2_H
 | 
			
		||||
#define RASTERIZERCANVASGLES2_H
 | 
			
		||||
 | 
			
		||||
#include "rasterizer_storage_gles2.h"
 | 
			
		||||
#include "servers/visual/rasterizer.h"
 | 
			
		||||
 | 
			
		||||
#include "shaders/canvas.glsl.gen.h"
 | 
			
		||||
 | 
			
		||||
// #include "shaders/canvas_shadow.glsl.gen.h"
 | 
			
		||||
 | 
			
		||||
class RasterizerSceneGLES2;
 | 
			
		||||
 | 
			
		||||
class RasterizerCanvasGLES2 : public RasterizerCanvas {
 | 
			
		||||
public:
 | 
			
		||||
	struct Uniforms {
 | 
			
		||||
		Transform projection_matrix;
 | 
			
		||||
 | 
			
		||||
		Transform2D modelview_matrix;
 | 
			
		||||
		Transform2D extra_matrix;
 | 
			
		||||
 | 
			
		||||
		Color final_modulate;
 | 
			
		||||
 | 
			
		||||
		float time;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct Data {
 | 
			
		||||
 | 
			
		||||
		GLuint canvas_quad_vertices;
 | 
			
		||||
		GLuint polygon_buffer;
 | 
			
		||||
		GLuint polygon_index_buffer;
 | 
			
		||||
 | 
			
		||||
		uint32_t polygon_buffer_size;
 | 
			
		||||
 | 
			
		||||
		GLuint ninepatch_vertices;
 | 
			
		||||
		GLuint ninepatch_elements;
 | 
			
		||||
 | 
			
		||||
	} data;
 | 
			
		||||
 | 
			
		||||
	struct State {
 | 
			
		||||
		Uniforms uniforms;
 | 
			
		||||
		bool canvas_texscreen_used;
 | 
			
		||||
		CanvasShaderGLES2 canvas_shader;
 | 
			
		||||
		// CanvasShadowShaderGLES3 canvas_shadow_shader;
 | 
			
		||||
 | 
			
		||||
		bool using_texture_rect;
 | 
			
		||||
		bool using_ninepatch;
 | 
			
		||||
 | 
			
		||||
		RID current_tex;
 | 
			
		||||
		RID current_normal;
 | 
			
		||||
		RasterizerStorageGLES2::Texture *current_tex_ptr;
 | 
			
		||||
 | 
			
		||||
		Transform vp;
 | 
			
		||||
 | 
			
		||||
	} state;
 | 
			
		||||
 | 
			
		||||
	typedef void Texture;
 | 
			
		||||
 | 
			
		||||
	RasterizerSceneGLES2 *scene_render;
 | 
			
		||||
 | 
			
		||||
	RasterizerStorageGLES2 *storage;
 | 
			
		||||
 | 
			
		||||
	virtual RID light_internal_create();
 | 
			
		||||
	virtual void light_internal_update(RID p_rid, Light *p_light);
 | 
			
		||||
	virtual void light_internal_free(RID p_rid);
 | 
			
		||||
 | 
			
		||||
	void _set_uniforms();
 | 
			
		||||
 | 
			
		||||
	virtual void canvas_begin();
 | 
			
		||||
	virtual void canvas_end();
 | 
			
		||||
 | 
			
		||||
	_FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false);
 | 
			
		||||
 | 
			
		||||
	_FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
 | 
			
		||||
	_FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
 | 
			
		||||
	_FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
 | 
			
		||||
 | 
			
		||||
	_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip);
 | 
			
		||||
	_FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
 | 
			
		||||
 | 
			
		||||
	virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);
 | 
			
		||||
	virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow);
 | 
			
		||||
 | 
			
		||||
	virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache);
 | 
			
		||||
 | 
			
		||||
	virtual void reset_canvas();
 | 
			
		||||
 | 
			
		||||
	RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map);
 | 
			
		||||
 | 
			
		||||
	void _bind_quad_buffer();
 | 
			
		||||
	void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src);
 | 
			
		||||
 | 
			
		||||
	void initialize();
 | 
			
		||||
	void finalize();
 | 
			
		||||
 | 
			
		||||
	virtual void draw_window_margins(int *black_margin, RID *black_image);
 | 
			
		||||
 | 
			
		||||
	RasterizerCanvasGLES2();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // RASTERIZERCANVASGLES2_H
 | 
			
		||||
							
								
								
									
										383
									
								
								drivers/gles2/rasterizer_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										383
									
								
								drivers/gles2/rasterizer_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,383 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  rasterizer_gles2.cpp                                                 */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#include "rasterizer_gles2.h"
 | 
			
		||||
 | 
			
		||||
#include "gl_context/context_gl.h"
 | 
			
		||||
#include "os/os.h"
 | 
			
		||||
#include "project_settings.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
 | 
			
		||||
#define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
 | 
			
		||||
#define _EXT_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
 | 
			
		||||
#define _EXT_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
 | 
			
		||||
#define _EXT_DEBUG_SOURCE_API_ARB 0x8246
 | 
			
		||||
#define _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
 | 
			
		||||
#define _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
 | 
			
		||||
#define _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
 | 
			
		||||
#define _EXT_DEBUG_SOURCE_APPLICATION_ARB 0x824A
 | 
			
		||||
#define _EXT_DEBUG_SOURCE_OTHER_ARB 0x824B
 | 
			
		||||
#define _EXT_DEBUG_TYPE_ERROR_ARB 0x824C
 | 
			
		||||
#define _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
 | 
			
		||||
#define _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
 | 
			
		||||
#define _EXT_DEBUG_TYPE_PORTABILITY_ARB 0x824F
 | 
			
		||||
#define _EXT_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
 | 
			
		||||
#define _EXT_DEBUG_TYPE_OTHER_ARB 0x8251
 | 
			
		||||
#define _EXT_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
 | 
			
		||||
#define _EXT_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
 | 
			
		||||
#define _EXT_DEBUG_LOGGED_MESSAGES_ARB 0x9145
 | 
			
		||||
#define _EXT_DEBUG_SEVERITY_HIGH_ARB 0x9146
 | 
			
		||||
#define _EXT_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
 | 
			
		||||
#define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148
 | 
			
		||||
#define _EXT_DEBUG_OUTPUT 0x92E0
 | 
			
		||||
 | 
			
		||||
#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
 | 
			
		||||
#define GLAPIENTRY APIENTRY
 | 
			
		||||
#else
 | 
			
		||||
#define GLAPIENTRY
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
 | 
			
		||||
 | 
			
		||||
	if (type == _EXT_DEBUG_TYPE_OTHER_ARB)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB)
 | 
			
		||||
		return; //these are ultimately annoying, so removing for now
 | 
			
		||||
 | 
			
		||||
	char debSource[256], debType[256], debSev[256];
 | 
			
		||||
	if (source == _EXT_DEBUG_SOURCE_API_ARB)
 | 
			
		||||
		strcpy(debSource, "OpenGL");
 | 
			
		||||
	else if (source == _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB)
 | 
			
		||||
		strcpy(debSource, "Windows");
 | 
			
		||||
	else if (source == _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB)
 | 
			
		||||
		strcpy(debSource, "Shader Compiler");
 | 
			
		||||
	else if (source == _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB)
 | 
			
		||||
		strcpy(debSource, "Third Party");
 | 
			
		||||
	else if (source == _EXT_DEBUG_SOURCE_APPLICATION_ARB)
 | 
			
		||||
		strcpy(debSource, "Application");
 | 
			
		||||
	else if (source == _EXT_DEBUG_SOURCE_OTHER_ARB)
 | 
			
		||||
		strcpy(debSource, "Other");
 | 
			
		||||
 | 
			
		||||
	if (type == _EXT_DEBUG_TYPE_ERROR_ARB)
 | 
			
		||||
		strcpy(debType, "Error");
 | 
			
		||||
	else if (type == _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB)
 | 
			
		||||
		strcpy(debType, "Deprecated behavior");
 | 
			
		||||
	else if (type == _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB)
 | 
			
		||||
		strcpy(debType, "Undefined behavior");
 | 
			
		||||
	else if (type == _EXT_DEBUG_TYPE_PORTABILITY_ARB)
 | 
			
		||||
		strcpy(debType, "Portability");
 | 
			
		||||
	else if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB)
 | 
			
		||||
		strcpy(debType, "Performance");
 | 
			
		||||
	else if (type == _EXT_DEBUG_TYPE_OTHER_ARB)
 | 
			
		||||
		strcpy(debType, "Other");
 | 
			
		||||
 | 
			
		||||
	if (severity == _EXT_DEBUG_SEVERITY_HIGH_ARB)
 | 
			
		||||
		strcpy(debSev, "High");
 | 
			
		||||
	else if (severity == _EXT_DEBUG_SEVERITY_MEDIUM_ARB)
 | 
			
		||||
		strcpy(debSev, "Medium");
 | 
			
		||||
	else if (severity == _EXT_DEBUG_SEVERITY_LOW_ARB)
 | 
			
		||||
		strcpy(debSev, "Low");
 | 
			
		||||
 | 
			
		||||
	String output = String() + "GL ERROR: Source: " + debSource + "\tType: " + debType + "\tID: " + itos(id) + "\tSeverity: " + debSev + "\tMessage: " + message;
 | 
			
		||||
 | 
			
		||||
	ERR_PRINTS(output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef void (*DEBUGPROCARB)(GLenum source,
 | 
			
		||||
		GLenum type,
 | 
			
		||||
		GLuint id,
 | 
			
		||||
		GLenum severity,
 | 
			
		||||
		GLsizei length,
 | 
			
		||||
		const char *message,
 | 
			
		||||
		const void *userParam);
 | 
			
		||||
 | 
			
		||||
typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userParam);
 | 
			
		||||
 | 
			
		||||
RasterizerStorage *RasterizerGLES2::get_storage() {
 | 
			
		||||
 | 
			
		||||
	return storage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RasterizerCanvas *RasterizerGLES2::get_canvas() {
 | 
			
		||||
 | 
			
		||||
	return canvas;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RasterizerScene *RasterizerGLES2::get_scene() {
 | 
			
		||||
 | 
			
		||||
	return scene;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::initialize() {
 | 
			
		||||
 | 
			
		||||
	if (OS::get_singleton()->is_stdout_verbose()) {
 | 
			
		||||
		print_line("Using GLES2 video driver");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef GLAD_ENABLED
 | 
			
		||||
	if (!gladLoadGL()) {
 | 
			
		||||
		ERR_PRINT("Error initializing GLAD");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
// GLVersion seems to be used for both GL and GL ES, so we need different version checks for them
 | 
			
		||||
#ifdef OPENGL_ENABLED // OpenGL 3.3 Core Profile required
 | 
			
		||||
	if (GLVersion.major < 3) {
 | 
			
		||||
#else // OpenGL ES 3.0
 | 
			
		||||
	if (GLVersion.major < 2) {
 | 
			
		||||
#endif
 | 
			
		||||
		ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 2.1 / OpenGL ES 2.0, sorry :(\n"
 | 
			
		||||
				  "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault.");
 | 
			
		||||
		OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 2.1 / OpenGL ES 2.0, sorry :(\n"
 | 
			
		||||
								   "Godot Engine will self-destruct as soon as you acknowledge this error message.",
 | 
			
		||||
				"Fatal error: Insufficient OpenGL / GLES driver support");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
// FIXME glDebugMessageCallbackARB does not seem to work on Mac OS X and opengl 3, this may be an issue with our opengl canvas..
 | 
			
		||||
#else
 | 
			
		||||
	if (true || OS::get_singleton()->is_stdout_verbose()) {
 | 
			
		||||
		glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
 | 
			
		||||
		glDebugMessageCallbackARB(_gl_debug_print, NULL);
 | 
			
		||||
		glEnable(_EXT_DEBUG_OUTPUT);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // GLAD_ENABLED
 | 
			
		||||
 | 
			
		||||
		// For debugging
 | 
			
		||||
#ifdef GLES_OVER_GL
 | 
			
		||||
	glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_ERROR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE);
 | 
			
		||||
	glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE);
 | 
			
		||||
	glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE);
 | 
			
		||||
	glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_PORTABILITY_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE);
 | 
			
		||||
	glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_PERFORMANCE_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE);
 | 
			
		||||
	glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_OTHER_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE);
 | 
			
		||||
#endif
 | 
			
		||||
	/* glDebugMessageInsertARB(
 | 
			
		||||
			GL_DEBUG_SOURCE_API_ARB,
 | 
			
		||||
			GL_DEBUG_TYPE_OTHER_ARB, 1,
 | 
			
		||||
			GL_DEBUG_SEVERITY_HIGH_ARB, 5, "hello");
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	const GLubyte *renderer = glGetString(GL_RENDERER);
 | 
			
		||||
	print_line("OpenGL ES 2.0 Renderer: " + String((const char *)renderer));
 | 
			
		||||
	storage->initialize();
 | 
			
		||||
	canvas->initialize();
 | 
			
		||||
	scene->initialize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::begin_frame() {
 | 
			
		||||
	uint64_t tick = OS::get_singleton()->get_ticks_usec();
 | 
			
		||||
 | 
			
		||||
	double delta = double(tick - prev_ticks) / 1000000.0;
 | 
			
		||||
	delta *= Engine::get_singleton()->get_time_scale();
 | 
			
		||||
 | 
			
		||||
	time_total += delta;
 | 
			
		||||
 | 
			
		||||
	if (delta == 0) {
 | 
			
		||||
		//to avoid hiccups
 | 
			
		||||
		delta = 0.001;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prev_ticks = tick;
 | 
			
		||||
 | 
			
		||||
	// double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs");
 | 
			
		||||
	// if (time_total > time_roll_over)
 | 
			
		||||
	//	time_total = 0; //roll over every day (should be customz
 | 
			
		||||
 | 
			
		||||
	storage->frame.time[0] = time_total;
 | 
			
		||||
	storage->frame.time[1] = Math::fmod(time_total, 3600);
 | 
			
		||||
	storage->frame.time[2] = Math::fmod(time_total, 900);
 | 
			
		||||
	storage->frame.time[3] = Math::fmod(time_total, 60);
 | 
			
		||||
	storage->frame.count++;
 | 
			
		||||
	storage->frame.delta = delta;
 | 
			
		||||
 | 
			
		||||
	storage->frame.prev_tick = tick;
 | 
			
		||||
 | 
			
		||||
	storage->update_dirty_resources();
 | 
			
		||||
 | 
			
		||||
	storage->info.render_final = storage->info.render;
 | 
			
		||||
	storage->info.render.reset();
 | 
			
		||||
 | 
			
		||||
	scene->iteration();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::set_current_render_target(RID p_render_target) {
 | 
			
		||||
 | 
			
		||||
	if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
 | 
			
		||||
		// pending clear request. Do that first.
 | 
			
		||||
		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
 | 
			
		||||
		glClearColor(storage->frame.clear_request_color.r,
 | 
			
		||||
				storage->frame.clear_request_color.g,
 | 
			
		||||
				storage->frame.clear_request_color.b,
 | 
			
		||||
				storage->frame.clear_request_color.a);
 | 
			
		||||
		glClear(GL_COLOR_BUFFER_BIT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (p_render_target.is_valid()) {
 | 
			
		||||
		RasterizerStorageGLES2::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
 | 
			
		||||
		storage->frame.current_rt = rt;
 | 
			
		||||
		ERR_FAIL_COND(!rt);
 | 
			
		||||
		storage->frame.clear_request = false;
 | 
			
		||||
 | 
			
		||||
		glViewport(0, 0, rt->width, rt->height);
 | 
			
		||||
	} else {
 | 
			
		||||
		storage->frame.current_rt = NULL;
 | 
			
		||||
		storage->frame.clear_request = false;
 | 
			
		||||
		glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
 | 
			
		||||
		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::restore_render_target() {
 | 
			
		||||
	ERR_FAIL_COND(storage->frame.current_rt == NULL);
 | 
			
		||||
	RasterizerStorageGLES2::RenderTarget *rt = storage->frame.current_rt;
 | 
			
		||||
	glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
 | 
			
		||||
	glViewport(0, 0, rt->width, rt->height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::clear_render_target(const Color &p_color) {
 | 
			
		||||
	ERR_FAIL_COND(!storage->frame.current_rt);
 | 
			
		||||
 | 
			
		||||
	storage->frame.clear_request = true;
 | 
			
		||||
	storage->frame.clear_request_color = p_color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) {
 | 
			
		||||
 | 
			
		||||
	if (p_image.is_null() || p_image->empty())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	int window_w = OS::get_singleton()->get_video_mode(0).width;
 | 
			
		||||
	int window_h = OS::get_singleton()->get_video_mode(0).height;
 | 
			
		||||
 | 
			
		||||
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
 | 
			
		||||
	glViewport(0, 0, window_w, window_h);
 | 
			
		||||
	glDisable(GL_BLEND);
 | 
			
		||||
	glDepthMask(GL_FALSE);
 | 
			
		||||
	glClearColor(p_color.r, p_color.g, p_color.b, p_color.a);
 | 
			
		||||
	glClear(GL_COLOR_BUFFER_BIT);
 | 
			
		||||
 | 
			
		||||
	canvas->canvas_begin();
 | 
			
		||||
 | 
			
		||||
	RID texture = storage->texture_create();
 | 
			
		||||
	storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), VS::TEXTURE_FLAG_FILTER);
 | 
			
		||||
	storage->texture_set_data(texture, p_image);
 | 
			
		||||
 | 
			
		||||
	Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
 | 
			
		||||
	Rect2 screenrect;
 | 
			
		||||
 | 
			
		||||
	screenrect = imgrect;
 | 
			
		||||
	screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor();
 | 
			
		||||
 | 
			
		||||
	RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(texture);
 | 
			
		||||
	glActiveTexture(GL_TEXTURE0);
 | 
			
		||||
	glBindTexture(GL_TEXTURE_2D, t->tex_id);
 | 
			
		||||
	canvas->draw_generic_textured_rect(screenrect, Rect2(0, 0, 1, 1));
 | 
			
		||||
	glBindTexture(GL_TEXTURE_2D, 0);
 | 
			
		||||
	canvas->canvas_end();
 | 
			
		||||
 | 
			
		||||
	storage->free(texture);
 | 
			
		||||
 | 
			
		||||
	OS::get_singleton()->swap_buffers();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen) {
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_COND(storage->frame.current_rt);
 | 
			
		||||
 | 
			
		||||
	RasterizerStorageGLES2::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
 | 
			
		||||
	ERR_FAIL_COND(!rt);
 | 
			
		||||
 | 
			
		||||
	canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
 | 
			
		||||
	canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
 | 
			
		||||
 | 
			
		||||
	canvas->state.canvas_shader.bind();
 | 
			
		||||
 | 
			
		||||
	canvas->canvas_begin();
 | 
			
		||||
	canvas->state.canvas_shader.set_uniform(CanvasShaderGLES2::BLIT_PASS, true);
 | 
			
		||||
	glDisable(GL_BLEND);
 | 
			
		||||
	glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
 | 
			
		||||
	glActiveTexture(GL_TEXTURE0);
 | 
			
		||||
	glBindTexture(GL_TEXTURE_2D, rt->color);
 | 
			
		||||
 | 
			
		||||
	// TODO normals
 | 
			
		||||
 | 
			
		||||
	canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1));
 | 
			
		||||
 | 
			
		||||
	canvas->state.canvas_shader.set_uniform(CanvasShaderGLES2::BLIT_PASS, false);
 | 
			
		||||
 | 
			
		||||
	glBindTexture(GL_TEXTURE_2D, 0);
 | 
			
		||||
	canvas->canvas_end();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::end_frame(bool p_swap_buffers) {
 | 
			
		||||
	if (p_swap_buffers)
 | 
			
		||||
		OS::get_singleton()->swap_buffers();
 | 
			
		||||
	else
 | 
			
		||||
		glFinish();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::finalize() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Rasterizer *RasterizerGLES2::_create_current() {
 | 
			
		||||
 | 
			
		||||
	return memnew(RasterizerGLES2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::make_current() {
 | 
			
		||||
	_create_func = _create_current;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerGLES2::register_config() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RasterizerGLES2::RasterizerGLES2() {
 | 
			
		||||
 | 
			
		||||
	storage = memnew(RasterizerStorageGLES2);
 | 
			
		||||
	canvas = memnew(RasterizerCanvasGLES2);
 | 
			
		||||
	scene = memnew(RasterizerSceneGLES2);
 | 
			
		||||
	canvas->storage = storage;
 | 
			
		||||
	canvas->scene_render = scene;
 | 
			
		||||
	storage->canvas = canvas;
 | 
			
		||||
	scene->storage = storage;
 | 
			
		||||
	storage->scene = scene;
 | 
			
		||||
 | 
			
		||||
	prev_ticks = 0;
 | 
			
		||||
	time_total = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RasterizerGLES2::~RasterizerGLES2() {
 | 
			
		||||
 | 
			
		||||
	memdelete(storage);
 | 
			
		||||
	memdelete(canvas);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								drivers/gles2/rasterizer_gles2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								drivers/gles2/rasterizer_gles2.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  rasterizer_gles2.h                                                   */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#ifndef RASTERIZERGLES2_H
 | 
			
		||||
#define RASTERIZERGLES2_H
 | 
			
		||||
 | 
			
		||||
#include "rasterizer_canvas_gles2.h"
 | 
			
		||||
#include "rasterizer_scene_gles2.h"
 | 
			
		||||
#include "rasterizer_storage_gles2.h"
 | 
			
		||||
#include "servers/visual/rasterizer.h"
 | 
			
		||||
 | 
			
		||||
class RasterizerGLES2 : public Rasterizer {
 | 
			
		||||
 | 
			
		||||
	static Rasterizer *_create_current();
 | 
			
		||||
 | 
			
		||||
	RasterizerStorageGLES2 *storage;
 | 
			
		||||
	RasterizerCanvasGLES2 *canvas;
 | 
			
		||||
	RasterizerSceneGLES2 *scene;
 | 
			
		||||
 | 
			
		||||
	uint64_t prev_ticks;
 | 
			
		||||
	double time_total;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	virtual RasterizerStorage *get_storage();
 | 
			
		||||
	virtual RasterizerCanvas *get_canvas();
 | 
			
		||||
	virtual RasterizerScene *get_scene();
 | 
			
		||||
 | 
			
		||||
	virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale);
 | 
			
		||||
 | 
			
		||||
	virtual void initialize();
 | 
			
		||||
	virtual void begin_frame();
 | 
			
		||||
	virtual void set_current_render_target(RID p_render_target);
 | 
			
		||||
	virtual void restore_render_target();
 | 
			
		||||
	virtual void clear_render_target(const Color &p_color);
 | 
			
		||||
	virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0);
 | 
			
		||||
	virtual void end_frame(bool p_swap_buffers);
 | 
			
		||||
	virtual void finalize();
 | 
			
		||||
 | 
			
		||||
	static void make_current();
 | 
			
		||||
 | 
			
		||||
	static void register_config();
 | 
			
		||||
	RasterizerGLES2();
 | 
			
		||||
	~RasterizerGLES2();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // RASTERIZERGLES2_H
 | 
			
		||||
							
								
								
									
										235
									
								
								drivers/gles2/rasterizer_scene_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								drivers/gles2/rasterizer_scene_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,235 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  rasterizer_scene_gles2.cpp                                           */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#include "rasterizer_scene_gles2.h"
 | 
			
		||||
#include "math_funcs.h"
 | 
			
		||||
#include "os/os.h"
 | 
			
		||||
#include "project_settings.h"
 | 
			
		||||
#include "rasterizer_canvas_gles2.h"
 | 
			
		||||
#include "servers/visual/visual_server_raster.h"
 | 
			
		||||
 | 
			
		||||
#ifndef GLES_OVER_GL
 | 
			
		||||
#define glClearDepth glClearDepthf
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* SHADOW ATLAS API */
 | 
			
		||||
 | 
			
		||||
RID RasterizerSceneGLES2::shadow_atlas_create() {
 | 
			
		||||
 | 
			
		||||
	return RID();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::set_directional_shadow_count(int p_count) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance) {
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
//////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
RID RasterizerSceneGLES2::reflection_atlas_create() {
 | 
			
		||||
	return RID();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::reflection_atlas_set_size(RID p_ref_atlas, int p_size) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
 | 
			
		||||
	return RID();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::reflection_probe_release_atlas_index(RID p_instance) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerSceneGLES2::reflection_probe_instance_needs_redraw(RID p_instance) {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerSceneGLES2::reflection_probe_instance_has_reflection(RID p_instance) {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_instance) {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ENVIRONMENT API */
 | 
			
		||||
 | 
			
		||||
RID RasterizerSceneGLES2::environment_create() {
 | 
			
		||||
 | 
			
		||||
	return RID();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_sky(RID p_env, RID p_sky) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_sky_custom_fov(RID p_env, float p_scale) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_bg_color(RID p_env, const Color &p_color) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_bg_energy(RID p_env, float p_energy) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_sky_contribution) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerSceneGLES2::is_environment(RID p_env) {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VS::EnvironmentBG RasterizerSceneGLES2::environment_get_background(RID p_env) {
 | 
			
		||||
	return VS::ENV_BG_CLEAR_COLOR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RasterizerSceneGLES2::environment_get_canvas_max_layer(RID p_env) {
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RID RasterizerSceneGLES2::light_instance_create(RID p_light) {
 | 
			
		||||
	return RID();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::light_instance_mark_visible(RID p_light_instance) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//////////////////////
 | 
			
		||||
 | 
			
		||||
RID RasterizerSceneGLES2::gi_probe_instance_create() {
 | 
			
		||||
 | 
			
		||||
	return RID();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {
 | 
			
		||||
}
 | 
			
		||||
void RasterizerSceneGLES2::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////
 | 
			
		||||
////////////////////////////
 | 
			
		||||
////////////////////////////
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerSceneGLES2::free(RID p_rid) {
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::initialize() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::iteration() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerSceneGLES2::finalize() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RasterizerSceneGLES2::RasterizerSceneGLES2() {
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										258
									
								
								drivers/gles2/rasterizer_scene_gles2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								drivers/gles2/rasterizer_scene_gles2.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,258 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  rasterizer_scene_gles2.h                                             */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#ifndef RASTERIZERSCENEGLES2_H
 | 
			
		||||
#define RASTERIZERSCENEGLES2_H
 | 
			
		||||
 | 
			
		||||
/* Must come before shaders or the Windows build fails... */
 | 
			
		||||
#include "rasterizer_storage_gles2.h"
 | 
			
		||||
 | 
			
		||||
#include "shaders/scene.glsl.gen.h"
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
#include "drivers/gles3/shaders/cube_to_dp.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/effect_blur.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/exposure.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/resolve.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/scene.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/screen_space_reflection.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/ssao.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/ssao_blur.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/ssao_minify.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/subsurf_scattering.glsl.gen.h"
 | 
			
		||||
#include "drivers/gles3/shaders/tonemap.glsl.gen.h"
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
class RasterizerSceneGLES2 : public RasterizerScene {
 | 
			
		||||
public:
 | 
			
		||||
	RasterizerStorageGLES2 *storage;
 | 
			
		||||
	struct State {
 | 
			
		||||
 | 
			
		||||
		bool texscreen_copied;
 | 
			
		||||
		int current_blend_mode;
 | 
			
		||||
		float current_line_width;
 | 
			
		||||
		int current_depth_draw;
 | 
			
		||||
		bool current_depth_test;
 | 
			
		||||
		GLuint current_main_tex;
 | 
			
		||||
 | 
			
		||||
		SceneShaderGLES2 scene_shader;
 | 
			
		||||
		// CubeToDpShaderGLES3 cube_to_dp_shader;
 | 
			
		||||
		// ResolveShaderGLES3 resolve_shader;
 | 
			
		||||
		// ScreenSpaceReflectionShaderGLES3 ssr_shader;
 | 
			
		||||
		// EffectBlurShaderGLES3 effect_blur_shader;
 | 
			
		||||
		// SubsurfScatteringShaderGLES3 sss_shader;
 | 
			
		||||
		// SsaoMinifyShaderGLES3 ssao_minify_shader;
 | 
			
		||||
		// SsaoShaderGLES3 ssao_shader;
 | 
			
		||||
		// SsaoBlurShaderGLES3 ssao_blur_shader;
 | 
			
		||||
		// ExposureShaderGLES3 exposure_shader;
 | 
			
		||||
		// TonemapShaderGLES3 tonemap_shader;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		struct SceneDataUBO {
 | 
			
		||||
			//this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes
 | 
			
		||||
			float projection_matrix[16];
 | 
			
		||||
			float inv_projection_matrix[16];
 | 
			
		||||
			float camera_inverse_matrix[16];
 | 
			
		||||
			float camera_matrix[16];
 | 
			
		||||
			float ambient_light_color[4];
 | 
			
		||||
			float bg_color[4];
 | 
			
		||||
			float fog_color_enabled[4];
 | 
			
		||||
			float fog_sun_color_amount[4];
 | 
			
		||||
 | 
			
		||||
			float ambient_energy;
 | 
			
		||||
			float bg_energy;
 | 
			
		||||
			float z_offset;
 | 
			
		||||
			float z_slope_scale;
 | 
			
		||||
			float shadow_dual_paraboloid_render_zfar;
 | 
			
		||||
			float shadow_dual_paraboloid_render_side;
 | 
			
		||||
			float viewport_size[2];
 | 
			
		||||
			float screen_pixel_size[2];
 | 
			
		||||
			float shadow_atlas_pixel_size[2];
 | 
			
		||||
			float shadow_directional_pixel_size[2];
 | 
			
		||||
 | 
			
		||||
			float time;
 | 
			
		||||
			float z_far;
 | 
			
		||||
			float reflection_multiplier;
 | 
			
		||||
			float subsurface_scatter_width;
 | 
			
		||||
			float ambient_occlusion_affect_light;
 | 
			
		||||
 | 
			
		||||
			uint32_t fog_depth_enabled;
 | 
			
		||||
			float fog_depth_begin;
 | 
			
		||||
			float fog_depth_curve;
 | 
			
		||||
			uint32_t fog_transmit_enabled;
 | 
			
		||||
			float fog_transmit_curve;
 | 
			
		||||
			uint32_t fog_height_enabled;
 | 
			
		||||
			float fog_height_min;
 | 
			
		||||
			float fog_height_max;
 | 
			
		||||
			float fog_height_curve;
 | 
			
		||||
			// make sure this struct is padded to be a multiple of 16 bytes for webgl
 | 
			
		||||
 | 
			
		||||
		} ubo_data;
 | 
			
		||||
 | 
			
		||||
		GLuint scene_ubo;
 | 
			
		||||
 | 
			
		||||
		struct EnvironmentRadianceUBO {
 | 
			
		||||
 | 
			
		||||
			float transform[16];
 | 
			
		||||
			float ambient_contribution;
 | 
			
		||||
			uint8_t padding[12];
 | 
			
		||||
 | 
			
		||||
		} env_radiance_data;
 | 
			
		||||
 | 
			
		||||
		GLuint env_radiance_ubo;
 | 
			
		||||
 | 
			
		||||
		GLuint sky_verts;
 | 
			
		||||
		GLuint sky_array;
 | 
			
		||||
 | 
			
		||||
		GLuint directional_ubo;
 | 
			
		||||
 | 
			
		||||
		GLuint spot_array_ubo;
 | 
			
		||||
		GLuint omni_array_ubo;
 | 
			
		||||
		GLuint reflection_array_ubo;
 | 
			
		||||
 | 
			
		||||
		GLuint immediate_buffer;
 | 
			
		||||
		GLuint immediate_array;
 | 
			
		||||
 | 
			
		||||
		uint32_t ubo_light_size;
 | 
			
		||||
		uint8_t *spot_array_tmp;
 | 
			
		||||
		uint8_t *omni_array_tmp;
 | 
			
		||||
		uint8_t *reflection_array_tmp;
 | 
			
		||||
 | 
			
		||||
		int max_ubo_lights;
 | 
			
		||||
		int max_forward_lights_per_object;
 | 
			
		||||
		int max_ubo_reflections;
 | 
			
		||||
		int max_skeleton_bones;
 | 
			
		||||
 | 
			
		||||
		bool used_contact_shadows;
 | 
			
		||||
 | 
			
		||||
		int spot_light_count;
 | 
			
		||||
		int omni_light_count;
 | 
			
		||||
		int directional_light_count;
 | 
			
		||||
		int reflection_probe_count;
 | 
			
		||||
 | 
			
		||||
		bool cull_front;
 | 
			
		||||
		bool cull_disabled;
 | 
			
		||||
		bool used_sss;
 | 
			
		||||
		bool used_screen_texture;
 | 
			
		||||
		bool using_contact_shadows;
 | 
			
		||||
 | 
			
		||||
		VS::ViewportDebugDraw debug_draw;
 | 
			
		||||
		*/
 | 
			
		||||
	} state;
 | 
			
		||||
 | 
			
		||||
	/* SHADOW ATLAS API */
 | 
			
		||||
 | 
			
		||||
	RID shadow_atlas_create();
 | 
			
		||||
	void shadow_atlas_set_size(RID p_atlas, int p_size);
 | 
			
		||||
	void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
 | 
			
		||||
	bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
 | 
			
		||||
 | 
			
		||||
	virtual int get_directional_light_shadow_size(RID p_light_intance);
 | 
			
		||||
	virtual void set_directional_shadow_count(int p_count);
 | 
			
		||||
 | 
			
		||||
	/* REFLECTION PROBE ATLAS API */
 | 
			
		||||
 | 
			
		||||
	virtual RID reflection_atlas_create();
 | 
			
		||||
	virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size);
 | 
			
		||||
	virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv);
 | 
			
		||||
 | 
			
		||||
	/* REFLECTION CUBEMAPS */
 | 
			
		||||
 | 
			
		||||
	/* REFLECTION PROBE INSTANCE */
 | 
			
		||||
 | 
			
		||||
	virtual RID reflection_probe_instance_create(RID p_probe);
 | 
			
		||||
	virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
 | 
			
		||||
	virtual void reflection_probe_release_atlas_index(RID p_instance);
 | 
			
		||||
	virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
 | 
			
		||||
	virtual bool reflection_probe_instance_has_reflection(RID p_instance);
 | 
			
		||||
	virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas);
 | 
			
		||||
	virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
 | 
			
		||||
 | 
			
		||||
	/* ENVIRONMENT API */
 | 
			
		||||
	virtual RID environment_create();
 | 
			
		||||
 | 
			
		||||
	virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg);
 | 
			
		||||
	virtual void environment_set_sky(RID p_env, RID p_sky);
 | 
			
		||||
	virtual void environment_set_sky_custom_fov(RID p_env, float p_scale);
 | 
			
		||||
	virtual void environment_set_bg_color(RID p_env, const Color &p_color);
 | 
			
		||||
	virtual void environment_set_bg_energy(RID p_env, float p_energy);
 | 
			
		||||
	virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
 | 
			
		||||
	virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0);
 | 
			
		||||
 | 
			
		||||
	virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);
 | 
			
		||||
	virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);
 | 
			
		||||
	virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale);
 | 
			
		||||
	virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture);
 | 
			
		||||
 | 
			
		||||
	virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness);
 | 
			
		||||
	virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness);
 | 
			
		||||
 | 
			
		||||
	virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
 | 
			
		||||
 | 
			
		||||
	virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp);
 | 
			
		||||
 | 
			
		||||
	virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount);
 | 
			
		||||
	virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve);
 | 
			
		||||
	virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve);
 | 
			
		||||
 | 
			
		||||
	virtual bool is_environment(RID p_env);
 | 
			
		||||
 | 
			
		||||
	virtual VS::EnvironmentBG environment_get_background(RID p_env);
 | 
			
		||||
	virtual int environment_get_canvas_max_layer(RID p_env);
 | 
			
		||||
 | 
			
		||||
	/* LIGHT INSTANCE */
 | 
			
		||||
	virtual RID light_instance_create(RID p_light);
 | 
			
		||||
	virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
 | 
			
		||||
	virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
 | 
			
		||||
	virtual void light_instance_mark_visible(RID p_light_instance);
 | 
			
		||||
 | 
			
		||||
	/* REFLECTION INSTANCE */
 | 
			
		||||
 | 
			
		||||
	virtual RID gi_probe_instance_create();
 | 
			
		||||
	virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data);
 | 
			
		||||
	virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
 | 
			
		||||
	virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds);
 | 
			
		||||
 | 
			
		||||
	/* RENDER LIST */
 | 
			
		||||
 | 
			
		||||
	virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
 | 
			
		||||
	virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
 | 
			
		||||
	virtual bool free(RID p_rid);
 | 
			
		||||
 | 
			
		||||
	virtual void set_scene_pass(uint64_t p_pass);
 | 
			
		||||
	virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw);
 | 
			
		||||
 | 
			
		||||
	void iteration();
 | 
			
		||||
	void initialize();
 | 
			
		||||
	void finalize();
 | 
			
		||||
	RasterizerSceneGLES2();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // RASTERIZERSCENEGLES2_H
 | 
			
		||||
							
								
								
									
										2061
									
								
								drivers/gles2/rasterizer_storage_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2061
									
								
								drivers/gles2/rasterizer_storage_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										838
									
								
								drivers/gles2/rasterizer_storage_gles2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										838
									
								
								drivers/gles2/rasterizer_storage_gles2.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,838 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  rasterizer_storage_gles2.h                                           */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#ifndef RASTERIZERSTORAGEGLES2_H
 | 
			
		||||
#define RASTERIZERSTORAGEGLES2_H
 | 
			
		||||
 | 
			
		||||
#include "self_list.h"
 | 
			
		||||
#include "servers/visual/rasterizer.h"
 | 
			
		||||
#include "servers/visual/shader_language.h"
 | 
			
		||||
#include "shader_compiler_gles2.h"
 | 
			
		||||
#include "shader_gles2.h"
 | 
			
		||||
 | 
			
		||||
#include "shaders/copy.glsl.gen.h"
 | 
			
		||||
/*
 | 
			
		||||
#include "shaders/blend_shape.glsl.gen.h"
 | 
			
		||||
#include "shaders/canvas.glsl.gen.h"
 | 
			
		||||
#include "shaders/copy.glsl.gen.h"
 | 
			
		||||
#include "shaders/cubemap_filter.glsl.gen.h"
 | 
			
		||||
#include "shaders/particles.glsl.gen.h"
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
class RasterizerCanvasGLES2;
 | 
			
		||||
class RasterizerSceneGLES2;
 | 
			
		||||
 | 
			
		||||
class RasterizerStorageGLES2 : public RasterizerStorage {
 | 
			
		||||
public:
 | 
			
		||||
	RasterizerCanvasGLES2 *canvas;
 | 
			
		||||
	RasterizerSceneGLES2 *scene;
 | 
			
		||||
 | 
			
		||||
	static GLuint system_fbo;
 | 
			
		||||
 | 
			
		||||
	struct Config {
 | 
			
		||||
 | 
			
		||||
		bool shrink_textures_x2;
 | 
			
		||||
		bool use_fast_texture_filter;
 | 
			
		||||
		// bool use_anisotropic_filter;
 | 
			
		||||
 | 
			
		||||
		bool hdr_supported;
 | 
			
		||||
 | 
			
		||||
		bool use_rgba_2d_shadows;
 | 
			
		||||
 | 
			
		||||
		// float anisotropic_level;
 | 
			
		||||
 | 
			
		||||
		int max_texture_image_units;
 | 
			
		||||
		int max_texture_size;
 | 
			
		||||
 | 
			
		||||
		bool generate_wireframes;
 | 
			
		||||
 | 
			
		||||
		bool use_texture_array_environment;
 | 
			
		||||
 | 
			
		||||
		Set<String> extensions;
 | 
			
		||||
 | 
			
		||||
		bool keep_original_textures;
 | 
			
		||||
 | 
			
		||||
		bool no_depth_prepass;
 | 
			
		||||
		bool force_vertex_shading;
 | 
			
		||||
	} config;
 | 
			
		||||
 | 
			
		||||
	struct Resources {
 | 
			
		||||
 | 
			
		||||
		GLuint white_tex;
 | 
			
		||||
		GLuint black_tex;
 | 
			
		||||
		GLuint normal_tex;
 | 
			
		||||
		GLuint aniso_tex;
 | 
			
		||||
 | 
			
		||||
		GLuint quadie;
 | 
			
		||||
		GLuint quadie_array;
 | 
			
		||||
 | 
			
		||||
	} resources;
 | 
			
		||||
 | 
			
		||||
	mutable struct Shaders {
 | 
			
		||||
 | 
			
		||||
		ShaderCompilerGLES2 compiler;
 | 
			
		||||
 | 
			
		||||
		CopyShaderGLES2 copy;
 | 
			
		||||
 | 
			
		||||
		ShaderCompilerGLES2::IdentifierActions actions_canvas;
 | 
			
		||||
		ShaderCompilerGLES2::IdentifierActions actions_scene;
 | 
			
		||||
		ShaderCompilerGLES2::IdentifierActions actions_particles;
 | 
			
		||||
 | 
			
		||||
	} shaders;
 | 
			
		||||
 | 
			
		||||
	struct Info {
 | 
			
		||||
 | 
			
		||||
		uint64_t texture_mem;
 | 
			
		||||
		uint64_t vertex_mem;
 | 
			
		||||
 | 
			
		||||
		struct Render {
 | 
			
		||||
			uint32_t object_count;
 | 
			
		||||
			uint32_t draw_call_count;
 | 
			
		||||
			uint32_t material_switch_count;
 | 
			
		||||
			uint32_t surface_switch_count;
 | 
			
		||||
			uint32_t shader_rebind_count;
 | 
			
		||||
			uint32_t vertices_count;
 | 
			
		||||
 | 
			
		||||
			void reset() {
 | 
			
		||||
				object_count = 0;
 | 
			
		||||
				draw_call_count = 0;
 | 
			
		||||
				material_switch_count = 0;
 | 
			
		||||
				surface_switch_count = 0;
 | 
			
		||||
				shader_rebind_count = 0;
 | 
			
		||||
				vertices_count = 0;
 | 
			
		||||
			}
 | 
			
		||||
		} render, render_final, snap;
 | 
			
		||||
 | 
			
		||||
		Info() {
 | 
			
		||||
 | 
			
		||||
			texture_mem = 0;
 | 
			
		||||
			vertex_mem = 0;
 | 
			
		||||
			render.reset();
 | 
			
		||||
			render_final.reset();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	} info;
 | 
			
		||||
 | 
			
		||||
	/////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
	//////////////////////////////////DATA///////////////////////////////////////////////////
 | 
			
		||||
	/////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
	/////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
	//////////////////////////////////API////////////////////////////////////////////////////
 | 
			
		||||
	/////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
	/* TEXTURE API */
 | 
			
		||||
 | 
			
		||||
	struct RenderTarget;
 | 
			
		||||
 | 
			
		||||
	struct Texture : RID_Data {
 | 
			
		||||
 | 
			
		||||
		Texture *proxy;
 | 
			
		||||
		Set<Texture *> proxy_owners;
 | 
			
		||||
 | 
			
		||||
		String path;
 | 
			
		||||
		uint32_t flags;
 | 
			
		||||
		int width, height;
 | 
			
		||||
		int alloc_width, alloc_height;
 | 
			
		||||
		Image::Format format;
 | 
			
		||||
 | 
			
		||||
		GLenum target;
 | 
			
		||||
		GLenum gl_format_cache;
 | 
			
		||||
		GLenum gl_internal_format_cache;
 | 
			
		||||
		GLenum gl_type_cache;
 | 
			
		||||
 | 
			
		||||
		int data_size;
 | 
			
		||||
		int total_data_size;
 | 
			
		||||
		bool ignore_mipmaps;
 | 
			
		||||
 | 
			
		||||
		int mipmaps;
 | 
			
		||||
 | 
			
		||||
		bool active;
 | 
			
		||||
		GLenum tex_id;
 | 
			
		||||
 | 
			
		||||
		uint16_t stored_cube_sides;
 | 
			
		||||
 | 
			
		||||
		RenderTarget *render_target;
 | 
			
		||||
 | 
			
		||||
		Ref<Image> images[6];
 | 
			
		||||
 | 
			
		||||
		Texture() {
 | 
			
		||||
			flags = 0;
 | 
			
		||||
			width = 0;
 | 
			
		||||
			height = 0;
 | 
			
		||||
			alloc_width = 0;
 | 
			
		||||
			alloc_height = 0;
 | 
			
		||||
			format = Image::FORMAT_L8;
 | 
			
		||||
 | 
			
		||||
			target = 0;
 | 
			
		||||
 | 
			
		||||
			data_size = 0;
 | 
			
		||||
			total_data_size = 0;
 | 
			
		||||
			ignore_mipmaps = false;
 | 
			
		||||
 | 
			
		||||
			active = false;
 | 
			
		||||
 | 
			
		||||
			tex_id = 0;
 | 
			
		||||
 | 
			
		||||
			stored_cube_sides = 0;
 | 
			
		||||
 | 
			
		||||
			proxy = NULL;
 | 
			
		||||
 | 
			
		||||
			render_target = NULL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_ALWAYS_INLINE_ Texture *get_ptr() {
 | 
			
		||||
			if (proxy) {
 | 
			
		||||
				return proxy; //->get_ptr(); only one level of indirection, else not inlining possible.
 | 
			
		||||
			} else {
 | 
			
		||||
				return this;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		~Texture() {
 | 
			
		||||
			if (tex_id != 0) {
 | 
			
		||||
				glDeleteTextures(1, &tex_id);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) {
 | 
			
		||||
				E->get()->proxy = NULL;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (proxy) {
 | 
			
		||||
				proxy->proxy_owners.erase(this);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	mutable RID_Owner<Texture> texture_owner;
 | 
			
		||||
 | 
			
		||||
	Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type);
 | 
			
		||||
 | 
			
		||||
	virtual RID texture_create();
 | 
			
		||||
	virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
 | 
			
		||||
	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
 | 
			
		||||
	virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const;
 | 
			
		||||
	virtual void texture_set_flags(RID p_texture, uint32_t p_flags);
 | 
			
		||||
	virtual uint32_t texture_get_flags(RID p_texture) const;
 | 
			
		||||
	virtual Image::Format texture_get_format(RID p_texture) const;
 | 
			
		||||
	virtual uint32_t texture_get_texid(RID p_texture) const;
 | 
			
		||||
	virtual uint32_t texture_get_width(RID p_texture) const;
 | 
			
		||||
	virtual uint32_t texture_get_height(RID p_texture) const;
 | 
			
		||||
	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height);
 | 
			
		||||
 | 
			
		||||
	virtual void texture_set_path(RID p_texture, const String &p_path);
 | 
			
		||||
	virtual String texture_get_path(RID p_texture) const;
 | 
			
		||||
 | 
			
		||||
	virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable);
 | 
			
		||||
 | 
			
		||||
	virtual void texture_debug_usage(List<VS::TextureInfo> *r_info);
 | 
			
		||||
 | 
			
		||||
	virtual RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const;
 | 
			
		||||
 | 
			
		||||
	virtual void textures_keep_original(bool p_enable);
 | 
			
		||||
 | 
			
		||||
	virtual void texture_set_proxy(RID p_texture, RID p_proxy);
 | 
			
		||||
 | 
			
		||||
	virtual void texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
 | 
			
		||||
	virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
 | 
			
		||||
	virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
 | 
			
		||||
 | 
			
		||||
	/* SKY API */
 | 
			
		||||
 | 
			
		||||
	virtual RID sky_create();
 | 
			
		||||
	virtual void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
 | 
			
		||||
 | 
			
		||||
	/* SHADER API */
 | 
			
		||||
 | 
			
		||||
	struct Material;
 | 
			
		||||
 | 
			
		||||
	struct Shader : public RID_Data {
 | 
			
		||||
 | 
			
		||||
		RID self;
 | 
			
		||||
 | 
			
		||||
		VS::ShaderMode mode;
 | 
			
		||||
		ShaderGLES2 *shader;
 | 
			
		||||
		String code;
 | 
			
		||||
		SelfList<Material>::List materials;
 | 
			
		||||
 | 
			
		||||
		Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
 | 
			
		||||
 | 
			
		||||
		uint32_t texture_count;
 | 
			
		||||
 | 
			
		||||
		uint32_t custom_code_id;
 | 
			
		||||
		uint32_t version;
 | 
			
		||||
 | 
			
		||||
		SelfList<Shader> dirty_list;
 | 
			
		||||
 | 
			
		||||
		Map<StringName, RID> default_textures;
 | 
			
		||||
 | 
			
		||||
		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 | 
			
		||||
 | 
			
		||||
		bool valid;
 | 
			
		||||
 | 
			
		||||
		String path;
 | 
			
		||||
 | 
			
		||||
		struct CanvasItem {
 | 
			
		||||
 | 
			
		||||
			enum BlendMode {
 | 
			
		||||
				BLEND_MODE_MIX,
 | 
			
		||||
				BLEND_MODE_ADD,
 | 
			
		||||
				BLEND_MODE_SUB,
 | 
			
		||||
				BLEND_MODE_MUL,
 | 
			
		||||
				BLEND_MODE_PMALPHA,
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			int blend_mode;
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
			enum LightMode {
 | 
			
		||||
				LIGHT_MODE_NORMAL,
 | 
			
		||||
				LIGHT_MODE_UNSHADED,
 | 
			
		||||
				LIGHT_MODE_LIGHT_ONLY
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			int light_mode;
 | 
			
		||||
			*/
 | 
			
		||||
			bool uses_screen_texture;
 | 
			
		||||
			bool uses_screen_uv;
 | 
			
		||||
			bool uses_time;
 | 
			
		||||
 | 
			
		||||
		} canvas_item;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		struct Spatial {
 | 
			
		||||
 | 
			
		||||
			enum BlendMode {
 | 
			
		||||
				BLEND_MODE_MIX,
 | 
			
		||||
				BLEND_MODE_ADD,
 | 
			
		||||
				BLEND_MODE_SUB,
 | 
			
		||||
				BLEND_MODE_MUL,
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			int blend_mode;
 | 
			
		||||
 | 
			
		||||
			enum DepthDrawMode {
 | 
			
		||||
				DEPTH_DRAW_OPAQUE,
 | 
			
		||||
				DEPTH_DRAW_ALWAYS,
 | 
			
		||||
				DEPTH_DRAW_NEVER,
 | 
			
		||||
				DEPTH_DRAW_ALPHA_PREPASS,
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			int depth_draw_mode;
 | 
			
		||||
 | 
			
		||||
			enum CullMode {
 | 
			
		||||
				CULL_MODE_FRONT,
 | 
			
		||||
				CULL_MODE_BACK,
 | 
			
		||||
				CULL_MODE_DISABLED,
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			int cull_mode;
 | 
			
		||||
 | 
			
		||||
			bool uses_alpha;
 | 
			
		||||
			bool uses_alpha_scissor;
 | 
			
		||||
			bool unshaded;
 | 
			
		||||
			bool no_depth_test;
 | 
			
		||||
			bool uses_vertex;
 | 
			
		||||
			bool uses_discard;
 | 
			
		||||
			bool uses_sss;
 | 
			
		||||
			bool uses_screen_texture;
 | 
			
		||||
			bool uses_time;
 | 
			
		||||
			bool writes_modelview_or_projection;
 | 
			
		||||
			bool uses_vertex_lighting;
 | 
			
		||||
			bool uses_world_coordinates;
 | 
			
		||||
 | 
			
		||||
		} spatial;
 | 
			
		||||
 | 
			
		||||
		struct Particles {
 | 
			
		||||
 | 
			
		||||
		} particles;
 | 
			
		||||
		*/
 | 
			
		||||
 | 
			
		||||
		bool uses_vertex_time;
 | 
			
		||||
		bool uses_fragment_time;
 | 
			
		||||
 | 
			
		||||
		Shader() :
 | 
			
		||||
				dirty_list(this) {
 | 
			
		||||
 | 
			
		||||
			shader = NULL;
 | 
			
		||||
			valid = false;
 | 
			
		||||
			custom_code_id = 0;
 | 
			
		||||
			version = 1;
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	mutable RID_Owner<Shader> shader_owner;
 | 
			
		||||
	mutable SelfList<Shader>::List _shader_dirty_list;
 | 
			
		||||
 | 
			
		||||
	void _shader_make_dirty(Shader *p_shader);
 | 
			
		||||
 | 
			
		||||
	virtual RID shader_create();
 | 
			
		||||
 | 
			
		||||
	virtual void shader_set_code(RID p_shader, const String &p_code);
 | 
			
		||||
	virtual String shader_get_code(RID p_shader) const;
 | 
			
		||||
	virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
 | 
			
		||||
 | 
			
		||||
	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
 | 
			
		||||
	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
 | 
			
		||||
 | 
			
		||||
	void _update_shader(Shader *p_shader) const;
 | 
			
		||||
	void update_dirty_shaders();
 | 
			
		||||
 | 
			
		||||
	/* COMMON MATERIAL API */
 | 
			
		||||
 | 
			
		||||
	struct Material : public RID_Data {
 | 
			
		||||
 | 
			
		||||
		Shader *shader;
 | 
			
		||||
		Map<StringName, Variant> params;
 | 
			
		||||
		SelfList<Material> list;
 | 
			
		||||
		SelfList<Material> dirty_list;
 | 
			
		||||
		Vector<RID> textures;
 | 
			
		||||
		float line_width;
 | 
			
		||||
		int render_priority;
 | 
			
		||||
 | 
			
		||||
		RID next_pass;
 | 
			
		||||
 | 
			
		||||
		uint32_t index;
 | 
			
		||||
		uint64_t last_pass;
 | 
			
		||||
 | 
			
		||||
		Map<Geometry *, int> geometry_owners;
 | 
			
		||||
		Map<RasterizerScene::InstanceBase *, int> instance_owners;
 | 
			
		||||
 | 
			
		||||
		bool can_cast_shadow_cache;
 | 
			
		||||
		bool is_animated_cache;
 | 
			
		||||
 | 
			
		||||
		Material() :
 | 
			
		||||
				list(this),
 | 
			
		||||
				dirty_list(this) {
 | 
			
		||||
			can_cast_shadow_cache = false;
 | 
			
		||||
			is_animated_cache = false;
 | 
			
		||||
			shader = NULL;
 | 
			
		||||
			line_width = 1.0;
 | 
			
		||||
			last_pass = 0;
 | 
			
		||||
			render_priority = 0;
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	mutable SelfList<Material>::List _material_dirty_list;
 | 
			
		||||
	void _material_make_dirty(Material *p_material) const;
 | 
			
		||||
 | 
			
		||||
	mutable RID_Owner<Material> material_owner;
 | 
			
		||||
 | 
			
		||||
	virtual RID material_create();
 | 
			
		||||
 | 
			
		||||
	virtual void material_set_shader(RID p_material, RID p_shader);
 | 
			
		||||
	virtual RID material_get_shader(RID p_material) const;
 | 
			
		||||
 | 
			
		||||
	virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
 | 
			
		||||
	virtual Variant material_get_param(RID p_material, const StringName &p_param) const;
 | 
			
		||||
 | 
			
		||||
	virtual void material_set_line_width(RID p_material, float p_width);
 | 
			
		||||
	virtual void material_set_next_pass(RID p_material, RID p_next_material);
 | 
			
		||||
 | 
			
		||||
	virtual bool material_is_animated(RID p_material);
 | 
			
		||||
	virtual bool material_casts_shadows(RID p_material);
 | 
			
		||||
 | 
			
		||||
	virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
 | 
			
		||||
	virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
 | 
			
		||||
 | 
			
		||||
	virtual void material_set_render_priority(RID p_material, int priority);
 | 
			
		||||
 | 
			
		||||
	void update_dirty_materials();
 | 
			
		||||
 | 
			
		||||
	/* MESH API */
 | 
			
		||||
	virtual RID mesh_create();
 | 
			
		||||
 | 
			
		||||
	virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>());
 | 
			
		||||
 | 
			
		||||
	virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount);
 | 
			
		||||
	virtual int mesh_get_blend_shape_count(RID p_mesh) const;
 | 
			
		||||
 | 
			
		||||
	virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode);
 | 
			
		||||
	virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
 | 
			
		||||
 | 
			
		||||
	virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data);
 | 
			
		||||
 | 
			
		||||
	virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
 | 
			
		||||
	virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
 | 
			
		||||
 | 
			
		||||
	virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const;
 | 
			
		||||
	virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const;
 | 
			
		||||
 | 
			
		||||
	virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const;
 | 
			
		||||
	virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const;
 | 
			
		||||
 | 
			
		||||
	virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const;
 | 
			
		||||
	virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const;
 | 
			
		||||
 | 
			
		||||
	virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const;
 | 
			
		||||
	virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const;
 | 
			
		||||
	virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const;
 | 
			
		||||
 | 
			
		||||
	virtual void mesh_remove_surface(RID p_mesh, int p_surface);
 | 
			
		||||
	virtual int mesh_get_surface_count(RID p_mesh) const;
 | 
			
		||||
 | 
			
		||||
	virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb);
 | 
			
		||||
	virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
 | 
			
		||||
 | 
			
		||||
	virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const;
 | 
			
		||||
	virtual void mesh_clear(RID p_mesh);
 | 
			
		||||
 | 
			
		||||
	/* MULTIMESH API */
 | 
			
		||||
 | 
			
		||||
	virtual RID multimesh_create();
 | 
			
		||||
 | 
			
		||||
	virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format);
 | 
			
		||||
	virtual int multimesh_get_instance_count(RID p_multimesh) const;
 | 
			
		||||
 | 
			
		||||
	virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
 | 
			
		||||
	virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
 | 
			
		||||
	virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
 | 
			
		||||
	virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
 | 
			
		||||
 | 
			
		||||
	virtual RID multimesh_get_mesh(RID p_multimesh) const;
 | 
			
		||||
 | 
			
		||||
	virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
 | 
			
		||||
	virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
 | 
			
		||||
	virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
 | 
			
		||||
 | 
			
		||||
	virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
 | 
			
		||||
	virtual int multimesh_get_visible_instances(RID p_multimesh) const;
 | 
			
		||||
 | 
			
		||||
	virtual AABB multimesh_get_aabb(RID p_multimesh) const;
 | 
			
		||||
 | 
			
		||||
	void update_dirty_multimeshes();
 | 
			
		||||
 | 
			
		||||
	/* IMMEDIATE API */
 | 
			
		||||
 | 
			
		||||
	virtual RID immediate_create();
 | 
			
		||||
	virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID());
 | 
			
		||||
	virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex);
 | 
			
		||||
	virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal);
 | 
			
		||||
	virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent);
 | 
			
		||||
	virtual void immediate_color(RID p_immediate, const Color &p_color);
 | 
			
		||||
	virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv);
 | 
			
		||||
	virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv);
 | 
			
		||||
	virtual void immediate_end(RID p_immediate);
 | 
			
		||||
	virtual void immediate_clear(RID p_immediate);
 | 
			
		||||
	virtual void immediate_set_material(RID p_immediate, RID p_material);
 | 
			
		||||
	virtual RID immediate_get_material(RID p_immediate) const;
 | 
			
		||||
	virtual AABB immediate_get_aabb(RID p_immediate) const;
 | 
			
		||||
 | 
			
		||||
	/* SKELETON API */
 | 
			
		||||
 | 
			
		||||
	void update_dirty_skeletons();
 | 
			
		||||
 | 
			
		||||
	virtual RID skeleton_create();
 | 
			
		||||
	virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
 | 
			
		||||
	virtual int skeleton_get_bone_count(RID p_skeleton) const;
 | 
			
		||||
	virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform);
 | 
			
		||||
	virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
 | 
			
		||||
	virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
 | 
			
		||||
	virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
 | 
			
		||||
 | 
			
		||||
	/* Light API */
 | 
			
		||||
 | 
			
		||||
	virtual RID light_create(VS::LightType p_type);
 | 
			
		||||
 | 
			
		||||
	virtual void light_set_color(RID p_light, const Color &p_color);
 | 
			
		||||
	virtual void light_set_param(RID p_light, VS::LightParam p_param, float p_value);
 | 
			
		||||
	virtual void light_set_shadow(RID p_light, bool p_enabled);
 | 
			
		||||
	virtual void light_set_shadow_color(RID p_light, const Color &p_color);
 | 
			
		||||
	virtual void light_set_projector(RID p_light, RID p_texture);
 | 
			
		||||
	virtual void light_set_negative(RID p_light, bool p_enable);
 | 
			
		||||
	virtual void light_set_cull_mask(RID p_light, uint32_t p_mask);
 | 
			
		||||
	virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
 | 
			
		||||
 | 
			
		||||
	virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode);
 | 
			
		||||
	virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail);
 | 
			
		||||
 | 
			
		||||
	virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode);
 | 
			
		||||
	virtual void light_directional_set_blend_splits(RID p_light, bool p_enable);
 | 
			
		||||
	virtual bool light_directional_get_blend_splits(RID p_light) const;
 | 
			
		||||
 | 
			
		||||
	virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
 | 
			
		||||
	virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
 | 
			
		||||
 | 
			
		||||
	virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode);
 | 
			
		||||
	virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
 | 
			
		||||
 | 
			
		||||
	virtual bool light_has_shadow(RID p_light) const;
 | 
			
		||||
 | 
			
		||||
	virtual VS::LightType light_get_type(RID p_light) const;
 | 
			
		||||
	virtual float light_get_param(RID p_light, VS::LightParam p_param);
 | 
			
		||||
	virtual Color light_get_color(RID p_light);
 | 
			
		||||
 | 
			
		||||
	virtual AABB light_get_aabb(RID p_light) const;
 | 
			
		||||
	virtual uint64_t light_get_version(RID p_light) const;
 | 
			
		||||
 | 
			
		||||
	/* PROBE API */
 | 
			
		||||
	virtual RID reflection_probe_create();
 | 
			
		||||
 | 
			
		||||
	virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode);
 | 
			
		||||
	virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity);
 | 
			
		||||
	virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient);
 | 
			
		||||
	virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy);
 | 
			
		||||
	virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib);
 | 
			
		||||
	virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance);
 | 
			
		||||
	virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents);
 | 
			
		||||
	virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset);
 | 
			
		||||
	virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable);
 | 
			
		||||
	virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
 | 
			
		||||
	virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
 | 
			
		||||
	virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
 | 
			
		||||
 | 
			
		||||
	virtual AABB reflection_probe_get_aabb(RID p_probe) const;
 | 
			
		||||
	virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
 | 
			
		||||
	virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual Vector3 reflection_probe_get_extents(RID p_probe) const;
 | 
			
		||||
	virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
 | 
			
		||||
	virtual float reflection_probe_get_origin_max_distance(RID p_probe) const;
 | 
			
		||||
	virtual bool reflection_probe_renders_shadows(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	/* GI PROBE API */
 | 
			
		||||
	virtual RID gi_probe_create();
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds);
 | 
			
		||||
	virtual AABB gi_probe_get_bounds(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_cell_size(RID p_probe, float p_size);
 | 
			
		||||
	virtual float gi_probe_get_cell_size(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform);
 | 
			
		||||
	virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data);
 | 
			
		||||
	virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range);
 | 
			
		||||
	virtual int gi_probe_get_dynamic_range(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_energy(RID p_probe, float p_range);
 | 
			
		||||
	virtual float gi_probe_get_energy(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_bias(RID p_probe, float p_range);
 | 
			
		||||
	virtual float gi_probe_get_bias(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_normal_bias(RID p_probe, float p_range);
 | 
			
		||||
	virtual float gi_probe_get_normal_bias(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_propagation(RID p_probe, float p_range);
 | 
			
		||||
	virtual float gi_probe_get_propagation(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_interior(RID p_probe, bool p_enable);
 | 
			
		||||
	virtual bool gi_probe_is_interior(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual void gi_probe_set_compress(RID p_probe, bool p_enable);
 | 
			
		||||
	virtual bool gi_probe_is_compressed(RID p_probe) const;
 | 
			
		||||
 | 
			
		||||
	virtual uint32_t gi_probe_get_version(RID p_probe);
 | 
			
		||||
 | 
			
		||||
	virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const;
 | 
			
		||||
	virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression);
 | 
			
		||||
	virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data);
 | 
			
		||||
 | 
			
		||||
	/* LIGHTMAP */
 | 
			
		||||
 | 
			
		||||
	virtual RID lightmap_capture_create();
 | 
			
		||||
	virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds);
 | 
			
		||||
	virtual AABB lightmap_capture_get_bounds(RID p_capture) const;
 | 
			
		||||
	virtual void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree);
 | 
			
		||||
	virtual PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const;
 | 
			
		||||
	virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform);
 | 
			
		||||
	virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const;
 | 
			
		||||
	virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv);
 | 
			
		||||
	virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const;
 | 
			
		||||
	virtual void lightmap_capture_set_energy(RID p_capture, float p_energy);
 | 
			
		||||
	virtual float lightmap_capture_get_energy(RID p_capture) const;
 | 
			
		||||
	virtual const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const;
 | 
			
		||||
 | 
			
		||||
	/* PARTICLES */
 | 
			
		||||
	void update_particles();
 | 
			
		||||
 | 
			
		||||
	virtual RID particles_create();
 | 
			
		||||
 | 
			
		||||
	virtual void particles_set_emitting(RID p_particles, bool p_emitting);
 | 
			
		||||
	virtual bool particles_get_emitting(RID p_particles);
 | 
			
		||||
 | 
			
		||||
	virtual void particles_set_amount(RID p_particles, int p_amount);
 | 
			
		||||
	virtual void particles_set_lifetime(RID p_particles, float p_lifetime);
 | 
			
		||||
	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot);
 | 
			
		||||
	virtual void particles_set_pre_process_time(RID p_particles, float p_time);
 | 
			
		||||
	virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio);
 | 
			
		||||
	virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio);
 | 
			
		||||
	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb);
 | 
			
		||||
	virtual void particles_set_speed_scale(RID p_particles, float p_scale);
 | 
			
		||||
	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
 | 
			
		||||
	virtual void particles_set_process_material(RID p_particles, RID p_material);
 | 
			
		||||
	virtual void particles_set_fixed_fps(RID p_particles, int p_fps);
 | 
			
		||||
	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable);
 | 
			
		||||
	virtual void particles_restart(RID p_particles);
 | 
			
		||||
 | 
			
		||||
	virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order);
 | 
			
		||||
 | 
			
		||||
	virtual void particles_set_draw_passes(RID p_particles, int p_passes);
 | 
			
		||||
	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh);
 | 
			
		||||
 | 
			
		||||
	virtual void particles_request_process(RID p_particles);
 | 
			
		||||
	virtual AABB particles_get_current_aabb(RID p_particles);
 | 
			
		||||
	virtual AABB particles_get_aabb(RID p_particles) const;
 | 
			
		||||
 | 
			
		||||
	virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform);
 | 
			
		||||
 | 
			
		||||
	virtual int particles_get_draw_passes(RID p_particles) const;
 | 
			
		||||
	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const;
 | 
			
		||||
 | 
			
		||||
	/* INSTANCE */
 | 
			
		||||
 | 
			
		||||
	virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
 | 
			
		||||
	virtual void instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
 | 
			
		||||
 | 
			
		||||
	virtual void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
 | 
			
		||||
	virtual void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
 | 
			
		||||
 | 
			
		||||
	/* RENDER TARGET */
 | 
			
		||||
 | 
			
		||||
	struct RenderTarget : public RID_Data {
 | 
			
		||||
		GLuint fbo;
 | 
			
		||||
 | 
			
		||||
		GLuint color;
 | 
			
		||||
		GLuint depth;
 | 
			
		||||
 | 
			
		||||
		// TODO post processing effects?
 | 
			
		||||
 | 
			
		||||
		// TODO HDR?
 | 
			
		||||
 | 
			
		||||
		// TODO this is hardcoded for texscreen copies for now
 | 
			
		||||
 | 
			
		||||
		struct Effect {
 | 
			
		||||
			GLuint fbo;
 | 
			
		||||
			int width;
 | 
			
		||||
			int height;
 | 
			
		||||
 | 
			
		||||
			GLuint color;
 | 
			
		||||
 | 
			
		||||
			Effect() {
 | 
			
		||||
				fbo = 0;
 | 
			
		||||
				width = 0;
 | 
			
		||||
				height = 0;
 | 
			
		||||
				color = 0;
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		Effect copy_screen_effect;
 | 
			
		||||
 | 
			
		||||
		int width, height;
 | 
			
		||||
 | 
			
		||||
		bool flags[RENDER_TARGET_FLAG_MAX];
 | 
			
		||||
 | 
			
		||||
		bool used_in_frame;
 | 
			
		||||
		VS::ViewportMSAA msaa;
 | 
			
		||||
 | 
			
		||||
		RID texture;
 | 
			
		||||
 | 
			
		||||
		RenderTarget() {
 | 
			
		||||
			fbo = 0;
 | 
			
		||||
 | 
			
		||||
			color = 0;
 | 
			
		||||
			depth = 0;
 | 
			
		||||
 | 
			
		||||
			width = 0;
 | 
			
		||||
			height = 0;
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
 | 
			
		||||
				flags[i] = false;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			used_in_frame = false;
 | 
			
		||||
 | 
			
		||||
			msaa = VS::VIEWPORT_MSAA_DISABLED;
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	mutable RID_Owner<RenderTarget> render_target_owner;
 | 
			
		||||
 | 
			
		||||
	void _render_target_clear(RenderTarget *rt);
 | 
			
		||||
	void _render_target_allocate(RenderTarget *rt);
 | 
			
		||||
 | 
			
		||||
	virtual RID render_target_create();
 | 
			
		||||
	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height);
 | 
			
		||||
	virtual RID render_target_get_texture(RID p_render_target) const;
 | 
			
		||||
 | 
			
		||||
	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
 | 
			
		||||
	virtual bool render_target_was_used(RID p_render_target);
 | 
			
		||||
	virtual void render_target_clear_used(RID p_render_target);
 | 
			
		||||
	virtual void render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa);
 | 
			
		||||
 | 
			
		||||
	/* CANVAS SHADOW */
 | 
			
		||||
 | 
			
		||||
	virtual RID canvas_light_shadow_buffer_create(int p_width);
 | 
			
		||||
 | 
			
		||||
	/* LIGHT SHADOW MAPPING */
 | 
			
		||||
 | 
			
		||||
	virtual RID canvas_light_occluder_create();
 | 
			
		||||
	virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines);
 | 
			
		||||
 | 
			
		||||
	virtual VS::InstanceType get_base_type(RID p_rid) const;
 | 
			
		||||
 | 
			
		||||
	virtual bool free(RID p_rid);
 | 
			
		||||
 | 
			
		||||
	struct Frame {
 | 
			
		||||
 | 
			
		||||
		RenderTarget *current_rt;
 | 
			
		||||
 | 
			
		||||
		bool clear_request;
 | 
			
		||||
		Color clear_request_color;
 | 
			
		||||
		int canvas_draw_commands;
 | 
			
		||||
		float time[4];
 | 
			
		||||
		float delta;
 | 
			
		||||
		uint64_t prev_tick;
 | 
			
		||||
		uint64_t count;
 | 
			
		||||
 | 
			
		||||
	} frame;
 | 
			
		||||
 | 
			
		||||
	void initialize();
 | 
			
		||||
	void finalize();
 | 
			
		||||
 | 
			
		||||
	virtual bool has_os_feature(const String &p_feature) const;
 | 
			
		||||
 | 
			
		||||
	virtual void update_dirty_resources();
 | 
			
		||||
 | 
			
		||||
	virtual void set_debug_generate_wireframes(bool p_generate);
 | 
			
		||||
 | 
			
		||||
	virtual void render_info_begin_capture();
 | 
			
		||||
	virtual void render_info_end_capture();
 | 
			
		||||
	virtual int get_captured_render_info(VS::RenderInfo p_info);
 | 
			
		||||
 | 
			
		||||
	virtual int get_render_info(VS::RenderInfo p_info);
 | 
			
		||||
 | 
			
		||||
	RasterizerStorageGLES2();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // RASTERIZERSTORAGEGLES2_H
 | 
			
		||||
							
								
								
									
										891
									
								
								drivers/gles2/shader_compiler_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										891
									
								
								drivers/gles2/shader_compiler_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,891 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  shader_compiler_gles3.cpp                                            */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#include "shader_compiler_gles2.h"
 | 
			
		||||
 | 
			
		||||
#include "os/os.h"
 | 
			
		||||
#include "string_buffer.h"
 | 
			
		||||
#include "string_builder.h"
 | 
			
		||||
 | 
			
		||||
#define SL ShaderLanguage
 | 
			
		||||
 | 
			
		||||
static String _mktab(int p_level) {
 | 
			
		||||
 | 
			
		||||
	String tb;
 | 
			
		||||
	for (int i = 0; i < p_level; i++) {
 | 
			
		||||
		tb += "\t";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String _typestr(SL::DataType p_type) {
 | 
			
		||||
 | 
			
		||||
	return ShaderLanguage::get_datatype_name(p_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String _prestr(SL::DataPrecision p_pres) {
 | 
			
		||||
 | 
			
		||||
	switch (p_pres) {
 | 
			
		||||
		case SL::PRECISION_LOWP: return "lowp ";
 | 
			
		||||
		case SL::PRECISION_MEDIUMP: return "mediump ";
 | 
			
		||||
		case SL::PRECISION_HIGHP: return "highp ";
 | 
			
		||||
		case SL::PRECISION_DEFAULT: return "";
 | 
			
		||||
	}
 | 
			
		||||
	return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String _qualstr(SL::ArgumentQualifier p_qual) {
 | 
			
		||||
 | 
			
		||||
	switch (p_qual) {
 | 
			
		||||
		case SL::ARGUMENT_QUALIFIER_IN: return "in ";
 | 
			
		||||
		case SL::ARGUMENT_QUALIFIER_OUT: return "out ";
 | 
			
		||||
		case SL::ARGUMENT_QUALIFIER_INOUT: return "inout ";
 | 
			
		||||
	}
 | 
			
		||||
	return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String _opstr(SL::Operator p_op) {
 | 
			
		||||
 | 
			
		||||
	return SL::get_operator_text(p_op);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String _mkid(const String &p_id) {
 | 
			
		||||
 | 
			
		||||
	StringBuffer<> id;
 | 
			
		||||
	id += "m_";
 | 
			
		||||
	id += p_id;
 | 
			
		||||
 | 
			
		||||
	return id.as_string();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String f2sp0(float p_float) {
 | 
			
		||||
 | 
			
		||||
	if (int(p_float) == p_float)
 | 
			
		||||
		return itos(p_float) + ".0";
 | 
			
		||||
	else
 | 
			
		||||
		return rtoss(p_float);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
 | 
			
		||||
 | 
			
		||||
	switch (p_type) {
 | 
			
		||||
		case SL::TYPE_BOOL: return p_values[0].boolean ? "true" : "false";
 | 
			
		||||
		case SL::TYPE_BVEC2:
 | 
			
		||||
		case SL::TYPE_BVEC3:
 | 
			
		||||
		case SL::TYPE_BVEC4: {
 | 
			
		||||
 | 
			
		||||
			StringBuffer<> text;
 | 
			
		||||
 | 
			
		||||
			text += "bvec";
 | 
			
		||||
			text += itos(p_type - SL::TYPE_BOOL + 1);
 | 
			
		||||
			text += "(";
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < p_values.size(); i++) {
 | 
			
		||||
				if (i > 0)
 | 
			
		||||
					text += ",";
 | 
			
		||||
 | 
			
		||||
				text += p_values[i].boolean ? "true" : "false";
 | 
			
		||||
			}
 | 
			
		||||
			text += ")";
 | 
			
		||||
			return text.as_string();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// GLSL ES 2 doesn't support uints, so we just use signed ints instead...
 | 
			
		||||
		case SL::TYPE_UINT: return itos(p_values[0].uint);
 | 
			
		||||
		case SL::TYPE_UVEC2:
 | 
			
		||||
		case SL::TYPE_UVEC3:
 | 
			
		||||
		case SL::TYPE_UVEC4: {
 | 
			
		||||
 | 
			
		||||
			StringBuffer<> text;
 | 
			
		||||
 | 
			
		||||
			text += "ivec";
 | 
			
		||||
			text += itos(p_type - SL::TYPE_UINT + 1);
 | 
			
		||||
			text += "(";
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < p_values.size(); i++) {
 | 
			
		||||
				if (i > 0)
 | 
			
		||||
					text += ",";
 | 
			
		||||
 | 
			
		||||
				text += itos(p_values[i].uint);
 | 
			
		||||
			}
 | 
			
		||||
			text += ")";
 | 
			
		||||
			return text.as_string();
 | 
			
		||||
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::TYPE_INT: return itos(p_values[0].sint);
 | 
			
		||||
		case SL::TYPE_IVEC2:
 | 
			
		||||
		case SL::TYPE_IVEC3:
 | 
			
		||||
		case SL::TYPE_IVEC4: {
 | 
			
		||||
 | 
			
		||||
			StringBuffer<> text;
 | 
			
		||||
 | 
			
		||||
			text += "ivec";
 | 
			
		||||
			text += itos(p_type - SL::TYPE_INT + 1);
 | 
			
		||||
			text += "(";
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < p_values.size(); i++) {
 | 
			
		||||
				if (i > 0)
 | 
			
		||||
					text += ",";
 | 
			
		||||
 | 
			
		||||
				text += itos(p_values[i].sint);
 | 
			
		||||
			}
 | 
			
		||||
			text += ")";
 | 
			
		||||
			return text.as_string();
 | 
			
		||||
 | 
			
		||||
		} break;
 | 
			
		||||
		case SL::TYPE_FLOAT: return f2sp0(p_values[0].real) + "f";
 | 
			
		||||
		case SL::TYPE_VEC2:
 | 
			
		||||
		case SL::TYPE_VEC3:
 | 
			
		||||
		case SL::TYPE_VEC4: {
 | 
			
		||||
 | 
			
		||||
			StringBuffer<> text;
 | 
			
		||||
 | 
			
		||||
			text += "vec";
 | 
			
		||||
			text += itos(p_type - SL::TYPE_FLOAT + 1);
 | 
			
		||||
			text += "(";
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < p_values.size(); i++) {
 | 
			
		||||
				if (i > 0)
 | 
			
		||||
					text += ",";
 | 
			
		||||
 | 
			
		||||
				text += f2sp0(p_values[i].real);
 | 
			
		||||
			}
 | 
			
		||||
			text += ")";
 | 
			
		||||
			return text.as_string();
 | 
			
		||||
 | 
			
		||||
		} break;
 | 
			
		||||
		case SL::TYPE_MAT2:
 | 
			
		||||
		case SL::TYPE_MAT3:
 | 
			
		||||
		case SL::TYPE_MAT4: {
 | 
			
		||||
 | 
			
		||||
			StringBuffer<> text;
 | 
			
		||||
 | 
			
		||||
			text += "mat";
 | 
			
		||||
			text += itos(p_type - SL::TYPE_MAT2 + 2);
 | 
			
		||||
			text += "(";
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < p_values.size(); i++) {
 | 
			
		||||
				if (i > 0)
 | 
			
		||||
					text += ",";
 | 
			
		||||
 | 
			
		||||
				text += f2sp0(p_values[i].real);
 | 
			
		||||
			}
 | 
			
		||||
			text += ")";
 | 
			
		||||
			return text.as_string();
 | 
			
		||||
 | 
			
		||||
		} break;
 | 
			
		||||
		default: ERR_FAIL_V(String());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added) {
 | 
			
		||||
	int fidx = -1;
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < p_node->functions.size(); i++) {
 | 
			
		||||
		if (p_node->functions[i].name == p_for_func) {
 | 
			
		||||
			fidx = i;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_COND(fidx == -1);
 | 
			
		||||
 | 
			
		||||
	for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) {
 | 
			
		||||
 | 
			
		||||
		if (r_added.has(E->get())) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_dump_function_deps(p_node, E->get(), p_func_code, r_to_add, r_added);
 | 
			
		||||
 | 
			
		||||
		SL::FunctionNode *fnode = NULL;
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < p_node->functions.size(); i++) {
 | 
			
		||||
			if (p_node->functions[i].name == E->get()) {
 | 
			
		||||
				fnode = p_node->functions[i].function;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ERR_FAIL_COND(!fnode);
 | 
			
		||||
 | 
			
		||||
		r_to_add += "\n";
 | 
			
		||||
 | 
			
		||||
		StringBuffer<128> header;
 | 
			
		||||
 | 
			
		||||
		header += _typestr(fnode->return_type);
 | 
			
		||||
		header += " ";
 | 
			
		||||
		header += _mkid(fnode->name);
 | 
			
		||||
		header += "(";
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < fnode->arguments.size(); i++) {
 | 
			
		||||
			if (i > 0)
 | 
			
		||||
				header += ", ";
 | 
			
		||||
 | 
			
		||||
			header += _qualstr(fnode->arguments[i].qualifier);
 | 
			
		||||
			header += _prestr(fnode->arguments[i].precision);
 | 
			
		||||
			header += _typestr(fnode->arguments[i].type);
 | 
			
		||||
			header += " ";
 | 
			
		||||
			header += _mkid(fnode->arguments[i].name);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		header += ")\n";
 | 
			
		||||
		r_to_add += header.as_string();
 | 
			
		||||
		r_to_add += p_func_code[E->get()];
 | 
			
		||||
 | 
			
		||||
		r_added.insert(E->get());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning) {
 | 
			
		||||
 | 
			
		||||
	StringBuilder code;
 | 
			
		||||
 | 
			
		||||
	switch (p_node->type) {
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_SHADER: {
 | 
			
		||||
 | 
			
		||||
			SL::ShaderNode *snode = (SL::ShaderNode *)p_node;
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < snode->render_modes.size(); i++) {
 | 
			
		||||
 | 
			
		||||
				if (p_default_actions.render_mode_defines.has(snode->render_modes[i]) && !used_rmode_defines.has(snode->render_modes[i])) {
 | 
			
		||||
 | 
			
		||||
					r_gen_code.custom_defines.push_back(p_default_actions.render_mode_defines[snode->render_modes[i]].utf8());
 | 
			
		||||
					used_rmode_defines.insert(snode->render_modes[i]);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (p_actions.render_mode_flags.has(snode->render_modes[i])) {
 | 
			
		||||
					*p_actions.render_mode_flags[snode->render_modes[i]] = true;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (p_actions.render_mode_values.has(snode->render_modes[i])) {
 | 
			
		||||
					Pair<int *, int> &p = p_actions.render_mode_values[snode->render_modes[i]];
 | 
			
		||||
					*p.first = p.second;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			int max_texture_uniforms = 0;
 | 
			
		||||
			int max_uniforms = 0;
 | 
			
		||||
 | 
			
		||||
			for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) {
 | 
			
		||||
				if (SL::is_sampler_type(E->get().type))
 | 
			
		||||
					max_texture_uniforms++;
 | 
			
		||||
				else
 | 
			
		||||
					max_uniforms++;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			r_gen_code.texture_uniforms.resize(max_texture_uniforms);
 | 
			
		||||
			r_gen_code.texture_hints.resize(max_texture_uniforms);
 | 
			
		||||
 | 
			
		||||
			r_gen_code.uniforms.resize(max_uniforms + max_texture_uniforms);
 | 
			
		||||
 | 
			
		||||
			StringBuilder vertex_global;
 | 
			
		||||
			StringBuilder fragment_global;
 | 
			
		||||
 | 
			
		||||
			// uniforms
 | 
			
		||||
 | 
			
		||||
			for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) {
 | 
			
		||||
				StringBuffer<> uniform_code;
 | 
			
		||||
 | 
			
		||||
				uniform_code += "uniform ";
 | 
			
		||||
 | 
			
		||||
				uniform_code += _prestr(E->get().precission);
 | 
			
		||||
				uniform_code += _typestr(E->get().type);
 | 
			
		||||
				uniform_code += " ";
 | 
			
		||||
				uniform_code += _mkid(E->key());
 | 
			
		||||
				uniform_code += ";\n";
 | 
			
		||||
 | 
			
		||||
				if (SL::is_sampler_type(E->get().type)) {
 | 
			
		||||
					r_gen_code.texture_uniforms[E->get().texture_order] = _mkid(E->key());
 | 
			
		||||
					r_gen_code.texture_hints[E->get().texture_order] = E->get().hint;
 | 
			
		||||
				} else {
 | 
			
		||||
					r_gen_code.uniforms[E->get().order] = E->key();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				vertex_global += uniform_code.as_string();
 | 
			
		||||
				fragment_global += uniform_code.as_string();
 | 
			
		||||
 | 
			
		||||
				p_actions.uniforms->insert(E->key(), E->get());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// varyings
 | 
			
		||||
 | 
			
		||||
			for (Map<StringName, SL::ShaderNode::Varying>::Element *E = snode->varyings.front(); E; E = E->next()) {
 | 
			
		||||
 | 
			
		||||
				StringBuffer<> varying_code;
 | 
			
		||||
 | 
			
		||||
				varying_code += "varying ";
 | 
			
		||||
				varying_code += _prestr(E->get().precission);
 | 
			
		||||
				varying_code += _typestr(E->get().type);
 | 
			
		||||
				varying_code += " ";
 | 
			
		||||
				varying_code += _mkid(E->key());
 | 
			
		||||
				varying_code += ";\n";
 | 
			
		||||
 | 
			
		||||
				String final_code = varying_code.as_string();
 | 
			
		||||
 | 
			
		||||
				vertex_global += final_code;
 | 
			
		||||
				fragment_global += final_code;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// functions
 | 
			
		||||
 | 
			
		||||
			Map<StringName, String> function_code;
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < snode->functions.size(); i++) {
 | 
			
		||||
				SL::FunctionNode *fnode = snode->functions[i].function;
 | 
			
		||||
				function_code[fnode->name] = _dump_node_code(fnode->body, 1, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Set<StringName> added_vertex;
 | 
			
		||||
			Set<StringName> added_fragment;
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < snode->functions.size(); i++) {
 | 
			
		||||
 | 
			
		||||
				SL::FunctionNode *fnode = snode->functions[i].function;
 | 
			
		||||
 | 
			
		||||
				current_func_name = fnode->name;
 | 
			
		||||
 | 
			
		||||
				if (fnode->name == vertex_name) {
 | 
			
		||||
					_dump_function_deps(snode, fnode->name, function_code, vertex_global, added_vertex);
 | 
			
		||||
					r_gen_code.vertex = function_code[vertex_name];
 | 
			
		||||
 | 
			
		||||
				} else if (fnode->name == fragment_name) {
 | 
			
		||||
					_dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment);
 | 
			
		||||
					r_gen_code.fragment = function_code[fragment_name];
 | 
			
		||||
 | 
			
		||||
				} else if (fnode->name == light_name) {
 | 
			
		||||
					_dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment);
 | 
			
		||||
					r_gen_code.light = function_code[light_name];
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			r_gen_code.vertex_global = vertex_global.as_string();
 | 
			
		||||
			r_gen_code.fragment_global = fragment_global.as_string();
 | 
			
		||||
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_FUNCTION: {
 | 
			
		||||
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_BLOCK: {
 | 
			
		||||
 | 
			
		||||
			SL::BlockNode *bnode = (SL::BlockNode *)p_node;
 | 
			
		||||
 | 
			
		||||
			if (!bnode->single_statement) {
 | 
			
		||||
				code += _mktab(p_level - 1);
 | 
			
		||||
				code += "{\n";
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < bnode->statements.size(); i++) {
 | 
			
		||||
				String statement_code = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
 | 
			
		||||
				if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) {
 | 
			
		||||
					code += statement_code;
 | 
			
		||||
				} else {
 | 
			
		||||
					code += _mktab(p_level);
 | 
			
		||||
					code += statement_code;
 | 
			
		||||
					code += ";\n";
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!bnode->single_statement) {
 | 
			
		||||
				code += _mktab(p_level - 1);
 | 
			
		||||
				code += "}\n";
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_VARIABLE_DECLARATION: {
 | 
			
		||||
			SL::VariableDeclarationNode *var_dec_node = (SL::VariableDeclarationNode *)p_node;
 | 
			
		||||
 | 
			
		||||
			StringBuffer<> declaration;
 | 
			
		||||
 | 
			
		||||
			declaration += _prestr(var_dec_node->precision);
 | 
			
		||||
			declaration += _typestr(var_dec_node->datatype);
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < var_dec_node->declarations.size(); i++) {
 | 
			
		||||
 | 
			
		||||
				if (i > 0) {
 | 
			
		||||
					declaration += ",";
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				declaration += " ";
 | 
			
		||||
 | 
			
		||||
				declaration += _mkid(var_dec_node->declarations[i].name);
 | 
			
		||||
 | 
			
		||||
				if (var_dec_node->declarations[i].initializer) {
 | 
			
		||||
					declaration += " = ";
 | 
			
		||||
					declaration += _dump_node_code(var_dec_node->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			code += declaration.as_string();
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_VARIABLE: {
 | 
			
		||||
			SL::VariableNode *var_node = (SL::VariableNode *)p_node;
 | 
			
		||||
 | 
			
		||||
			if (p_assigning && p_actions.write_flag_pointers.has(var_node->name)) {
 | 
			
		||||
				*p_actions.write_flag_pointers[var_node->name] = true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (p_default_actions.usage_defines.has(var_node->name) && !used_name_defines.has(var_node->name)) {
 | 
			
		||||
				String define = p_default_actions.usage_defines[var_node->name];
 | 
			
		||||
 | 
			
		||||
				if (define.begins_with("@")) {
 | 
			
		||||
					define = p_default_actions.usage_defines[define.substr(1, define.length())];
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				r_gen_code.custom_defines.push_back(define.utf8());
 | 
			
		||||
				used_name_defines.insert(var_node->name);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (p_actions.usage_flag_pointers.has(var_node->name) && !used_flag_pointers.has(var_node->name)) {
 | 
			
		||||
				*p_actions.usage_flag_pointers[var_node->name] = true;
 | 
			
		||||
				used_flag_pointers.insert(var_node->name);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (p_default_actions.renames.has(var_node->name)) {
 | 
			
		||||
				code += p_default_actions.renames[var_node->name];
 | 
			
		||||
			} else {
 | 
			
		||||
				code += _mkid(var_node->name);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (var_node->name == time_name) {
 | 
			
		||||
				if (current_func_name == vertex_name) {
 | 
			
		||||
					r_gen_code.uses_vertex_time = true;
 | 
			
		||||
				}
 | 
			
		||||
				if (current_func_name == fragment_name || current_func_name == light_name) {
 | 
			
		||||
					r_gen_code.uses_fragment_time = true;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_CONSTANT: {
 | 
			
		||||
			SL::ConstantNode *const_node = (SL::ConstantNode *)p_node;
 | 
			
		||||
 | 
			
		||||
			return get_constant_text(const_node->datatype, const_node->values);
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_OPERATOR: {
 | 
			
		||||
			SL::OperatorNode *op_node = (SL::OperatorNode *)p_node;
 | 
			
		||||
 | 
			
		||||
			switch (op_node->op) {
 | 
			
		||||
				case SL::OP_ASSIGN:
 | 
			
		||||
				case SL::OP_ASSIGN_ADD:
 | 
			
		||||
				case SL::OP_ASSIGN_SUB:
 | 
			
		||||
				case SL::OP_ASSIGN_MUL:
 | 
			
		||||
				case SL::OP_ASSIGN_DIV:
 | 
			
		||||
				case SL::OP_ASSIGN_SHIFT_LEFT:
 | 
			
		||||
				case SL::OP_ASSIGN_SHIFT_RIGHT:
 | 
			
		||||
				case SL::OP_ASSIGN_MOD:
 | 
			
		||||
				case SL::OP_ASSIGN_BIT_AND:
 | 
			
		||||
				case SL::OP_ASSIGN_BIT_OR:
 | 
			
		||||
				case SL::OP_ASSIGN_BIT_XOR: {
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true);
 | 
			
		||||
					code += " ";
 | 
			
		||||
					code += _opstr(op_node->op);
 | 
			
		||||
					code += " ";
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				} break;
 | 
			
		||||
 | 
			
		||||
				case SL::OP_BIT_INVERT:
 | 
			
		||||
				case SL::OP_NEGATE:
 | 
			
		||||
				case SL::OP_NOT:
 | 
			
		||||
				case SL::OP_DECREMENT:
 | 
			
		||||
				case SL::OP_INCREMENT: {
 | 
			
		||||
					code += _opstr(op_node->op);
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				} break;
 | 
			
		||||
 | 
			
		||||
				case SL::OP_POST_DECREMENT:
 | 
			
		||||
				case SL::OP_POST_INCREMENT: {
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					code += _opstr(op_node->op);
 | 
			
		||||
				} break;
 | 
			
		||||
 | 
			
		||||
				case SL::OP_CALL:
 | 
			
		||||
				case SL::OP_CONSTRUCT: {
 | 
			
		||||
					ERR_FAIL_COND_V(op_node->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
 | 
			
		||||
 | 
			
		||||
					SL::VariableNode *var_node = (SL::VariableNode *)op_node->arguments[0];
 | 
			
		||||
 | 
			
		||||
					if (op_node->op == SL::OP_CONSTRUCT) {
 | 
			
		||||
						code += var_node->name;
 | 
			
		||||
					} else {
 | 
			
		||||
 | 
			
		||||
						if (var_node->name == "texture") {
 | 
			
		||||
							// emit texture call
 | 
			
		||||
 | 
			
		||||
							if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D) {
 | 
			
		||||
								code += "texture2D";
 | 
			
		||||
							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
 | 
			
		||||
								code += "textureCube";
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
						} else if (p_default_actions.renames.has(var_node->name)) {
 | 
			
		||||
							code += p_default_actions.renames[var_node->name];
 | 
			
		||||
						} else if (internal_functions.has(var_node->name)) {
 | 
			
		||||
							code += var_node->name;
 | 
			
		||||
						} else {
 | 
			
		||||
							code += _mkid(var_node->name);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					code += "(";
 | 
			
		||||
 | 
			
		||||
					for (int i = 1; i < op_node->arguments.size(); i++) {
 | 
			
		||||
						if (i > 1) {
 | 
			
		||||
							code += ", ";
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						code += _dump_node_code(op_node->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					code += ")";
 | 
			
		||||
 | 
			
		||||
				} break;
 | 
			
		||||
 | 
			
		||||
				case SL::OP_INDEX: {
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					code += "[";
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					code += "]";
 | 
			
		||||
				} break;
 | 
			
		||||
 | 
			
		||||
				case SL::OP_SELECT_IF: {
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					code += " ? ";
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					code += " : ";
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				} break;
 | 
			
		||||
 | 
			
		||||
				default: {
 | 
			
		||||
					code += "(";
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					code += " ";
 | 
			
		||||
					code += _opstr(op_node->op);
 | 
			
		||||
					code += " ";
 | 
			
		||||
					code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
					code += ")";
 | 
			
		||||
				} break;
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_CONTROL_FLOW: {
 | 
			
		||||
			SL::ControlFlowNode *cf_node = (SL::ControlFlowNode *)p_node;
 | 
			
		||||
 | 
			
		||||
			if (cf_node->flow_op == SL::FLOW_OP_IF) {
 | 
			
		||||
 | 
			
		||||
				code += _mktab(p_level);
 | 
			
		||||
				code += "if (";
 | 
			
		||||
				code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				code += ")\n";
 | 
			
		||||
				code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
 | 
			
		||||
				if (cf_node->blocks.size() == 2) {
 | 
			
		||||
					code += _mktab(p_level);
 | 
			
		||||
					code += "else\n";
 | 
			
		||||
					code += _dump_node_code(cf_node->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				}
 | 
			
		||||
			} else if (cf_node->flow_op == SL::FLOW_OP_WHILE) {
 | 
			
		||||
				code += _mktab(p_level);
 | 
			
		||||
				code += "while (";
 | 
			
		||||
				code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				code += ")\n";
 | 
			
		||||
				code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
			} else if (cf_node->flow_op == SL::FLOW_OP_FOR) {
 | 
			
		||||
 | 
			
		||||
				code += _mktab(p_level);
 | 
			
		||||
				code += "for (";
 | 
			
		||||
				code += _dump_node_code(cf_node->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				code += "; ";
 | 
			
		||||
				code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				code += "; ";
 | 
			
		||||
				code += _dump_node_code(cf_node->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				code += ")\n";
 | 
			
		||||
 | 
			
		||||
				code += _dump_node_code(cf_node->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
 | 
			
		||||
			} else if (cf_node->flow_op == SL::FLOW_OP_RETURN) {
 | 
			
		||||
				code += _mktab(p_level);
 | 
			
		||||
				code += "return";
 | 
			
		||||
 | 
			
		||||
				if (cf_node->expressions.size()) {
 | 
			
		||||
					code += " ";
 | 
			
		||||
					code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
				}
 | 
			
		||||
				code += ";\n";
 | 
			
		||||
			} else if (cf_node->flow_op == SL::FLOW_OP_DISCARD) {
 | 
			
		||||
				code += "discard;";
 | 
			
		||||
			} else if (cf_node->flow_op == SL::FLOW_OP_CONTINUE) {
 | 
			
		||||
				code += "continue;";
 | 
			
		||||
			} else if (cf_node->flow_op == SL::FLOW_OP_BREAK) {
 | 
			
		||||
				code += "break;";
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
 | 
			
		||||
		case SL::Node::TYPE_MEMBER: {
 | 
			
		||||
			SL::MemberNode *member_node = (SL::MemberNode *)p_node;
 | 
			
		||||
			code += _dump_node_code(member_node->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
 | 
			
		||||
			code += ".";
 | 
			
		||||
			code += member_node->name;
 | 
			
		||||
		} break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return code.as_string();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
 | 
			
		||||
 | 
			
		||||
	Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types());
 | 
			
		||||
 | 
			
		||||
	if (err != OK) {
 | 
			
		||||
 | 
			
		||||
		Vector<String> shader = p_code.split("\n");
 | 
			
		||||
		for (int i = 0; i < shader.size(); i++) {
 | 
			
		||||
			print_line(itos(i) + " " + shader[i]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r_gen_code.custom_defines.clear();
 | 
			
		||||
	r_gen_code.uniforms.clear();
 | 
			
		||||
	r_gen_code.texture_uniforms.clear();
 | 
			
		||||
	r_gen_code.texture_hints.clear();
 | 
			
		||||
	r_gen_code.vertex = String();
 | 
			
		||||
	r_gen_code.vertex_global = String();
 | 
			
		||||
	r_gen_code.fragment = String();
 | 
			
		||||
	r_gen_code.fragment_global = String();
 | 
			
		||||
	r_gen_code.light = String();
 | 
			
		||||
	r_gen_code.uses_fragment_time = false;
 | 
			
		||||
	r_gen_code.uses_vertex_time = false;
 | 
			
		||||
 | 
			
		||||
	used_name_defines.clear();
 | 
			
		||||
	used_rmode_defines.clear();
 | 
			
		||||
	used_flag_pointers.clear();
 | 
			
		||||
 | 
			
		||||
	_dump_node_code(parser.get_shader(), 1, r_gen_code, *p_actions, actions[p_mode], false);
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShaderCompilerGLES2::ShaderCompilerGLES2() {
 | 
			
		||||
 | 
			
		||||
	/** CANVAS ITEM SHADER **/
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "gl_PointSize";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] == "extra_matrix";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["TIME"] = "time";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["FRAGCOORD"] = "gl_FragCoord";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv";
 | 
			
		||||
	//actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_SHADOW_COLOR"]="light_shadow_color";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"] = "#define SHADOW_COLOR_USED\n";
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
 | 
			
		||||
 | 
			
		||||
	/** SPATIAL SHADER **/
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["NORMAL"] = "normal";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["TANGENT"] = "tangent";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
 | 
			
		||||
	//actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"]=ShaderLanguage::TYPE_INT;
 | 
			
		||||
 | 
			
		||||
	//builtins
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["TIME"] = "time";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["ALPHA"] = "alpha";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["METALLIC"] = "metallic";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["SPECULAR"] = "specular";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["RIM"] = "rim";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
 | 
			
		||||
	//actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["AO"] = "ao";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission";
 | 
			
		||||
	//actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["SIDE"] = "side";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor";
 | 
			
		||||
 | 
			
		||||
	//for light
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
 | 
			
		||||
 | 
			
		||||
	/* PARTICLES SHADER */
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["COLOR"] = "out_color";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["MASS"] = "mass";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "active";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["RESTART"] = "restart";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["TIME"] = "time";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["DELTA"] = "local_delta";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform";
 | 
			
		||||
	actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed";
 | 
			
		||||
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
 | 
			
		||||
	actions[VS::SHADER_SPATIAL].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
 | 
			
		||||
 | 
			
		||||
	vertex_name = "vertex";
 | 
			
		||||
	fragment_name = "fragment";
 | 
			
		||||
	light_name = "light";
 | 
			
		||||
	time_name = "TIME";
 | 
			
		||||
 | 
			
		||||
	List<String> func_list;
 | 
			
		||||
 | 
			
		||||
	ShaderLanguage::get_builtin_funcs(&func_list);
 | 
			
		||||
 | 
			
		||||
	for (List<String>::Element *E = func_list.front(); E; E = E->next()) {
 | 
			
		||||
		internal_functions.insert(E->get());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										101
									
								
								drivers/gles2/shader_compiler_gles2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								drivers/gles2/shader_compiler_gles2.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,101 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  shader_compiler_gles2.h                                              */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#ifndef SHADERCOMPILERGLES2_H
 | 
			
		||||
#define SHADERCOMPILERGLES2_H
 | 
			
		||||
 | 
			
		||||
#include "pair.h"
 | 
			
		||||
#include "servers/visual/shader_language.h"
 | 
			
		||||
#include "servers/visual/shader_types.h"
 | 
			
		||||
#include "servers/visual_server.h"
 | 
			
		||||
 | 
			
		||||
#include "string_builder.h"
 | 
			
		||||
 | 
			
		||||
class ShaderCompilerGLES2 {
 | 
			
		||||
public:
 | 
			
		||||
	struct IdentifierActions {
 | 
			
		||||
 | 
			
		||||
		Map<StringName, Pair<int *, int> > render_mode_values;
 | 
			
		||||
		Map<StringName, bool *> render_mode_flags;
 | 
			
		||||
		Map<StringName, bool *> usage_flag_pointers;
 | 
			
		||||
		Map<StringName, bool *> write_flag_pointers;
 | 
			
		||||
 | 
			
		||||
		Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct GeneratedCode {
 | 
			
		||||
 | 
			
		||||
		Vector<CharString> custom_defines;
 | 
			
		||||
		Vector<StringName> uniforms;
 | 
			
		||||
		Vector<StringName> texture_uniforms;
 | 
			
		||||
		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 | 
			
		||||
 | 
			
		||||
		String vertex_global;
 | 
			
		||||
		String vertex;
 | 
			
		||||
		String fragment_global;
 | 
			
		||||
		String fragment;
 | 
			
		||||
		String light;
 | 
			
		||||
 | 
			
		||||
		bool uses_fragment_time;
 | 
			
		||||
		bool uses_vertex_time;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	ShaderLanguage parser;
 | 
			
		||||
 | 
			
		||||
	struct DefaultIdentifierActions {
 | 
			
		||||
 | 
			
		||||
		Map<StringName, String> renames;
 | 
			
		||||
		Map<StringName, String> render_mode_defines;
 | 
			
		||||
		Map<StringName, String> usage_defines;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added);
 | 
			
		||||
	String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning);
 | 
			
		||||
 | 
			
		||||
	StringName current_func_name;
 | 
			
		||||
	StringName vertex_name;
 | 
			
		||||
	StringName fragment_name;
 | 
			
		||||
	StringName light_name;
 | 
			
		||||
	StringName time_name;
 | 
			
		||||
 | 
			
		||||
	Set<StringName> used_name_defines;
 | 
			
		||||
	Set<StringName> used_flag_pointers;
 | 
			
		||||
	Set<StringName> used_rmode_defines;
 | 
			
		||||
	Set<StringName> internal_functions;
 | 
			
		||||
 | 
			
		||||
	DefaultIdentifierActions actions[VS::SHADER_MAX];
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	Error compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
 | 
			
		||||
 | 
			
		||||
	ShaderCompilerGLES2();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // SHADERCOMPILERGLES3_H
 | 
			
		||||
							
								
								
									
										689
									
								
								drivers/gles2/shader_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										689
									
								
								drivers/gles2/shader_gles2.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,689 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  shader_gles2.cpp                                                     */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#include "shader_gles2.h"
 | 
			
		||||
 | 
			
		||||
#include "memory.h"
 | 
			
		||||
#include "print_string.h"
 | 
			
		||||
#include "string_builder.h"
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_OPENGL
 | 
			
		||||
 | 
			
		||||
// #include "shaders/copy.glsl.gen.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_OPENGL
 | 
			
		||||
 | 
			
		||||
#define DEBUG_TEST_ERROR(m_section)                                         \
 | 
			
		||||
	{                                                                       \
 | 
			
		||||
		uint32_t err = glGetError();                                        \
 | 
			
		||||
		if (err) {                                                          \
 | 
			
		||||
			print_line("OpenGL Error #" + itos(err) + " at: " + m_section); \
 | 
			
		||||
		}                                                                   \
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define DEBUG_TEST_ERROR(m_section)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ShaderGLES2 *ShaderGLES2::active = NULL;
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_SHADER
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_SHADER
 | 
			
		||||
 | 
			
		||||
#define DEBUG_PRINT(m_text) print_line(m_text);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define DEBUG_PRINT(m_text)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::bind_uniforms() {
 | 
			
		||||
	if (!uniforms_dirty)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	// regular uniforms
 | 
			
		||||
 | 
			
		||||
	const Map<uint32_t, Variant>::Element *E = uniform_defaults.front();
 | 
			
		||||
 | 
			
		||||
	while (E) {
 | 
			
		||||
		int idx = E->key();
 | 
			
		||||
		int location = version->uniform_location[idx];
 | 
			
		||||
 | 
			
		||||
		if (location < 0) {
 | 
			
		||||
			E = E->next();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const Variant &v = E->value();
 | 
			
		||||
		_set_uniform_variant(location, v);
 | 
			
		||||
		E = E->next();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// camera uniforms
 | 
			
		||||
 | 
			
		||||
	const Map<uint32_t, CameraMatrix>::Element *C = uniform_cameras.front();
 | 
			
		||||
 | 
			
		||||
	while (C) {
 | 
			
		||||
		int idx = E->key();
 | 
			
		||||
		int location = version->uniform_location[idx];
 | 
			
		||||
 | 
			
		||||
		if (location < 0) {
 | 
			
		||||
			C = C->next();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		glUniformMatrix4fv(location, 1, GL_FALSE, &(C->get().matrix[0][0]));
 | 
			
		||||
		C = C->next();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uniforms_dirty = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLint ShaderGLES2::get_uniform_location(int p_index) const {
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_COND_V(!version, -1);
 | 
			
		||||
 | 
			
		||||
	return version->uniform_location[p_index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ShaderGLES2::bind() {
 | 
			
		||||
 | 
			
		||||
	if (active != this || !version || new_conditional_version.key != conditional_version.key) {
 | 
			
		||||
		conditional_version = new_conditional_version;
 | 
			
		||||
		version = get_current_version();
 | 
			
		||||
	} else {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_COND_V(!version, false);
 | 
			
		||||
 | 
			
		||||
	glUseProgram(version->id);
 | 
			
		||||
 | 
			
		||||
	DEBUG_TEST_ERROR("use program");
 | 
			
		||||
 | 
			
		||||
	active = this;
 | 
			
		||||
	uniforms_dirty = true;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::unbind() {
 | 
			
		||||
	version = NULL;
 | 
			
		||||
	glUseProgram(0);
 | 
			
		||||
	uniforms_dirty = true;
 | 
			
		||||
	active = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String _fix_error_code_line(const String &p_error, int p_code_start, int p_offset) {
 | 
			
		||||
 | 
			
		||||
	int last_find_pos = -1;
 | 
			
		||||
	// NVIDIA
 | 
			
		||||
	String error = p_error;
 | 
			
		||||
	while ((last_find_pos = p_error.find("(", last_find_pos + 1)) != -1) {
 | 
			
		||||
 | 
			
		||||
		int end_pos = last_find_pos + 1;
 | 
			
		||||
 | 
			
		||||
		while (true) {
 | 
			
		||||
 | 
			
		||||
			if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') {
 | 
			
		||||
 | 
			
		||||
				end_pos++;
 | 
			
		||||
				continue;
 | 
			
		||||
			} else if (p_error[end_pos] == ')') {
 | 
			
		||||
				break;
 | 
			
		||||
			} else {
 | 
			
		||||
 | 
			
		||||
				end_pos = -1;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (end_pos == -1)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1);
 | 
			
		||||
		String begin = error.substr(0, last_find_pos + 1);
 | 
			
		||||
		String end = error.substr(end_pos, error.length());
 | 
			
		||||
		int num = numstr.to_int() + p_code_start - p_offset;
 | 
			
		||||
		error = begin + itos(num) + end;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ATI
 | 
			
		||||
	last_find_pos = -1;
 | 
			
		||||
	while ((last_find_pos = p_error.find("ERROR: ", last_find_pos + 1)) != -1) {
 | 
			
		||||
 | 
			
		||||
		last_find_pos += 6;
 | 
			
		||||
		int end_pos = last_find_pos + 1;
 | 
			
		||||
 | 
			
		||||
		while (true) {
 | 
			
		||||
 | 
			
		||||
			if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') {
 | 
			
		||||
 | 
			
		||||
				end_pos++;
 | 
			
		||||
				continue;
 | 
			
		||||
			} else if (p_error[end_pos] == ':') {
 | 
			
		||||
				break;
 | 
			
		||||
			} else {
 | 
			
		||||
 | 
			
		||||
				end_pos = -1;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		continue;
 | 
			
		||||
		if (end_pos == -1)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1);
 | 
			
		||||
		print_line("numstr: " + numstr);
 | 
			
		||||
		String begin = error.substr(0, last_find_pos + 1);
 | 
			
		||||
		String end = error.substr(end_pos, error.length());
 | 
			
		||||
		int num = numstr.to_int() + p_code_start - p_offset;
 | 
			
		||||
		error = begin + itos(num) + end;
 | 
			
		||||
	}
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShaderGLES2::Version *ShaderGLES2::get_current_version() {
 | 
			
		||||
 | 
			
		||||
	Version *_v = version_map.getptr(conditional_version);
 | 
			
		||||
 | 
			
		||||
	if (_v) {
 | 
			
		||||
		if (conditional_version.code_version != 0) {
 | 
			
		||||
			CustomCode *cc = custom_code_map.getptr(conditional_version.code_version);
 | 
			
		||||
			ERR_FAIL_COND_V(!cc, _v);
 | 
			
		||||
			if (cc->version == _v->code_version)
 | 
			
		||||
				return _v;
 | 
			
		||||
		} else {
 | 
			
		||||
			return _v;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_v)
 | 
			
		||||
		version_map[conditional_version];
 | 
			
		||||
 | 
			
		||||
	Version &v = version_map[conditional_version];
 | 
			
		||||
 | 
			
		||||
	if (!_v) {
 | 
			
		||||
		v.uniform_location = memnew_arr(GLint, uniform_count);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (v.ok) {
 | 
			
		||||
			glDeleteShader(v.vert_id);
 | 
			
		||||
			glDeleteShader(v.frag_id);
 | 
			
		||||
			glDeleteProgram(v.id);
 | 
			
		||||
			v.id = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.ok = false;
 | 
			
		||||
 | 
			
		||||
	Vector<const char *> strings;
 | 
			
		||||
 | 
			
		||||
#ifdef GLES_OVER_GL
 | 
			
		||||
	strings.push_back("#version 120\n");
 | 
			
		||||
	strings.push_back("#define USE_GLES_OVER_GL\n");
 | 
			
		||||
#else
 | 
			
		||||
	strings.push_back("#version 100\n");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	int define_line_ofs = 1;
 | 
			
		||||
 | 
			
		||||
	for (int j = 0; j < conditional_count; j++) {
 | 
			
		||||
		bool enable = (conditional_version.version & (1 << j)) > 0;
 | 
			
		||||
 | 
			
		||||
		if (enable) {
 | 
			
		||||
			strings.push_back(conditional_defines[j]);
 | 
			
		||||
			define_line_ofs++;
 | 
			
		||||
			DEBUG_PRINT(conditional_defines[j]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// keep them around during the functino
 | 
			
		||||
	CharString code_string;
 | 
			
		||||
	CharString code_string2;
 | 
			
		||||
	CharString code_globals;
 | 
			
		||||
 | 
			
		||||
	CustomCode *cc = NULL;
 | 
			
		||||
 | 
			
		||||
	if (conditional_version.code_version > 0) {
 | 
			
		||||
		cc = custom_code_map.getptr(conditional_version.code_version);
 | 
			
		||||
 | 
			
		||||
		ERR_FAIL_COND_V(!cc, NULL);
 | 
			
		||||
		v.code_version = cc->version;
 | 
			
		||||
		define_line_ofs += 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// program
 | 
			
		||||
 | 
			
		||||
	v.id = glCreateProgram();
 | 
			
		||||
	ERR_FAIL_COND_V(v.id == 0, NULL);
 | 
			
		||||
 | 
			
		||||
	if (cc) {
 | 
			
		||||
		for (int i = 0; i < cc->custom_defines.size(); i++) {
 | 
			
		||||
			strings.push_back(cc->custom_defines[i]);
 | 
			
		||||
			DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i]));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// vertex shader
 | 
			
		||||
 | 
			
		||||
	int string_base_size = strings.size();
 | 
			
		||||
 | 
			
		||||
	strings.push_back(vertex_code0.get_data());
 | 
			
		||||
 | 
			
		||||
	if (cc) {
 | 
			
		||||
		code_globals = cc->vertex_globals.ascii();
 | 
			
		||||
		strings.push_back(code_globals.get_data());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strings.push_back(vertex_code1.get_data());
 | 
			
		||||
 | 
			
		||||
	if (cc) {
 | 
			
		||||
		code_string = cc->vertex.ascii();
 | 
			
		||||
		strings.push_back(code_string.get_data());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strings.push_back(vertex_code2.get_data());
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_SHADER
 | 
			
		||||
 | 
			
		||||
	DEBUG_PRINT("\nVertex Code:\n\n" + String(code_string.get_data()));
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	v.vert_id = glCreateShader(GL_VERTEX_SHADER);
 | 
			
		||||
	glShaderSource(v.vert_id, strings.size(), &strings[0], NULL);
 | 
			
		||||
	glCompileShader(v.vert_id);
 | 
			
		||||
 | 
			
		||||
	GLint status;
 | 
			
		||||
 | 
			
		||||
	glGetShaderiv(v.vert_id, GL_COMPILE_STATUS, &status);
 | 
			
		||||
	if (status == GL_FALSE) {
 | 
			
		||||
		GLsizei iloglen;
 | 
			
		||||
		glGetShaderiv(v.vert_id, GL_INFO_LOG_LENGTH, &iloglen);
 | 
			
		||||
 | 
			
		||||
		if (iloglen < 0) {
 | 
			
		||||
			glDeleteShader(v.vert_id);
 | 
			
		||||
			glDeleteProgram(v.id);
 | 
			
		||||
			v.id = 0;
 | 
			
		||||
 | 
			
		||||
			ERR_PRINT("No OpenGL vertex shader compiler log. What the frick?");
 | 
			
		||||
		} else {
 | 
			
		||||
			if (iloglen == 0) {
 | 
			
		||||
				iloglen = 4096; // buggy driver (Adreno 220+)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			char *ilogmem = (char *)Memory::alloc_static(iloglen + 1);
 | 
			
		||||
			ilogmem[iloglen] = '\0';
 | 
			
		||||
			glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem);
 | 
			
		||||
 | 
			
		||||
			String err_string = get_shader_name() + ": Vertex shader compilation failed:\n";
 | 
			
		||||
 | 
			
		||||
			err_string += ilogmem;
 | 
			
		||||
			err_string = _fix_error_code_line(err_string, vertex_code_start, define_line_ofs);
 | 
			
		||||
 | 
			
		||||
			ERR_PRINTS(err_string);
 | 
			
		||||
 | 
			
		||||
			Memory::free_static(ilogmem);
 | 
			
		||||
			glDeleteShader(v.vert_id);
 | 
			
		||||
			glDeleteProgram(v.id);
 | 
			
		||||
			v.id = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ERR_FAIL_V(NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strings.resize(string_base_size);
 | 
			
		||||
 | 
			
		||||
	// fragment shader
 | 
			
		||||
 | 
			
		||||
	strings.push_back(fragment_code0.get_data());
 | 
			
		||||
 | 
			
		||||
	if (cc) {
 | 
			
		||||
		code_globals = cc->fragment_globals.ascii();
 | 
			
		||||
		strings.push_back(code_globals.get_data());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strings.push_back(fragment_code1.get_data());
 | 
			
		||||
 | 
			
		||||
	if (cc) {
 | 
			
		||||
		code_string = cc->fragment.ascii();
 | 
			
		||||
		strings.push_back(code_string.get_data());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strings.push_back(fragment_code2.get_data());
 | 
			
		||||
 | 
			
		||||
	if (cc) {
 | 
			
		||||
		code_string2 = cc->light.ascii();
 | 
			
		||||
		strings.push_back(code_string2.get_data());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strings.push_back(fragment_code3.get_data());
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_SHADER
 | 
			
		||||
	DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string.get_data()));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	v.frag_id = glCreateShader(GL_FRAGMENT_SHADER);
 | 
			
		||||
	glShaderSource(v.frag_id, strings.size(), &strings[0], NULL);
 | 
			
		||||
	glCompileShader(v.frag_id);
 | 
			
		||||
 | 
			
		||||
	glGetShaderiv(v.frag_id, GL_COMPILE_STATUS, &status);
 | 
			
		||||
	if (status == GL_FALSE) {
 | 
			
		||||
		GLsizei iloglen;
 | 
			
		||||
		glGetShaderiv(v.frag_id, GL_INFO_LOG_LENGTH, &iloglen);
 | 
			
		||||
 | 
			
		||||
		if (iloglen < 0) {
 | 
			
		||||
			glDeleteShader(v.frag_id);
 | 
			
		||||
			glDeleteShader(v.vert_id);
 | 
			
		||||
			glDeleteProgram(v.id);
 | 
			
		||||
			v.id = 0;
 | 
			
		||||
 | 
			
		||||
			ERR_PRINT("No OpenGL fragment shader compiler log. What the frick?");
 | 
			
		||||
		} else {
 | 
			
		||||
			if (iloglen == 0) {
 | 
			
		||||
				iloglen = 4096; // buggy driver (Adreno 220+)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			char *ilogmem = (char *)Memory::alloc_static(iloglen + 1);
 | 
			
		||||
			ilogmem[iloglen] = '\0';
 | 
			
		||||
			glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem);
 | 
			
		||||
 | 
			
		||||
			String err_string = get_shader_name() + ": Fragment shader compilation failed:\n";
 | 
			
		||||
 | 
			
		||||
			err_string += ilogmem;
 | 
			
		||||
			err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs);
 | 
			
		||||
 | 
			
		||||
			ERR_PRINTS(err_string);
 | 
			
		||||
 | 
			
		||||
			Memory::free_static(ilogmem);
 | 
			
		||||
			glDeleteShader(v.frag_id);
 | 
			
		||||
			glDeleteShader(v.vert_id);
 | 
			
		||||
			glDeleteProgram(v.id);
 | 
			
		||||
			v.id = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ERR_FAIL_V(NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	glAttachShader(v.id, v.frag_id);
 | 
			
		||||
	glAttachShader(v.id, v.vert_id);
 | 
			
		||||
 | 
			
		||||
	// bind the attribute locations. This has to be done before linking so that the
 | 
			
		||||
	// linker doesn't assign some random indices
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < attribute_pair_count; i++) {
 | 
			
		||||
		glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	glLinkProgram(v.id);
 | 
			
		||||
 | 
			
		||||
	glGetProgramiv(v.id, GL_LINK_STATUS, &status);
 | 
			
		||||
	if (status == GL_FALSE) {
 | 
			
		||||
		GLsizei iloglen;
 | 
			
		||||
		glGetProgramiv(v.id, GL_INFO_LOG_LENGTH, &iloglen);
 | 
			
		||||
 | 
			
		||||
		if (iloglen < 0) {
 | 
			
		||||
			glDeleteShader(v.frag_id);
 | 
			
		||||
			glDeleteShader(v.vert_id);
 | 
			
		||||
			glDeleteProgram(v.id);
 | 
			
		||||
			v.id = 0;
 | 
			
		||||
 | 
			
		||||
			ERR_PRINT("No OpenGL program link log. What the frick?");
 | 
			
		||||
			ERR_FAIL_V(NULL);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (iloglen == 0) {
 | 
			
		||||
			iloglen = 4096; // buggy driver (Adreno 220+)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		char *ilogmem = (char *)Memory::alloc_static(iloglen + 1);
 | 
			
		||||
		ilogmem[iloglen] = '\0';
 | 
			
		||||
		glGetProgramInfoLog(v.id, iloglen, &iloglen, ilogmem);
 | 
			
		||||
 | 
			
		||||
		String err_string = get_shader_name() + ": Program linking failed:\n";
 | 
			
		||||
 | 
			
		||||
		err_string += ilogmem;
 | 
			
		||||
		err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs);
 | 
			
		||||
 | 
			
		||||
		ERR_PRINTS(err_string);
 | 
			
		||||
 | 
			
		||||
		Memory::free_static(ilogmem);
 | 
			
		||||
		glDeleteShader(v.frag_id);
 | 
			
		||||
		glDeleteShader(v.vert_id);
 | 
			
		||||
		glDeleteProgram(v.id);
 | 
			
		||||
		v.id = 0;
 | 
			
		||||
 | 
			
		||||
		ERR_FAIL_V(NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get uniform locations
 | 
			
		||||
 | 
			
		||||
	glUseProgram(v.id);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < uniform_count; i++) {
 | 
			
		||||
		v.uniform_location[i] = glGetUniformLocation(v.id, uniform_names[i]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < texunit_pair_count; i++) {
 | 
			
		||||
		GLint loc = glGetUniformLocation(v.id, texunit_pairs[i].name);
 | 
			
		||||
		if (loc >= 0)
 | 
			
		||||
			glUniform1i(loc, texunit_pairs[i].index);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cc) {
 | 
			
		||||
		v.custom_uniform_locations.resize(cc->custom_uniforms.size());
 | 
			
		||||
		for (int i = 0; i < cc->custom_uniforms.size(); i++) {
 | 
			
		||||
			v.custom_uniform_locations[i] = glGetUniformLocation(v.id, String(cc->custom_uniforms[i]).ascii().get_data());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	glUseProgram(0);
 | 
			
		||||
	v.ok = true;
 | 
			
		||||
 | 
			
		||||
	return &v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLint ShaderGLES2::get_uniform_location(const String &p_name) const {
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_COND_V(!version, -1);
 | 
			
		||||
	return glGetUniformLocation(version->id, p_name.ascii().get_data());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::setup(
 | 
			
		||||
		const char **p_conditional_defines,
 | 
			
		||||
		int p_conditional_count,
 | 
			
		||||
		const char **p_uniform_names,
 | 
			
		||||
		int p_uniform_count,
 | 
			
		||||
		const AttributePair *p_attribute_pairs,
 | 
			
		||||
		int p_attribute_count,
 | 
			
		||||
		const TexUnitPair *p_texunit_pairs,
 | 
			
		||||
		int p_texunit_pair_count,
 | 
			
		||||
		const char *p_vertex_code,
 | 
			
		||||
		const char *p_fragment_code,
 | 
			
		||||
		int p_vertex_code_start,
 | 
			
		||||
		int p_fragment_code_start) {
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_COND(version);
 | 
			
		||||
 | 
			
		||||
	conditional_version.key = 0;
 | 
			
		||||
	new_conditional_version.key = 0;
 | 
			
		||||
	uniform_count = p_uniform_count;
 | 
			
		||||
	conditional_count = p_conditional_count;
 | 
			
		||||
	conditional_defines = p_conditional_defines;
 | 
			
		||||
	uniform_names = p_uniform_names;
 | 
			
		||||
	vertex_code = p_vertex_code;
 | 
			
		||||
	fragment_code = p_fragment_code;
 | 
			
		||||
	texunit_pairs = p_texunit_pairs;
 | 
			
		||||
	texunit_pair_count = p_texunit_pair_count;
 | 
			
		||||
	vertex_code_start = p_vertex_code_start;
 | 
			
		||||
	fragment_code_start = p_fragment_code_start;
 | 
			
		||||
	attribute_pairs = p_attribute_pairs;
 | 
			
		||||
	attribute_pair_count = p_attribute_count;
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		String globals_tag = "\nVERTEX_SHADER_GLOBALS";
 | 
			
		||||
		String code_tag = "\nVERTEX_SHADER_CODE";
 | 
			
		||||
		String code = vertex_code;
 | 
			
		||||
		int cpos = code.find(globals_tag);
 | 
			
		||||
		if (cpos == -1) {
 | 
			
		||||
			vertex_code0 = code.ascii();
 | 
			
		||||
		} else {
 | 
			
		||||
			vertex_code0 = code.substr(0, cpos).ascii();
 | 
			
		||||
			code = code.substr(cpos + globals_tag.length(), code.length());
 | 
			
		||||
 | 
			
		||||
			cpos = code.find(code_tag);
 | 
			
		||||
 | 
			
		||||
			if (cpos == -1) {
 | 
			
		||||
				vertex_code1 = code.ascii();
 | 
			
		||||
			} else {
 | 
			
		||||
				vertex_code1 = code.substr(0, cpos).ascii();
 | 
			
		||||
				vertex_code2 = code.substr(cpos + code_tag.length(), code.length()).ascii();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		String globals_tag = "\nFRAGMENT_SHADER_GLOBALS";
 | 
			
		||||
		String code_tag = "\nFRAGMENT_SHADER_CODE";
 | 
			
		||||
		String light_code_tag = "\nLIGHT_SHADER_CODE";
 | 
			
		||||
		String code = fragment_code;
 | 
			
		||||
		int cpos = code.find(globals_tag);
 | 
			
		||||
		if (cpos == -1) {
 | 
			
		||||
			fragment_code0 = code.ascii();
 | 
			
		||||
		} else {
 | 
			
		||||
			fragment_code0 = code.substr(0, cpos).ascii();
 | 
			
		||||
			code = code.substr(cpos + globals_tag.length(), code.length());
 | 
			
		||||
 | 
			
		||||
			cpos = code.find(code_tag);
 | 
			
		||||
 | 
			
		||||
			if (cpos == -1) {
 | 
			
		||||
				fragment_code1 = code.ascii();
 | 
			
		||||
			} else {
 | 
			
		||||
 | 
			
		||||
				fragment_code1 = code.substr(0, cpos).ascii();
 | 
			
		||||
				String code2 = code.substr(cpos + code_tag.length(), code.length());
 | 
			
		||||
 | 
			
		||||
				cpos = code2.find(light_code_tag);
 | 
			
		||||
				if (cpos == -1) {
 | 
			
		||||
					fragment_code2 = code2.ascii();
 | 
			
		||||
				} else {
 | 
			
		||||
					fragment_code2 = code2.substr(0, cpos).ascii();
 | 
			
		||||
					fragment_code3 = code2.substr(cpos + light_code_tag.length(), code2.length()).ascii();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::finish() {
 | 
			
		||||
	const VersionKey *V = NULL;
 | 
			
		||||
 | 
			
		||||
	while ((V = version_map.next(V))) {
 | 
			
		||||
		Version &v = version_map[*V];
 | 
			
		||||
		glDeleteShader(v.vert_id);
 | 
			
		||||
		glDeleteShader(v.frag_id);
 | 
			
		||||
		glDeleteProgram(v.id);
 | 
			
		||||
		memdelete_arr(v.uniform_location);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::clear_caches() {
 | 
			
		||||
	const VersionKey *V = NULL;
 | 
			
		||||
 | 
			
		||||
	while ((V = version_map.next(V))) {
 | 
			
		||||
		Version &v = version_map[*V];
 | 
			
		||||
		glDeleteShader(v.vert_id);
 | 
			
		||||
		glDeleteShader(v.frag_id);
 | 
			
		||||
		glDeleteProgram(v.id);
 | 
			
		||||
		memdelete_arr(v.uniform_location);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	version_map.clear();
 | 
			
		||||
 | 
			
		||||
	custom_code_map.clear();
 | 
			
		||||
	version = NULL;
 | 
			
		||||
	last_custom_code = 1;
 | 
			
		||||
	uniforms_dirty = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t ShaderGLES2::create_custom_shader() {
 | 
			
		||||
	custom_code_map[last_custom_code] = CustomCode();
 | 
			
		||||
	custom_code_map[last_custom_code].version = 1;
 | 
			
		||||
	return last_custom_code++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::set_custom_shader_code(uint32_t p_code_id,
 | 
			
		||||
		const String &p_vertex,
 | 
			
		||||
		const String &p_vertex_globals,
 | 
			
		||||
		const String &p_fragment,
 | 
			
		||||
		const String &p_light,
 | 
			
		||||
		const String &p_fragment_globals,
 | 
			
		||||
		const Vector<StringName> &p_uniforms,
 | 
			
		||||
		const Vector<StringName> &p_texture_uniforms,
 | 
			
		||||
		const Vector<CharString> &p_custom_defines) {
 | 
			
		||||
	CustomCode *cc = custom_code_map.getptr(p_code_id);
 | 
			
		||||
	ERR_FAIL_COND(!cc);
 | 
			
		||||
 | 
			
		||||
	cc->vertex = p_vertex;
 | 
			
		||||
	cc->vertex_globals = p_vertex_globals;
 | 
			
		||||
	cc->fragment = p_fragment;
 | 
			
		||||
	cc->fragment_globals = p_fragment_globals;
 | 
			
		||||
	cc->light = p_light;
 | 
			
		||||
	cc->custom_uniforms = p_uniforms;
 | 
			
		||||
	cc->custom_defines = p_custom_defines;
 | 
			
		||||
	cc->version++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::set_custom_shader(uint32_t p_code_id) {
 | 
			
		||||
	new_conditional_version.code_version = p_code_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::free_custom_shader(uint32_t p_code_id) {
 | 
			
		||||
	ERR_FAIL_COND(!custom_code_map.has(p_code_id));
 | 
			
		||||
	if (conditional_version.code_version == p_code_id)
 | 
			
		||||
		conditional_version.code_version = 0;
 | 
			
		||||
 | 
			
		||||
	custom_code_map.erase(p_code_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::set_base_material_tex_index(int p_idx) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShaderGLES2::ShaderGLES2() {
 | 
			
		||||
	version = NULL;
 | 
			
		||||
	last_custom_code = 1;
 | 
			
		||||
	uniforms_dirty = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShaderGLES2::~ShaderGLES2() {
 | 
			
		||||
	finish();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										386
									
								
								drivers/gles2/shader_gles2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										386
									
								
								drivers/gles2/shader_gles2.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,386 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
/*  shader_gles2.h                                                       */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/*                       This file is part of:                           */
 | 
			
		||||
/*                           GODOT ENGINE                                */
 | 
			
		||||
/*                      https://godotengine.org                          */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
 | 
			
		||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
			
		||||
/* a copy of this software and associated documentation files (the       */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including   */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to */
 | 
			
		||||
/* the following conditions:                                             */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be        */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.       */
 | 
			
		||||
/*                                                                       */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
			
		||||
/*************************************************************************/
 | 
			
		||||
#ifndef SHADER_GLES2_H
 | 
			
		||||
#define SHADER_GLES2_H
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "platform_config.h"
 | 
			
		||||
#ifndef GLES2_INCLUDE_H
 | 
			
		||||
#include <GLES2/gl2.h>
 | 
			
		||||
#else
 | 
			
		||||
#include GLES2_INCLUDE_H
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "camera_matrix.h"
 | 
			
		||||
#include "hash_map.h"
 | 
			
		||||
#include "map.h"
 | 
			
		||||
#include "variant.h"
 | 
			
		||||
 | 
			
		||||
class ShaderGLES2 {
 | 
			
		||||
protected:
 | 
			
		||||
	struct Enum {
 | 
			
		||||
 | 
			
		||||
		uint64_t mask;
 | 
			
		||||
		uint64_t shift;
 | 
			
		||||
		const char *defines[16];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct EnumValue {
 | 
			
		||||
 | 
			
		||||
		uint64_t set_mask;
 | 
			
		||||
		uint64_t clear_mask;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct AttributePair {
 | 
			
		||||
 | 
			
		||||
		const char *name;
 | 
			
		||||
		int index;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct UniformPair {
 | 
			
		||||
		const char *name;
 | 
			
		||||
		Variant::Type type_hint;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct TexUnitPair {
 | 
			
		||||
 | 
			
		||||
		const char *name;
 | 
			
		||||
		int index;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	bool uniforms_dirty;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	//@TODO Optimize to a fixed set of shader pools and use a LRU
 | 
			
		||||
	int uniform_count;
 | 
			
		||||
	int texunit_pair_count;
 | 
			
		||||
	int conditional_count;
 | 
			
		||||
	int vertex_code_start;
 | 
			
		||||
	int fragment_code_start;
 | 
			
		||||
	int attribute_pair_count;
 | 
			
		||||
 | 
			
		||||
	struct CustomCode {
 | 
			
		||||
 | 
			
		||||
		String vertex;
 | 
			
		||||
		String vertex_globals;
 | 
			
		||||
		String fragment;
 | 
			
		||||
		String fragment_globals;
 | 
			
		||||
		String light;
 | 
			
		||||
		uint32_t version;
 | 
			
		||||
		Vector<StringName> texture_uniforms;
 | 
			
		||||
		Vector<StringName> custom_uniforms;
 | 
			
		||||
		Vector<CharString> custom_defines;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct Version {
 | 
			
		||||
 | 
			
		||||
		GLuint id;
 | 
			
		||||
		GLuint vert_id;
 | 
			
		||||
		GLuint frag_id;
 | 
			
		||||
		GLint *uniform_location;
 | 
			
		||||
		Vector<GLint> texture_uniform_locations;
 | 
			
		||||
		Vector<GLint> custom_uniform_locations;
 | 
			
		||||
		uint32_t code_version;
 | 
			
		||||
		bool ok;
 | 
			
		||||
		Version() {
 | 
			
		||||
			code_version = 0;
 | 
			
		||||
			ok = false;
 | 
			
		||||
			uniform_location = NULL;
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Version *version;
 | 
			
		||||
 | 
			
		||||
	union VersionKey {
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			uint32_t version;
 | 
			
		||||
			uint32_t code_version;
 | 
			
		||||
		};
 | 
			
		||||
		uint64_t key;
 | 
			
		||||
		bool operator==(const VersionKey &p_key) const { return key == p_key.key; }
 | 
			
		||||
		bool operator<(const VersionKey &p_key) const { return key < p_key.key; }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct VersionKeyHash {
 | 
			
		||||
 | 
			
		||||
		static _FORCE_INLINE_ uint32_t hash(const VersionKey &p_key) { return HashMapHasherDefault::hash(p_key.key); }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	//this should use a way more cachefriendly version..
 | 
			
		||||
	HashMap<VersionKey, Version, VersionKeyHash> version_map;
 | 
			
		||||
 | 
			
		||||
	HashMap<uint32_t, CustomCode> custom_code_map;
 | 
			
		||||
	uint32_t last_custom_code;
 | 
			
		||||
 | 
			
		||||
	VersionKey conditional_version;
 | 
			
		||||
	VersionKey new_conditional_version;
 | 
			
		||||
 | 
			
		||||
	virtual String get_shader_name() const = 0;
 | 
			
		||||
 | 
			
		||||
	const char **conditional_defines;
 | 
			
		||||
	const char **uniform_names;
 | 
			
		||||
	const AttributePair *attribute_pairs;
 | 
			
		||||
	const TexUnitPair *texunit_pairs;
 | 
			
		||||
	const char *vertex_code;
 | 
			
		||||
	const char *fragment_code;
 | 
			
		||||
	CharString fragment_code0;
 | 
			
		||||
	CharString fragment_code1;
 | 
			
		||||
	CharString fragment_code2;
 | 
			
		||||
	CharString fragment_code3;
 | 
			
		||||
 | 
			
		||||
	CharString vertex_code0;
 | 
			
		||||
	CharString vertex_code1;
 | 
			
		||||
	CharString vertex_code2;
 | 
			
		||||
 | 
			
		||||
	Vector<CharString> custom_defines;
 | 
			
		||||
 | 
			
		||||
	Version *get_current_version();
 | 
			
		||||
 | 
			
		||||
	static ShaderGLES2 *active;
 | 
			
		||||
 | 
			
		||||
	int max_image_units;
 | 
			
		||||
 | 
			
		||||
	_FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform, const Variant &p_value) {
 | 
			
		||||
 | 
			
		||||
		if (p_uniform < 0)
 | 
			
		||||
			return; // do none
 | 
			
		||||
		switch (p_value.get_type()) {
 | 
			
		||||
 | 
			
		||||
			case Variant::BOOL:
 | 
			
		||||
			case Variant::INT: {
 | 
			
		||||
 | 
			
		||||
				int val = p_value;
 | 
			
		||||
				glUniform1i(p_uniform, val);
 | 
			
		||||
			} break;
 | 
			
		||||
			case Variant::REAL: {
 | 
			
		||||
 | 
			
		||||
				real_t val = p_value;
 | 
			
		||||
				glUniform1f(p_uniform, val);
 | 
			
		||||
			} break;
 | 
			
		||||
			case Variant::COLOR: {
 | 
			
		||||
 | 
			
		||||
				Color val = p_value;
 | 
			
		||||
				glUniform4f(p_uniform, val.r, val.g, val.b, val.a);
 | 
			
		||||
			} break;
 | 
			
		||||
			case Variant::VECTOR2: {
 | 
			
		||||
 | 
			
		||||
				Vector2 val = p_value;
 | 
			
		||||
				glUniform2f(p_uniform, val.x, val.y);
 | 
			
		||||
			} break;
 | 
			
		||||
			case Variant::VECTOR3: {
 | 
			
		||||
 | 
			
		||||
				Vector3 val = p_value;
 | 
			
		||||
				glUniform3f(p_uniform, val.x, val.y, val.z);
 | 
			
		||||
			} break;
 | 
			
		||||
			case Variant::PLANE: {
 | 
			
		||||
 | 
			
		||||
				Plane val = p_value;
 | 
			
		||||
				glUniform4f(p_uniform, val.normal.x, val.normal.y, val.normal.z, val.d);
 | 
			
		||||
			} break;
 | 
			
		||||
			case Variant::QUAT: {
 | 
			
		||||
 | 
			
		||||
				Quat val = p_value;
 | 
			
		||||
				glUniform4f(p_uniform, val.x, val.y, val.z, val.w);
 | 
			
		||||
			} break;
 | 
			
		||||
 | 
			
		||||
			case Variant::TRANSFORM2D: {
 | 
			
		||||
 | 
			
		||||
				Transform2D tr = p_value;
 | 
			
		||||
				GLfloat matrix[16] = { /* build a 16x16 matrix */
 | 
			
		||||
					tr.elements[0][0],
 | 
			
		||||
					tr.elements[0][1],
 | 
			
		||||
					0,
 | 
			
		||||
					0,
 | 
			
		||||
					tr.elements[1][0],
 | 
			
		||||
					tr.elements[1][1],
 | 
			
		||||
					0,
 | 
			
		||||
					0,
 | 
			
		||||
					0,
 | 
			
		||||
					0,
 | 
			
		||||
					1,
 | 
			
		||||
					0,
 | 
			
		||||
					tr.elements[2][0],
 | 
			
		||||
					tr.elements[2][1],
 | 
			
		||||
					0,
 | 
			
		||||
					1
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				glUniformMatrix4fv(p_uniform, 1, false, matrix);
 | 
			
		||||
 | 
			
		||||
			} break;
 | 
			
		||||
			case Variant::BASIS:
 | 
			
		||||
			case Variant::TRANSFORM: {
 | 
			
		||||
 | 
			
		||||
				Transform tr = p_value;
 | 
			
		||||
				GLfloat matrix[16] = { /* build a 16x16 matrix */
 | 
			
		||||
					tr.basis.elements[0][0],
 | 
			
		||||
					tr.basis.elements[1][0],
 | 
			
		||||
					tr.basis.elements[2][0],
 | 
			
		||||
					0,
 | 
			
		||||
					tr.basis.elements[0][1],
 | 
			
		||||
					tr.basis.elements[1][1],
 | 
			
		||||
					tr.basis.elements[2][1],
 | 
			
		||||
					0,
 | 
			
		||||
					tr.basis.elements[0][2],
 | 
			
		||||
					tr.basis.elements[1][2],
 | 
			
		||||
					tr.basis.elements[2][2],
 | 
			
		||||
					0,
 | 
			
		||||
					tr.origin.x,
 | 
			
		||||
					tr.origin.y,
 | 
			
		||||
					tr.origin.z,
 | 
			
		||||
					1
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				glUniformMatrix4fv(p_uniform, 1, false, matrix);
 | 
			
		||||
			} break;
 | 
			
		||||
			default: { ERR_FAIL(); } // do nothing
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Map<uint32_t, Variant> uniform_defaults;
 | 
			
		||||
	Map<uint32_t, CameraMatrix> uniform_cameras;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	_FORCE_INLINE_ int _get_uniform(int p_which) const;
 | 
			
		||||
	_FORCE_INLINE_ void _set_conditional(int p_which, bool p_value);
 | 
			
		||||
 | 
			
		||||
	void setup(const char **p_conditional_defines,
 | 
			
		||||
			int p_conditional_count,
 | 
			
		||||
			const char **p_uniform_names,
 | 
			
		||||
			int p_uniform_count,
 | 
			
		||||
			const AttributePair *p_attribute_pairs,
 | 
			
		||||
			int p_attribute_count,
 | 
			
		||||
			const TexUnitPair *p_texunit_pairs,
 | 
			
		||||
			int p_texunit_pair_count,
 | 
			
		||||
			const char *p_vertex_code,
 | 
			
		||||
			const char *p_fragment_code,
 | 
			
		||||
			int p_vertex_code_start,
 | 
			
		||||
			int p_fragment_code_start);
 | 
			
		||||
 | 
			
		||||
	ShaderGLES2();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	enum {
 | 
			
		||||
		CUSTOM_SHADER_DISABLED = 0
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	GLint get_uniform_location(const String &p_name) const;
 | 
			
		||||
	GLint get_uniform_location(int p_index) const;
 | 
			
		||||
 | 
			
		||||
	static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; }
 | 
			
		||||
	bool bind();
 | 
			
		||||
	void unbind();
 | 
			
		||||
	void bind_uniforms();
 | 
			
		||||
 | 
			
		||||
	inline GLuint get_program() const { return version ? version->id : 0; }
 | 
			
		||||
 | 
			
		||||
	void clear_caches();
 | 
			
		||||
 | 
			
		||||
	uint32_t create_custom_shader();
 | 
			
		||||
	void set_custom_shader_code(uint32_t p_code_id,
 | 
			
		||||
			const String &p_vertex,
 | 
			
		||||
			const String &p_vertex_globals,
 | 
			
		||||
			const String &p_fragment,
 | 
			
		||||
			const String &p_light,
 | 
			
		||||
			const String &p_fragment_globals,
 | 
			
		||||
			const Vector<StringName> &p_uniforms,
 | 
			
		||||
			const Vector<StringName> &p_texture_uniforms,
 | 
			
		||||
			const Vector<CharString> &p_custom_defines);
 | 
			
		||||
 | 
			
		||||
	void set_custom_shader(uint32_t p_code_id);
 | 
			
		||||
	void free_custom_shader(uint32_t p_code_id);
 | 
			
		||||
 | 
			
		||||
	void set_uniform_default(int p_idx, const Variant &p_value) {
 | 
			
		||||
 | 
			
		||||
		if (p_value.get_type() == Variant::NIL) {
 | 
			
		||||
 | 
			
		||||
			uniform_defaults.erase(p_idx);
 | 
			
		||||
		} else {
 | 
			
		||||
 | 
			
		||||
			uniform_defaults[p_idx] = p_value;
 | 
			
		||||
		}
 | 
			
		||||
		uniforms_dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint32_t get_version() const { return new_conditional_version.version; }
 | 
			
		||||
 | 
			
		||||
	void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) {
 | 
			
		||||
 | 
			
		||||
		uniform_cameras[p_idx] = p_mat;
 | 
			
		||||
		uniforms_dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant &p_value) {
 | 
			
		||||
 | 
			
		||||
		ERR_FAIL_COND(!version);
 | 
			
		||||
		ERR_FAIL_INDEX(p_idx, version->texture_uniform_locations.size());
 | 
			
		||||
		_set_uniform_variant(version->texture_uniform_locations[p_idx], p_value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) {
 | 
			
		||||
 | 
			
		||||
		ERR_FAIL_COND_V(!version, -1);
 | 
			
		||||
		ERR_FAIL_INDEX_V(p_idx, version->texture_uniform_locations.size(), -1);
 | 
			
		||||
		return version->texture_uniform_locations[p_idx];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	virtual void init() = 0;
 | 
			
		||||
	void finish();
 | 
			
		||||
 | 
			
		||||
	void set_base_material_tex_index(int p_idx);
 | 
			
		||||
 | 
			
		||||
	void add_custom_define(const String &p_define) {
 | 
			
		||||
		custom_defines.push_back(p_define.utf8());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	virtual ~ShaderGLES2();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// called a lot, made inline
 | 
			
		||||
 | 
			
		||||
int ShaderGLES2::_get_uniform(int p_which) const {
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_INDEX_V(p_which, uniform_count, -1);
 | 
			
		||||
	ERR_FAIL_COND_V(!version, -1);
 | 
			
		||||
	return version->uniform_location[p_which];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShaderGLES2::_set_conditional(int p_which, bool p_value) {
 | 
			
		||||
 | 
			
		||||
	ERR_FAIL_INDEX(p_which, conditional_count);
 | 
			
		||||
	if (p_value)
 | 
			
		||||
		new_conditional_version.version |= (1 << p_which);
 | 
			
		||||
	else
 | 
			
		||||
		new_conditional_version.version &= ~(1 << p_which);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										22
									
								
								drivers/gles2/shaders/SCsub
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								drivers/gles2/shaders/SCsub
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
Import('env')
 | 
			
		||||
 | 
			
		||||
if 'GLES2_GLSL' in env['BUILDERS']:
 | 
			
		||||
    env.GLES2_GLSL('copy.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('resolve.glsl');
 | 
			
		||||
    env.GLES2_GLSL('canvas.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('canvas_shadow.glsl');
 | 
			
		||||
    env.GLES2_GLSL('scene.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('cubemap_filter.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('cube_to_dp.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('blend_shape.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('screen_space_reflection.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('effect_blur.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('subsurf_scattering.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('ssao.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('ssao_minify.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('ssao_blur.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('exposure.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('tonemap.glsl');
 | 
			
		||||
#    env.GLES2_GLSL('particles.glsl');
 | 
			
		||||
							
								
								
									
										197
									
								
								drivers/gles2/shaders/blend_shape.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								drivers/gles2/shaders/blend_shape.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,197 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
from VisualServer:
 | 
			
		||||
 | 
			
		||||
ARRAY_VERTEX=0,
 | 
			
		||||
ARRAY_NORMAL=1,
 | 
			
		||||
ARRAY_TANGENT=2,
 | 
			
		||||
ARRAY_COLOR=3,
 | 
			
		||||
ARRAY_TEX_UV=4,
 | 
			
		||||
ARRAY_TEX_UV2=5,
 | 
			
		||||
ARRAY_BONES=6,
 | 
			
		||||
ARRAY_WEIGHTS=7,
 | 
			
		||||
ARRAY_INDEX=8,
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifdef USE_2D_VERTEX
 | 
			
		||||
#define VFORMAT vec2
 | 
			
		||||
#else
 | 
			
		||||
#define VFORMAT vec3
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* INPUT ATTRIBS */
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp VFORMAT vertex_attrib;
 | 
			
		||||
layout(location=1) in vec3 normal_attrib;
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_TANGENT
 | 
			
		||||
layout(location=2) in vec4 tangent_attrib;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_COLOR
 | 
			
		||||
layout(location=3) in vec4 color_attrib;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV
 | 
			
		||||
layout(location=4) in vec2 uv_attrib;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV2
 | 
			
		||||
layout(location=5) in vec2 uv2_attrib;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_SKELETON
 | 
			
		||||
layout(location=6) in ivec4 bone_attrib;
 | 
			
		||||
layout(location=7) in vec4 weight_attrib;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* BLEND ATTRIBS */
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_BLEND
 | 
			
		||||
 | 
			
		||||
layout(location=8) in highp VFORMAT vertex_attrib_blend;
 | 
			
		||||
layout(location=9) in vec3 normal_attrib_blend;
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_TANGENT
 | 
			
		||||
layout(location=10) in vec4 tangent_attrib_blend;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_COLOR
 | 
			
		||||
layout(location=11) in vec4 color_attrib_blend;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV
 | 
			
		||||
layout(location=12) in vec2 uv_attrib_blend;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV2
 | 
			
		||||
layout(location=13) in vec2 uv2_attrib_blend;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_SKELETON
 | 
			
		||||
layout(location=14) in ivec4 bone_attrib_blend;
 | 
			
		||||
layout(location=15) in vec4 weight_attrib_blend;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* OUTPUTS */
 | 
			
		||||
 | 
			
		||||
out VFORMAT vertex_out; //tfb:
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_NORMAL
 | 
			
		||||
out vec3 normal_out; //tfb:ENABLE_NORMAL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_TANGENT
 | 
			
		||||
out vec4 tangent_out; //tfb:ENABLE_TANGENT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_COLOR
 | 
			
		||||
out vec4 color_out; //tfb:ENABLE_COLOR
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV
 | 
			
		||||
out vec2 uv_out; //tfb:ENABLE_UV
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV2
 | 
			
		||||
out vec2 uv2_out; //tfb:ENABLE_UV2
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_SKELETON
 | 
			
		||||
out ivec4 bone_out; //tfb:ENABLE_SKELETON
 | 
			
		||||
out vec4 weight_out; //tfb:ENABLE_SKELETON
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform float blend_amount;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_BLEND
 | 
			
		||||
 | 
			
		||||
	vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount;
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_NORMAL
 | 
			
		||||
	normal_out = normal_attrib_blend + normal_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_TANGENT
 | 
			
		||||
 | 
			
		||||
	tangent_out.xyz = tangent_attrib_blend.xyz + tangent_attrib.xyz * blend_amount;
 | 
			
		||||
	tangent_out.w = tangent_attrib_blend.w; //just copy, no point in blending his
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_COLOR
 | 
			
		||||
 | 
			
		||||
	color_out = color_attrib_blend + color_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV
 | 
			
		||||
 | 
			
		||||
	uv_out = uv_attrib_blend + uv_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV2
 | 
			
		||||
 | 
			
		||||
	uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_SKELETON
 | 
			
		||||
 | 
			
		||||
	bone_out = bone_attrib_blend;
 | 
			
		||||
	weight_out = weight_attrib_blend + weight_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else //ENABLE_BLEND
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	vertex_out = vertex_attrib * blend_amount;
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_NORMAL
 | 
			
		||||
	normal_out = normal_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_TANGENT
 | 
			
		||||
 | 
			
		||||
	tangent_out.xyz = tangent_attrib.xyz * blend_amount;
 | 
			
		||||
	tangent_out.w = tangent_attrib.w; //just copy, no point in blending his
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_COLOR
 | 
			
		||||
 | 
			
		||||
	color_out = color_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV
 | 
			
		||||
 | 
			
		||||
	uv_out = uv_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_UV2
 | 
			
		||||
 | 
			
		||||
	uv2_out = uv2_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_SKELETON
 | 
			
		||||
 | 
			
		||||
	bone_out = bone_attrib;
 | 
			
		||||
	weight_out = weight_attrib * blend_amount;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
	gl_Position = vec4(0.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										141
									
								
								drivers/gles2/shaders/canvas.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								drivers/gles2/shaders/canvas.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,141 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLES_OVER_GL
 | 
			
		||||
#define mediump
 | 
			
		||||
#define highp
 | 
			
		||||
#else
 | 
			
		||||
precision mediump float;
 | 
			
		||||
precision mediump int;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform highp mat4 projection_matrix;
 | 
			
		||||
uniform highp mat4 modelview_matrix;
 | 
			
		||||
uniform highp mat4 extra_matrix;
 | 
			
		||||
attribute highp vec2 vertex; // attrib:0
 | 
			
		||||
attribute vec4 color_attrib; // attrib:3
 | 
			
		||||
attribute vec2 uv_attrib; // attrib:4
 | 
			
		||||
 | 
			
		||||
varying vec2 uv_interp;
 | 
			
		||||
varying vec4 color_interp;
 | 
			
		||||
 | 
			
		||||
uniform highp vec2 color_texpixel_size;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_TEXTURE_RECT
 | 
			
		||||
 | 
			
		||||
uniform vec4 dst_rect;
 | 
			
		||||
uniform vec4 src_rect;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform bool blit_pass;
 | 
			
		||||
 | 
			
		||||
VERTEX_SHADER_GLOBALS
 | 
			
		||||
 | 
			
		||||
vec2 select(vec2 a, vec2 b, bvec2 c) {
 | 
			
		||||
	vec2 ret;
 | 
			
		||||
 | 
			
		||||
	ret.x = c.x ? b.x : a.x;
 | 
			
		||||
	ret.y = c.y ? b.y : a.y;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	vec4 color = color_attrib;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_TEXTURE_RECT
 | 
			
		||||
 | 
			
		||||
	if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
 | 
			
		||||
		uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx;
 | 
			
		||||
	} else {
 | 
			
		||||
		uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vec4 outvec = vec4(0.0, 0.0, 0.0, 1.0);
 | 
			
		||||
 | 
			
		||||
	// This is what is done in the GLES 3 bindings and should
 | 
			
		||||
	// take care of flipped rects.
 | 
			
		||||
	//
 | 
			
		||||
	// But it doesn't.
 | 
			
		||||
	// I don't know why, will need to investigate further.
 | 
			
		||||
 | 
			
		||||
	outvec.xy = dst_rect.xy + abs(dst_rect.zw) * select(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0)));
 | 
			
		||||
 | 
			
		||||
	// outvec.xy = dst_rect.xy + abs(dst_rect.zw) * vertex;
 | 
			
		||||
#else
 | 
			
		||||
	vec4 outvec = vec4(vertex.xy, 0.0, 1.0);
 | 
			
		||||
 | 
			
		||||
#ifdef USE_UV_ATTRIBUTE
 | 
			
		||||
	uv_interp = uv_attrib;
 | 
			
		||||
#else
 | 
			
		||||
	uv_interp = vertex.xy;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
        vec2 src_vtx=outvec.xy;
 | 
			
		||||
VERTEX_SHADER_CODE
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	color_interp = color;
 | 
			
		||||
 | 
			
		||||
	gl_Position = projection_matrix * modelview_matrix * outvec;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLES_OVER_GL
 | 
			
		||||
#define mediump
 | 
			
		||||
#define highp
 | 
			
		||||
#else
 | 
			
		||||
precision mediump float;
 | 
			
		||||
precision mediump int;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform sampler2D color_texture; // texunit:0
 | 
			
		||||
uniform highp vec2 color_texpixel_size;
 | 
			
		||||
uniform mediump sampler2D normal_texture; // texunit:1
 | 
			
		||||
 | 
			
		||||
varying mediump vec2 uv_interp;
 | 
			
		||||
varying mediump vec4 color_interp;
 | 
			
		||||
 | 
			
		||||
uniform bool blit_pass;
 | 
			
		||||
 | 
			
		||||
uniform vec4 final_modulate;
 | 
			
		||||
 | 
			
		||||
#ifdef SCREEN_TEXTURE_USED
 | 
			
		||||
 | 
			
		||||
uniform sampler2D screen_texture; // texunit:2
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SCREEN_UV_USED
 | 
			
		||||
 | 
			
		||||
uniform vec2 screen_pixel_size;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
FRAGMENT_SHADER_GLOBALS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	vec4 color = color_interp;
 | 
			
		||||
 | 
			
		||||
	color *= texture2D(color_texture, uv_interp);
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
FRAGMENT_SHADER_CODE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	color *= final_modulate;
 | 
			
		||||
 | 
			
		||||
	gl_FragColor = color;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								drivers/gles2/shaders/canvas_shadow.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								drivers/gles2/shaders/canvas_shadow.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uniform highp mat4 projection_matrix;
 | 
			
		||||
uniform highp mat4 light_matrix;
 | 
			
		||||
uniform highp mat4 world_matrix;
 | 
			
		||||
uniform highp float distance_norm;
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec3 vertex;
 | 
			
		||||
 | 
			
		||||
out highp vec4 position_interp;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	gl_Position = projection_matrix * (light_matrix * (world_matrix *  vec4(vertex,1.0)));
 | 
			
		||||
	position_interp=gl_Position;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
in highp vec4 position_interp;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_RGBA_SHADOWS
 | 
			
		||||
 | 
			
		||||
layout(location=0) out lowp vec4 distance_buf;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
layout(location=0) out highp float distance_buf;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_RGBA_SHADOWS
 | 
			
		||||
 | 
			
		||||
	highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
 | 
			
		||||
	comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
 | 
			
		||||
	distance_buf=comp;
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	distance_buf=depth;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										72
									
								
								drivers/gles2/shaders/copy.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								drivers/gles2/shaders/copy.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLES_OVER_GL
 | 
			
		||||
#define mediump
 | 
			
		||||
#define highp
 | 
			
		||||
#else
 | 
			
		||||
precision mediump float;
 | 
			
		||||
precision mediump int;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
attribute highp vec4 vertex_attrib; // attrib:0
 | 
			
		||||
attribute vec2 uv_in; // attrib:4
 | 
			
		||||
attribute vec2 uv2_in; // attrib:5
 | 
			
		||||
 | 
			
		||||
varying vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
varying vec2 uv2_interp;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_COPY_SECTION
 | 
			
		||||
uniform vec4 copy_section;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	uv_interp = uv_in;
 | 
			
		||||
	uv2_interp = uv2_in;
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_COPY_SECTION
 | 
			
		||||
	uv_interp = copy_section.xy + uv_interp * copy_section.zw;
 | 
			
		||||
	gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLES_OVER_GL
 | 
			
		||||
#define mediump
 | 
			
		||||
#define highp
 | 
			
		||||
#else
 | 
			
		||||
precision mediump float;
 | 
			
		||||
precision mediump int;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
varying vec2 uv_interp;
 | 
			
		||||
uniform sampler2D source; // texunit:0
 | 
			
		||||
 | 
			
		||||
varying vec2 uv2_interp;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CUSTOM_ALPHA
 | 
			
		||||
uniform float custom_alpha;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	//vec4 color = color_interp;
 | 
			
		||||
	vec4 color = texture2D( source,  uv_interp );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef USE_NO_ALPHA
 | 
			
		||||
	color.a=1.0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CUSTOM_ALPHA
 | 
			
		||||
	color.a=custom_alpha;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	gl_FragColor = color;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										79
									
								
								drivers/gles2/shaders/cube_to_dp.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								drivers/gles2/shaders/cube_to_dp.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
layout(location=4) in vec2 uv_in;
 | 
			
		||||
 | 
			
		||||
out vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	uv_interp = uv_in;
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uniform highp samplerCube source_cube; //texunit:0
 | 
			
		||||
in vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
uniform bool z_flip;
 | 
			
		||||
uniform highp float z_far;
 | 
			
		||||
uniform highp float z_near;
 | 
			
		||||
uniform highp float bias;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	highp vec3 normal = vec3( uv_interp * 2.0 - 1.0, 0.0 );
 | 
			
		||||
/*
 | 
			
		||||
	if(z_flip) {
 | 
			
		||||
		normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y));
 | 
			
		||||
	} else {
 | 
			
		||||
		normal.z = -0.5 + 0.5*((normal.x * normal.x) + (normal.y * normal.y));
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
	//normal.z = sqrt(1.0-dot(normal.xy,normal.xy));
 | 
			
		||||
	//normal.xy*=1.0+normal.z;
 | 
			
		||||
 | 
			
		||||
	normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y));
 | 
			
		||||
	normal = normalize(normal);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	normal.z=0.5;
 | 
			
		||||
	normal=normalize(normal);
 | 
			
		||||
*/
 | 
			
		||||
	if (!z_flip) {
 | 
			
		||||
		normal.z=-normal.z;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 ));
 | 
			
		||||
	float depth = texture(source_cube,normal).r;
 | 
			
		||||
 | 
			
		||||
	// absolute values for direction cosines, bigger value equals closer to basis axis
 | 
			
		||||
	vec3 unorm = abs(normal);
 | 
			
		||||
 | 
			
		||||
	if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) {
 | 
			
		||||
	    // x code
 | 
			
		||||
	    unorm = normal.x > 0.0 ?  vec3( 1.0, 0.0, 0.0 ) : vec3( -1.0, 0.0, 0.0 ) ;
 | 
			
		||||
	} else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) {
 | 
			
		||||
	    // y code
 | 
			
		||||
	    unorm = normal.y > 0.0 ?  vec3( 0.0, 1.0, 0.0 ) :  vec3( 0.0, -1.0, 0.0 ) ;
 | 
			
		||||
	} else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) {
 | 
			
		||||
	    // z code
 | 
			
		||||
	    unorm = normal.z > 0.0 ?  vec3( 0.0, 0.0, 1.0 ) :  vec3( 0.0, 0.0, -1.0 ) ;
 | 
			
		||||
	} else {
 | 
			
		||||
	    // oh-no we messed up code
 | 
			
		||||
	    // has to be
 | 
			
		||||
	    unorm = vec3( 1.0, 0.0, 0.0 );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	float depth_fix = 1.0 / dot(normal,unorm);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	depth = 2.0 * depth - 1.0;
 | 
			
		||||
	float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near));
 | 
			
		||||
	gl_FragDepth = (linear_depth*depth_fix+bias) / z_far;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										294
									
								
								drivers/gles2/shaders/cubemap_filter.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								drivers/gles2/shaders/cubemap_filter.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,294 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec2 vertex;
 | 
			
		||||
 | 
			
		||||
layout(location=4) in highp vec2 uv;
 | 
			
		||||
 | 
			
		||||
out highp vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	uv_interp=uv;
 | 
			
		||||
	gl_Position=vec4(vertex,0,1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
precision highp float;
 | 
			
		||||
precision highp int;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOURCE_PANORAMA
 | 
			
		||||
uniform sampler2D source_panorama; //texunit:0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
 | 
			
		||||
uniform sampler2DArray source_dual_paraboloid_array; //texunit:0
 | 
			
		||||
uniform int source_array_index;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
 | 
			
		||||
uniform samplerCube source_cube; //texunit:0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform int face_id;
 | 
			
		||||
uniform float roughness;
 | 
			
		||||
in highp vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 frag_color;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define M_PI 3.14159265359
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vec3 texelCoordToVec(vec2 uv, int faceID)
 | 
			
		||||
{
 | 
			
		||||
    mat3 faceUvVectors[6];
 | 
			
		||||
/*
 | 
			
		||||
    // -x
 | 
			
		||||
    faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0);  // u -> +z
 | 
			
		||||
    faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
 | 
			
		||||
 | 
			
		||||
    // +x
 | 
			
		||||
    faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
 | 
			
		||||
    faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0);  // +x face
 | 
			
		||||
 | 
			
		||||
    // -y
 | 
			
		||||
    faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0);  // u -> +x
 | 
			
		||||
    faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
 | 
			
		||||
    faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
 | 
			
		||||
 | 
			
		||||
    // +y
 | 
			
		||||
    faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0);  // u -> +x
 | 
			
		||||
    faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0);  // v -> +z
 | 
			
		||||
    faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0);  // +y face
 | 
			
		||||
 | 
			
		||||
    // -z
 | 
			
		||||
    faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
 | 
			
		||||
    faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
 | 
			
		||||
 | 
			
		||||
    // +z
 | 
			
		||||
    faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0);  // u -> +x
 | 
			
		||||
    faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0);  // +z face
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
    // -x
 | 
			
		||||
    faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0);  // u -> +z
 | 
			
		||||
    faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face
 | 
			
		||||
 | 
			
		||||
    // +x
 | 
			
		||||
    faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z
 | 
			
		||||
    faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0);  // +x face
 | 
			
		||||
 | 
			
		||||
    // -y
 | 
			
		||||
    faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0);  // u -> +x
 | 
			
		||||
    faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z
 | 
			
		||||
    faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face
 | 
			
		||||
 | 
			
		||||
    // +y
 | 
			
		||||
    faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0);  // u -> +x
 | 
			
		||||
    faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0);  // v -> +z
 | 
			
		||||
    faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0);  // +y face
 | 
			
		||||
 | 
			
		||||
    // -z
 | 
			
		||||
    faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
 | 
			
		||||
    faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face
 | 
			
		||||
 | 
			
		||||
    // +z
 | 
			
		||||
    faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0);  // u -> +x
 | 
			
		||||
    faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
 | 
			
		||||
    faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0);  // +z face
 | 
			
		||||
 | 
			
		||||
    // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
 | 
			
		||||
    vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
 | 
			
		||||
    return normalize(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
 | 
			
		||||
{
 | 
			
		||||
	float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
 | 
			
		||||
 | 
			
		||||
	// Compute distribution direction
 | 
			
		||||
	float Phi = 2.0 * M_PI * Xi.x;
 | 
			
		||||
	float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
 | 
			
		||||
	float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
 | 
			
		||||
 | 
			
		||||
	// Convert to spherical direction
 | 
			
		||||
	vec3 H;
 | 
			
		||||
	H.x = SinTheta * cos(Phi);
 | 
			
		||||
	H.y = SinTheta * sin(Phi);
 | 
			
		||||
	H.z = CosTheta;
 | 
			
		||||
 | 
			
		||||
	vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
 | 
			
		||||
	vec3 TangentX = normalize(cross(UpVector, N));
 | 
			
		||||
	vec3 TangentY = cross(N, TangentX);
 | 
			
		||||
 | 
			
		||||
	// Tangent to world space
 | 
			
		||||
	return TangentX * H.x + TangentY * H.y + N * H.z;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
 | 
			
		||||
float GGX(float NdotV, float a)
 | 
			
		||||
{
 | 
			
		||||
	float k = a / 2.0;
 | 
			
		||||
	return NdotV / (NdotV * (1.0 - k) + k);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
 | 
			
		||||
float G_Smith(float a, float nDotV, float nDotL)
 | 
			
		||||
{
 | 
			
		||||
	return GGX(nDotL, a * a) * GGX(nDotV, a * a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float radicalInverse_VdC(uint bits) {
 | 
			
		||||
    bits = (bits << 16u) | (bits >> 16u);
 | 
			
		||||
    bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
 | 
			
		||||
    bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
 | 
			
		||||
    bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
 | 
			
		||||
    bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
 | 
			
		||||
    return float(bits) * 2.3283064365386963e-10; // / 0x100000000
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vec2 Hammersley(uint i, uint N) {
 | 
			
		||||
     return vec2(float(i)/float(N), radicalInverse_VdC(i));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef LOW_QUALITY
 | 
			
		||||
 | 
			
		||||
#define SAMPLE_COUNT 64u
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define SAMPLE_COUNT 512u
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform bool z_flip;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOURCE_PANORAMA
 | 
			
		||||
 | 
			
		||||
vec4 texturePanorama(vec3 normal,sampler2D pano ) {
 | 
			
		||||
 | 
			
		||||
	vec2 st = vec2(
 | 
			
		||||
		atan(normal.x, normal.z),
 | 
			
		||||
		acos(normal.y)
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	if(st.x < 0.0)
 | 
			
		||||
		st.x += M_PI*2.0;
 | 
			
		||||
 | 
			
		||||
	st/=vec2(M_PI*2.0,M_PI);
 | 
			
		||||
 | 
			
		||||
	return textureLod(pano,st,0.0);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vec4 textureDualParaboloidArray(vec3 normal) {
 | 
			
		||||
 | 
			
		||||
	vec3 norm = normalize(normal);
 | 
			
		||||
	norm.xy/=1.0+abs(norm.z);
 | 
			
		||||
	norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25);
 | 
			
		||||
	if (norm.z<0.0) {
 | 
			
		||||
		norm.y=0.5-norm.y+0.5;
 | 
			
		||||
	}
 | 
			
		||||
	return textureLod(source_dual_paraboloid_array, vec3(norm.xy, float(source_array_index) ), 0.0);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
#ifdef USE_DUAL_PARABOLOID
 | 
			
		||||
 | 
			
		||||
	vec3 N = vec3( uv_interp * 2.0 - 1.0, 0.0 );
 | 
			
		||||
	N.z = 0.5 - 0.5*((N.x * N.x) + (N.y * N.y));
 | 
			
		||||
	N = normalize(N);
 | 
			
		||||
 | 
			
		||||
	if (z_flip) {
 | 
			
		||||
		N.y=-N.y; //y is flipped to improve blending between both sides
 | 
			
		||||
		N.z=-N.z;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
	vec2 uv         = (uv_interp * 2.0) - 1.0;
 | 
			
		||||
	vec3 N          = texelCoordToVec(uv, face_id);
 | 
			
		||||
#endif
 | 
			
		||||
	//vec4 color = color_interp;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_DIRECT_WRITE
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOURCE_PANORAMA
 | 
			
		||||
 | 
			
		||||
	frag_color=vec4(texturePanorama(N,source_panorama).rgb,1.0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
 | 
			
		||||
 | 
			
		||||
	frag_color=vec4(textureDualParaboloidArray(N).rgb,1.0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
 | 
			
		||||
 | 
			
		||||
	N.y=-N.y;
 | 
			
		||||
	frag_color=vec4(texture(N,source_cube).rgb,1.0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
 | 
			
		||||
 | 
			
		||||
	for(uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) {
 | 
			
		||||
		vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT);
 | 
			
		||||
 | 
			
		||||
		vec3 H  = ImportanceSampleGGX( xi, roughness, N );
 | 
			
		||||
		vec3 V  = N;
 | 
			
		||||
		vec3 L  = normalize(2.0 * dot( V, H ) * H - V);
 | 
			
		||||
 | 
			
		||||
		float ndotl = clamp(dot(N, L),0.0,1.0);
 | 
			
		||||
 | 
			
		||||
		if (ndotl>0.0) {
 | 
			
		||||
#ifdef USE_SOURCE_PANORAMA
 | 
			
		||||
			sum.rgb += texturePanorama(H,source_panorama).rgb *ndotl;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
 | 
			
		||||
 | 
			
		||||
			sum.rgb += textureDualParaboloidArray(H).rgb *ndotl;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
 | 
			
		||||
			H.y=-H.y;
 | 
			
		||||
			sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl;
 | 
			
		||||
#endif
 | 
			
		||||
			sum.a += ndotl;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sum /= sum.a;
 | 
			
		||||
 | 
			
		||||
	frag_color = vec4(sum.rgb, 1.0);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										301
									
								
								drivers/gles2/shaders/effect_blur.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								drivers/gles2/shaders/effect_blur.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,301 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
layout(location=4) in vec2 uv_in;
 | 
			
		||||
 | 
			
		||||
out vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_BLUR_SECTION
 | 
			
		||||
 | 
			
		||||
uniform vec4 blur_section;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	uv_interp = uv_in;
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
#ifdef USE_BLUR_SECTION
 | 
			
		||||
 | 
			
		||||
	uv_interp = blur_section.xy + uv_interp * blur_section.zw;
 | 
			
		||||
	gl_Position.xy = (blur_section.xy + (gl_Position.xy * 0.5 + 0.5) * blur_section.zw) * 2.0 - 1.0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
#if !defined(GLES_OVER_GL)
 | 
			
		||||
precision mediump float;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
in vec2 uv_interp;
 | 
			
		||||
uniform sampler2D source_color; //texunit:0
 | 
			
		||||
 | 
			
		||||
#ifdef SSAO_MERGE
 | 
			
		||||
uniform sampler2D source_ssao; //texunit:1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform float lod;
 | 
			
		||||
uniform vec2 pixel_size;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 frag_color;
 | 
			
		||||
 | 
			
		||||
#ifdef SSAO_MERGE
 | 
			
		||||
 | 
			
		||||
uniform vec4 ssao_color;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined (GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL)
 | 
			
		||||
 | 
			
		||||
uniform float glow_strength;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(DOF_FAR_BLUR) || defined (DOF_NEAR_BLUR)
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_QUALITY_LOW
 | 
			
		||||
const int dof_kernel_size=5;
 | 
			
		||||
const int dof_kernel_from=2;
 | 
			
		||||
const float dof_kernel[5] = float[] (0.153388,0.221461,0.250301,0.221461,0.153388);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_QUALITY_MEDIUM
 | 
			
		||||
const int dof_kernel_size=11;
 | 
			
		||||
const int dof_kernel_from=5;
 | 
			
		||||
const float dof_kernel[11] = float[] (0.055037,0.072806,0.090506,0.105726,0.116061,0.119726,0.116061,0.105726,0.090506,0.072806,0.055037);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_QUALITY_HIGH
 | 
			
		||||
const int dof_kernel_size=21;
 | 
			
		||||
const int dof_kernel_from=10;
 | 
			
		||||
const float dof_kernel[21] = float[] (0.028174,0.032676,0.037311,0.041944,0.046421,0.050582,0.054261,0.057307,0.059587,0.060998,0.061476,0.060998,0.059587,0.057307,0.054261,0.050582,0.046421,0.041944,0.037311,0.032676,0.028174);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform sampler2D dof_source_depth; //texunit:1
 | 
			
		||||
uniform float dof_begin;
 | 
			
		||||
uniform float dof_end;
 | 
			
		||||
uniform vec2 dof_dir;
 | 
			
		||||
uniform float dof_radius;
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_NEAR_BLUR_MERGE
 | 
			
		||||
 | 
			
		||||
uniform sampler2D source_dof_original; //texunit:2
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef GLOW_FIRST_PASS
 | 
			
		||||
 | 
			
		||||
uniform float exposure;
 | 
			
		||||
uniform float white;
 | 
			
		||||
 | 
			
		||||
#ifdef GLOW_USE_AUTO_EXPOSURE
 | 
			
		||||
 | 
			
		||||
uniform highp sampler2D source_auto_exposure; //texunit:1
 | 
			
		||||
uniform highp float auto_exposure_grey;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform float glow_bloom;
 | 
			
		||||
uniform float glow_hdr_threshold;
 | 
			
		||||
uniform float glow_hdr_scale;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform float camera_z_far;
 | 
			
		||||
uniform float camera_z_near;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef GAUSSIAN_HORIZONTAL
 | 
			
		||||
	vec2 pix_size = pixel_size;
 | 
			
		||||
	pix_size*=0.5; //reading from larger buffer, so use more samples
 | 
			
		||||
	vec4 color =textureLod( source_color,  uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.214607;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.189879;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.157305;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.071303;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.189879;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.157305;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.071303;
 | 
			
		||||
	frag_color = color;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef GAUSSIAN_VERTICAL
 | 
			
		||||
	vec4 color =textureLod( source_color,  uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.38774;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 0.0, 1.0)*pixel_size,lod )*0.24477;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 0.0, 2.0)*pixel_size,lod )*0.06136;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 0.0,-1.0)*pixel_size,lod )*0.24477;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 0.0,-2.0)*pixel_size,lod )*0.06136;
 | 
			
		||||
	frag_color = color;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//glow uses larger sigma for a more rounded blur effect
 | 
			
		||||
 | 
			
		||||
#ifdef GLOW_GAUSSIAN_HORIZONTAL
 | 
			
		||||
	vec2 pix_size = pixel_size;
 | 
			
		||||
	pix_size*=0.5; //reading from larger buffer, so use more samples
 | 
			
		||||
	vec4 color =textureLod( source_color,  uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.174938;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.165569;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.140367;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.106595;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.165569;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.140367;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.106595;
 | 
			
		||||
	color*=glow_strength;
 | 
			
		||||
	frag_color = color;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef GLOW_GAUSSIAN_VERTICAL
 | 
			
		||||
	vec4 color =textureLod( source_color,  uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.288713;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.233062;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.122581;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.233062;
 | 
			
		||||
	color+=textureLod( source_color,  uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.122581;
 | 
			
		||||
	color*=glow_strength;
 | 
			
		||||
	frag_color = color;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_FAR_BLUR
 | 
			
		||||
 | 
			
		||||
	vec4 color_accum = vec4(0.0);
 | 
			
		||||
 | 
			
		||||
	float depth = textureLod( dof_source_depth, uv_interp, 0.0).r;
 | 
			
		||||
	depth = depth * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
	depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
	depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	float amount = smoothstep(dof_begin,dof_end,depth);
 | 
			
		||||
	float k_accum=0.0;
 | 
			
		||||
 | 
			
		||||
	for(int i=0;i<dof_kernel_size;i++) {
 | 
			
		||||
 | 
			
		||||
		int int_ofs = i-dof_kernel_from;
 | 
			
		||||
		vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
 | 
			
		||||
 | 
			
		||||
		float tap_k = dof_kernel[i];
 | 
			
		||||
 | 
			
		||||
		float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r;
 | 
			
		||||
		tap_depth = tap_depth * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
		tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
		tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
 | 
			
		||||
#endif
 | 
			
		||||
		float tap_amount = mix(smoothstep(dof_begin,dof_end,tap_depth),1.0,int_ofs==0);
 | 
			
		||||
		tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect
 | 
			
		||||
 | 
			
		||||
		vec4 tap_color = textureLod( source_color, tap_uv, 0.0) * tap_k;
 | 
			
		||||
 | 
			
		||||
		k_accum+=tap_k*tap_amount;
 | 
			
		||||
		color_accum+=tap_color*tap_amount;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (k_accum>0.0) {
 | 
			
		||||
		color_accum/=k_accum;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	frag_color = color_accum;///k_accum;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_NEAR_BLUR
 | 
			
		||||
 | 
			
		||||
	vec4 color_accum = vec4(0.0);
 | 
			
		||||
 | 
			
		||||
	float max_accum=0;
 | 
			
		||||
 | 
			
		||||
	for(int i=0;i<dof_kernel_size;i++) {
 | 
			
		||||
 | 
			
		||||
		int int_ofs = i-dof_kernel_from;
 | 
			
		||||
		vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius;
 | 
			
		||||
		float ofs_influence = max(0.0,1.0-float(abs(int_ofs))/float(dof_kernel_from));
 | 
			
		||||
 | 
			
		||||
		float tap_k = dof_kernel[i];
 | 
			
		||||
 | 
			
		||||
		vec4 tap_color = textureLod( source_color, tap_uv, 0.0);
 | 
			
		||||
 | 
			
		||||
		float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r;
 | 
			
		||||
		tap_depth = tap_depth * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION	
 | 
			
		||||
		tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
		tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
 | 
			
		||||
#endif
 | 
			
		||||
		float tap_amount = 1.0-smoothstep(dof_end,dof_begin,tap_depth);
 | 
			
		||||
		tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_NEAR_FIRST_TAP
 | 
			
		||||
 | 
			
		||||
		tap_color.a= 1.0-smoothstep(dof_end,dof_begin,tap_depth);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		max_accum=max(max_accum,tap_amount*ofs_influence);
 | 
			
		||||
 | 
			
		||||
		color_accum+=tap_color*tap_k;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	color_accum.a=max(color_accum.a,sqrt(max_accum));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef DOF_NEAR_BLUR_MERGE
 | 
			
		||||
 | 
			
		||||
	vec4 original = textureLod( source_dof_original, uv_interp, 0.0);
 | 
			
		||||
	color_accum = mix(original,color_accum,color_accum.a);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef DOF_NEAR_FIRST_TAP
 | 
			
		||||
	//color_accum=vec4(vec3(color_accum.a),1.0);
 | 
			
		||||
#endif
 | 
			
		||||
	frag_color = color_accum;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef GLOW_FIRST_PASS
 | 
			
		||||
 | 
			
		||||
#ifdef GLOW_USE_AUTO_EXPOSURE
 | 
			
		||||
 | 
			
		||||
	frag_color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey;
 | 
			
		||||
#endif
 | 
			
		||||
	frag_color*=exposure;
 | 
			
		||||
 | 
			
		||||
	float luminance = max(frag_color.r,max(frag_color.g,frag_color.b));
 | 
			
		||||
	float feedback = max( smoothstep(glow_hdr_threshold,glow_hdr_threshold+glow_hdr_scale,luminance), glow_bloom );
 | 
			
		||||
 | 
			
		||||
	frag_color *= feedback;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef SIMPLE_COPY
 | 
			
		||||
	vec4 color =textureLod( source_color,  uv_interp,0.0);
 | 
			
		||||
	frag_color = color;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SSAO_MERGE
 | 
			
		||||
 | 
			
		||||
	vec4 color =textureLod( source_color,  uv_interp,0.0);
 | 
			
		||||
	float ssao =textureLod( source_ssao,  uv_interp,0.0).r;
 | 
			
		||||
 | 
			
		||||
	frag_color = vec4( mix(color.rgb,color.rgb*mix(ssao_color.rgb,vec3(1.0),ssao),color.a), 1.0 );
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								drivers/gles2/shaders/exposure.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								drivers/gles2/shaders/exposure.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,98 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uniform highp sampler2D source_exposure; //texunit:0
 | 
			
		||||
 | 
			
		||||
#ifdef EXPOSURE_BEGIN
 | 
			
		||||
 | 
			
		||||
uniform highp ivec2 source_render_size;
 | 
			
		||||
uniform highp ivec2 target_size;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef EXPOSURE_END
 | 
			
		||||
 | 
			
		||||
uniform highp sampler2D prev_exposure; //texunit:1
 | 
			
		||||
uniform highp float exposure_adjust;
 | 
			
		||||
uniform highp float min_luminance;
 | 
			
		||||
uniform highp float max_luminance;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out highp float exposure;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef EXPOSURE_BEGIN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	ivec2 src_pos = ivec2(gl_FragCoord.xy)*source_render_size/target_size;
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
	//more precise and expensive, but less jittery
 | 
			
		||||
	ivec2 next_pos = ivec2(gl_FragCoord.xy+ivec2(1))*source_render_size/target_size;
 | 
			
		||||
	next_pos = max(next_pos,src_pos+ivec2(1)); //so it at least reads one pixel
 | 
			
		||||
	highp vec3 source_color=vec3(0.0);
 | 
			
		||||
	for(int i=src_pos.x;i<next_pos.x;i++) {
 | 
			
		||||
		for(int j=src_pos.y;j<next_pos.y;j++) {
 | 
			
		||||
			source_color += texelFetch(source_exposure,ivec2(i,j),0).rgb;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	source_color/=float( (next_pos.x-src_pos.x)*(next_pos.y-src_pos.y) );
 | 
			
		||||
#else
 | 
			
		||||
	highp vec3 source_color = texelFetch(source_exposure,src_pos,0).rgb;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	exposure = max(source_color.r,max(source_color.g,source_color.b));
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	ivec2 coord = ivec2(gl_FragCoord.xy);
 | 
			
		||||
	exposure  = texelFetch(source_exposure,coord*3+ivec2(0,0),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(1,0),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(2,0),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(0,1),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(1,1),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(2,1),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(0,2),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(1,2),0).r;
 | 
			
		||||
	exposure += texelFetch(source_exposure,coord*3+ivec2(2,2),0).r;
 | 
			
		||||
	exposure *= (1.0/9.0);
 | 
			
		||||
 | 
			
		||||
#ifdef EXPOSURE_END
 | 
			
		||||
 | 
			
		||||
#ifdef EXPOSURE_FORCE_SET
 | 
			
		||||
	//will stay as is
 | 
			
		||||
#else
 | 
			
		||||
	highp float prev_lum = texelFetch(prev_exposure,ivec2(0,0),0).r; //1 pixel previous exposure
 | 
			
		||||
	exposure = clamp( prev_lum + (exposure-prev_lum)*exposure_adjust,min_luminance,max_luminance);
 | 
			
		||||
 | 
			
		||||
#endif //EXPOSURE_FORCE_SET
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //EXPOSURE_END
 | 
			
		||||
 | 
			
		||||
#endif //EXPOSURE_BEGIN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										260
									
								
								drivers/gles2/shaders/particles.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								drivers/gles2/shaders/particles.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,260 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 color;
 | 
			
		||||
layout(location=1) in highp vec4 velocity_active;
 | 
			
		||||
layout(location=2) in highp vec4 custom;
 | 
			
		||||
layout(location=3) in highp vec4 xform_1;
 | 
			
		||||
layout(location=4) in highp vec4 xform_2;
 | 
			
		||||
layout(location=5) in highp vec4 xform_3;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct Attractor {
 | 
			
		||||
 | 
			
		||||
	vec3 pos;
 | 
			
		||||
	vec3 dir;
 | 
			
		||||
	float radius;
 | 
			
		||||
	float eat_radius;
 | 
			
		||||
	float strength;
 | 
			
		||||
	float attenuation;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_ATTRACTORS 64
 | 
			
		||||
 | 
			
		||||
uniform bool emitting;
 | 
			
		||||
uniform float system_phase;
 | 
			
		||||
uniform float prev_system_phase;
 | 
			
		||||
uniform int total_particles;
 | 
			
		||||
uniform float explosiveness;
 | 
			
		||||
uniform float randomness;
 | 
			
		||||
uniform float time;
 | 
			
		||||
uniform float delta;
 | 
			
		||||
 | 
			
		||||
uniform int attractor_count;
 | 
			
		||||
uniform Attractor attractors[MAX_ATTRACTORS];
 | 
			
		||||
uniform bool clear;
 | 
			
		||||
uniform uint cycle;
 | 
			
		||||
uniform float lifetime;
 | 
			
		||||
uniform mat4 emission_transform;
 | 
			
		||||
uniform uint random_seed;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
out highp vec4 out_color; //tfb:
 | 
			
		||||
out highp vec4 out_velocity_active; //tfb:
 | 
			
		||||
out highp vec4 out_custom; //tfb:
 | 
			
		||||
out highp vec4 out_xform_1; //tfb:
 | 
			
		||||
out highp vec4 out_xform_2; //tfb:
 | 
			
		||||
out highp vec4 out_xform_3; //tfb:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(USE_MATERIAL)
 | 
			
		||||
 | 
			
		||||
layout(std140) uniform UniformData { //ubo:0
 | 
			
		||||
 | 
			
		||||
MATERIAL_UNIFORMS
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
VERTEX_SHADER_GLOBALS
 | 
			
		||||
 | 
			
		||||
uint hash(uint x) {
 | 
			
		||||
 | 
			
		||||
	x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
 | 
			
		||||
	x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
 | 
			
		||||
	x = (x >> uint(16)) ^ x;
 | 
			
		||||
	return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
#ifdef PARTICLES_COPY
 | 
			
		||||
 | 
			
		||||
	out_color=color;
 | 
			
		||||
	out_velocity_active=velocity_active;
 | 
			
		||||
	out_custom = custom;
 | 
			
		||||
	out_xform_1 = xform_1;
 | 
			
		||||
	out_xform_2 = xform_2;
 | 
			
		||||
	out_xform_3 = xform_3;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	bool apply_forces=true;
 | 
			
		||||
	bool apply_velocity=true;
 | 
			
		||||
	float local_delta=delta;
 | 
			
		||||
 | 
			
		||||
	float mass = 1.0;
 | 
			
		||||
 | 
			
		||||
	float restart_phase = float(gl_VertexID)/float(total_particles);
 | 
			
		||||
 | 
			
		||||
	if (randomness>0.0) {
 | 
			
		||||
		uint seed = cycle;
 | 
			
		||||
		if (restart_phase >= system_phase) {
 | 
			
		||||
			seed-=uint(1);
 | 
			
		||||
		}
 | 
			
		||||
		seed*=uint(total_particles);
 | 
			
		||||
		seed+=uint(gl_VertexID);
 | 
			
		||||
		float random = float(hash(seed) % uint(65536)) / 65536.0;
 | 
			
		||||
		restart_phase+=randomness * random * 1.0 / float(total_particles);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	restart_phase*= (1.0-explosiveness);
 | 
			
		||||
	bool restart=false;
 | 
			
		||||
	bool shader_active = velocity_active.a > 0.5;
 | 
			
		||||
 | 
			
		||||
	if (system_phase > prev_system_phase) {
 | 
			
		||||
		// restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed
 | 
			
		||||
 | 
			
		||||
		if (restart_phase >= prev_system_phase && restart_phase < system_phase ) {
 | 
			
		||||
			restart=true;
 | 
			
		||||
#ifdef USE_FRACTIONAL_DELTA
 | 
			
		||||
			local_delta = (system_phase - restart_phase) * lifetime;
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
		if (restart_phase >= prev_system_phase) {
 | 
			
		||||
			restart=true;
 | 
			
		||||
#ifdef USE_FRACTIONAL_DELTA
 | 
			
		||||
			local_delta = (1.0 - restart_phase + system_phase) * lifetime;
 | 
			
		||||
#endif
 | 
			
		||||
		} else if (restart_phase < system_phase ) {
 | 
			
		||||
			restart=true;
 | 
			
		||||
#ifdef USE_FRACTIONAL_DELTA
 | 
			
		||||
			local_delta = (system_phase - restart_phase) * lifetime;
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint current_cycle = cycle;
 | 
			
		||||
 | 
			
		||||
	if (system_phase < restart_phase) {
 | 
			
		||||
		current_cycle-=uint(1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID);
 | 
			
		||||
	int index = int(gl_VertexID);
 | 
			
		||||
 | 
			
		||||
	if (restart) {
 | 
			
		||||
		shader_active=emitting;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mat4 xform;
 | 
			
		||||
 | 
			
		||||
#if defined(ENABLE_KEEP_DATA)
 | 
			
		||||
	if (clear) {
 | 
			
		||||
#else
 | 
			
		||||
	if (clear || restart) {
 | 
			
		||||
#endif
 | 
			
		||||
		out_color=vec4(1.0);
 | 
			
		||||
		out_velocity_active=vec4(0.0);
 | 
			
		||||
		out_custom=vec4(0.0);
 | 
			
		||||
		if (!restart)
 | 
			
		||||
			shader_active=false;
 | 
			
		||||
 | 
			
		||||
		xform = mat4(
 | 
			
		||||
				vec4(1.0,0.0,0.0,0.0),
 | 
			
		||||
				vec4(0.0,1.0,0.0,0.0),
 | 
			
		||||
				vec4(0.0,0.0,1.0,0.0),
 | 
			
		||||
				vec4(0.0,0.0,0.0,1.0)
 | 
			
		||||
			);
 | 
			
		||||
	} else {
 | 
			
		||||
		out_color=color;
 | 
			
		||||
		out_velocity_active=velocity_active;
 | 
			
		||||
		out_custom=custom;
 | 
			
		||||
		xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (shader_active) {
 | 
			
		||||
		//execute shader
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
VERTEX_SHADER_CODE
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if !defined(DISABLE_FORCE)
 | 
			
		||||
 | 
			
		||||
		if (false) {
 | 
			
		||||
 | 
			
		||||
			vec3 force = vec3(0.0);
 | 
			
		||||
			for(int i=0;i<attractor_count;i++) {
 | 
			
		||||
 | 
			
		||||
				vec3 rel_vec = xform[3].xyz - attractors[i].pos;
 | 
			
		||||
				float dist = length(rel_vec);
 | 
			
		||||
				if (attractors[i].radius < dist)
 | 
			
		||||
					continue;
 | 
			
		||||
				if (attractors[i].eat_radius>0.0 &&  attractors[i].eat_radius > dist) {
 | 
			
		||||
					out_velocity_active.a=0.0;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				rel_vec = normalize(rel_vec);
 | 
			
		||||
 | 
			
		||||
				float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation);
 | 
			
		||||
 | 
			
		||||
				if (attractors[i].dir==vec3(0.0)) {
 | 
			
		||||
					//towards center
 | 
			
		||||
					force+=attractors[i].strength * rel_vec * attenuation * mass;
 | 
			
		||||
				} else {
 | 
			
		||||
					force+=attractors[i].strength * attractors[i].dir * attenuation *mass;
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			out_velocity_active.xyz += force * local_delta;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(DISABLE_VELOCITY)
 | 
			
		||||
 | 
			
		||||
		if (true) {
 | 
			
		||||
 | 
			
		||||
			xform[3].xyz += out_velocity_active.xyz * local_delta;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
	} else {
 | 
			
		||||
		xform=mat4(0.0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xform = transpose(xform);
 | 
			
		||||
 | 
			
		||||
	out_velocity_active.a = mix(0.0,1.0,shader_active);
 | 
			
		||||
 | 
			
		||||
	out_xform_1 = xform[0];
 | 
			
		||||
	out_xform_2 = xform[1];
 | 
			
		||||
	out_xform_3 = xform[2];
 | 
			
		||||
 | 
			
		||||
#endif //PARTICLES_COPY
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
//any code here is never executed, stuff is filled just so it works
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(USE_MATERIAL)
 | 
			
		||||
 | 
			
		||||
layout(std140) uniform UniformData {
 | 
			
		||||
 | 
			
		||||
MATERIAL_UNIFORMS
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
FRAGMENT_SHADER_GLOBALS
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
LIGHT_SHADER_CODE
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
FRAGMENT_SHADER_CODE
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								drivers/gles2/shaders/resolve.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								drivers/gles2/shaders/resolve.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
layout(location=4) in vec2 uv_in;
 | 
			
		||||
 | 
			
		||||
out vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	uv_interp = uv_in;
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
#if !defined(GLES_OVER_GL)
 | 
			
		||||
precision mediump float;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
in vec2 uv_interp;
 | 
			
		||||
uniform sampler2D source_specular; //texunit:0
 | 
			
		||||
uniform sampler2D source_ssr; //texunit:1
 | 
			
		||||
 | 
			
		||||
uniform vec2 pixel_size;
 | 
			
		||||
 | 
			
		||||
in vec2 uv2_interp;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 frag_color;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	vec4 specular = texture( source_specular,  uv_interp );
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SSR
 | 
			
		||||
 | 
			
		||||
	vec4 ssr = textureLod(source_ssr,uv_interp,0.0);
 | 
			
		||||
	specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	frag_color = vec4(specular.rgb,1.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2113
									
								
								drivers/gles2/shaders/scene.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2113
									
								
								drivers/gles2/shaders/scene.glsl
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										318
									
								
								drivers/gles2/shaders/screen_space_reflection.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								drivers/gles2/shaders/screen_space_reflection.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,318 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
layout(location=4) in vec2 uv_in;
 | 
			
		||||
 | 
			
		||||
out vec2 uv_interp;
 | 
			
		||||
out vec2 pos_interp;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	uv_interp = uv_in;
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
	pos_interp.xy=gl_Position.xy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
in vec2 uv_interp;
 | 
			
		||||
in vec2 pos_interp;
 | 
			
		||||
 | 
			
		||||
uniform sampler2D source_diffuse; //texunit:0
 | 
			
		||||
uniform sampler2D source_normal_roughness; //texunit:1
 | 
			
		||||
uniform sampler2D source_depth; //texunit:2
 | 
			
		||||
 | 
			
		||||
uniform float camera_z_near;
 | 
			
		||||
uniform float camera_z_far;
 | 
			
		||||
 | 
			
		||||
uniform vec2 viewport_size;
 | 
			
		||||
uniform vec2 pixel_size;
 | 
			
		||||
 | 
			
		||||
uniform float filter_mipmap_levels;
 | 
			
		||||
 | 
			
		||||
uniform mat4 inverse_projection;
 | 
			
		||||
uniform mat4 projection;
 | 
			
		||||
 | 
			
		||||
uniform int num_steps;
 | 
			
		||||
uniform float depth_tolerance;
 | 
			
		||||
uniform float distance_fade;
 | 
			
		||||
uniform float curve_fade_in;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 frag_color;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vec2 view_to_screen(vec3 view_pos,out float w) {
 | 
			
		||||
    vec4 projected = projection * vec4(view_pos, 1.0);
 | 
			
		||||
    projected.xyz /= projected.w;
 | 
			
		||||
    projected.xy = projected.xy * 0.5 + 0.5;
 | 
			
		||||
    w=projected.w;
 | 
			
		||||
    return projected.xy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define M_PI 3.14159265359
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	////
 | 
			
		||||
 | 
			
		||||
	vec4 diffuse = texture( source_diffuse,  uv_interp );
 | 
			
		||||
	vec4 normal_roughness = texture( source_normal_roughness, uv_interp);
 | 
			
		||||
 | 
			
		||||
	vec3 normal;
 | 
			
		||||
 | 
			
		||||
	normal = normal_roughness.xyz*2.0-1.0;
 | 
			
		||||
 | 
			
		||||
	float roughness = normal_roughness.w;
 | 
			
		||||
 | 
			
		||||
	float depth_tex = texture(source_depth,uv_interp).r;
 | 
			
		||||
 | 
			
		||||
	vec4 world_pos = inverse_projection * vec4( uv_interp*2.0-1.0, depth_tex*2.0-1.0, 1.0 );
 | 
			
		||||
	vec3 vertex = world_pos.xyz/world_pos.w;
 | 
			
		||||
 | 
			
		||||
	vec3 view_dir = normalize(vertex);
 | 
			
		||||
	vec3 ray_dir = normalize(reflect(view_dir, normal));
 | 
			
		||||
 | 
			
		||||
	if (dot(ray_dir,normal)<0.001) {
 | 
			
		||||
		frag_color=vec4(0.0);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	//ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0);
 | 
			
		||||
 | 
			
		||||
	//ray_dir = normalize(vec3(1,1,-1));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	//make ray length and clip it against the near plane (don't want to trace beyond visible)
 | 
			
		||||
	float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far;
 | 
			
		||||
	vec3 ray_end = vertex + ray_dir*ray_len;
 | 
			
		||||
 | 
			
		||||
	float w_begin;
 | 
			
		||||
	vec2 vp_line_begin = view_to_screen(vertex,w_begin);
 | 
			
		||||
	float w_end;
 | 
			
		||||
	vec2 vp_line_end = view_to_screen( ray_end, w_end);
 | 
			
		||||
	vec2 vp_line_dir = vp_line_end-vp_line_begin;
 | 
			
		||||
 | 
			
		||||
	//we need to interpolate w along the ray, to generate perspective correct reflections
 | 
			
		||||
 | 
			
		||||
	w_begin = 1.0/w_begin;
 | 
			
		||||
	w_end = 1.0/w_end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	float z_begin = vertex.z*w_begin;
 | 
			
		||||
	float z_end = ray_end.z*w_end;
 | 
			
		||||
 | 
			
		||||
	vec2 line_begin = vp_line_begin/pixel_size;
 | 
			
		||||
	vec2 line_dir = vp_line_dir/pixel_size;
 | 
			
		||||
	float z_dir = z_end - z_begin;
 | 
			
		||||
	float w_dir = w_end - w_begin;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// clip the line to the viewport edges
 | 
			
		||||
 | 
			
		||||
	float scale_max_x = min(1.0, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x));
 | 
			
		||||
	float scale_max_y = min(1.0, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y));
 | 
			
		||||
	float scale_min_x = min(1.0, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x));
 | 
			
		||||
	float scale_min_y = min(1.0, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y));
 | 
			
		||||
	float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y);
 | 
			
		||||
	line_dir *= line_clip;
 | 
			
		||||
	z_dir *= line_clip;
 | 
			
		||||
	w_dir *=line_clip;
 | 
			
		||||
 | 
			
		||||
	//clip z and w advance to line advance
 | 
			
		||||
	vec2 line_advance = normalize(line_dir); //down to pixel
 | 
			
		||||
	float step_size = length(line_advance)/length(line_dir);
 | 
			
		||||
	float z_advance = z_dir*step_size; // adapt z advance to line advance
 | 
			
		||||
	float w_advance = w_dir*step_size; // adapt w advance to line advance
 | 
			
		||||
 | 
			
		||||
	//make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice)
 | 
			
		||||
	float advance_angle_adj = 1.0/max(abs(line_advance.x),abs(line_advance.y));
 | 
			
		||||
	line_advance*=advance_angle_adj; // adapt z advance to line advance
 | 
			
		||||
	z_advance*=advance_angle_adj;
 | 
			
		||||
	w_advance*=advance_angle_adj;
 | 
			
		||||
 | 
			
		||||
	vec2 pos = line_begin;
 | 
			
		||||
	float z = z_begin;
 | 
			
		||||
	float w = w_begin;
 | 
			
		||||
	float z_from=z/w;
 | 
			
		||||
	float z_to=z_from;
 | 
			
		||||
	float depth;
 | 
			
		||||
	vec2 prev_pos=pos;
 | 
			
		||||
 | 
			
		||||
	bool found=false;
 | 
			
		||||
 | 
			
		||||
	float steps_taken=0.0;
 | 
			
		||||
 | 
			
		||||
	for(int i=0;i<num_steps;i++) {
 | 
			
		||||
 | 
			
		||||
		pos+=line_advance;
 | 
			
		||||
		z+=z_advance;
 | 
			
		||||
		w+=w_advance;
 | 
			
		||||
 | 
			
		||||
		//convert to linear depth
 | 
			
		||||
 | 
			
		||||
		depth = texture(source_depth, pos*pixel_size).r * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
		depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
		depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
 | 
			
		||||
#endif
 | 
			
		||||
		depth=-depth;
 | 
			
		||||
 | 
			
		||||
		z_from = z_to;
 | 
			
		||||
		z_to = z/w;
 | 
			
		||||
 | 
			
		||||
		if (depth>z_to) {
 | 
			
		||||
			//if depth was surpassed
 | 
			
		||||
			if (depth<=max(z_to,z_from)+depth_tolerance) {
 | 
			
		||||
				//check the depth tolerance
 | 
			
		||||
				found=true;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		steps_taken+=1.0;
 | 
			
		||||
		prev_pos=pos;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (found) {
 | 
			
		||||
 | 
			
		||||
		float margin_blend=1.0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		vec2 margin = vec2((viewport_size.x+viewport_size.y)*0.5*0.05); //make a uniform margin
 | 
			
		||||
		if (any(bvec4(lessThan(pos,-margin),greaterThan(pos,viewport_size+margin)))) {
 | 
			
		||||
			//clip outside screen + margin
 | 
			
		||||
			frag_color=vec4(0.0);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			//blend fading out towards external margin
 | 
			
		||||
			vec2 margin_grad = mix(pos-viewport_size,-pos,lessThan(pos,vec2(0.0)));
 | 
			
		||||
			margin_blend = 1.0-smoothstep(0.0,margin.x,max(margin_grad.x,margin_grad.y));
 | 
			
		||||
			//margin_blend=1.0;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vec2 final_pos;
 | 
			
		||||
		float grad;
 | 
			
		||||
		grad=steps_taken/float(num_steps);
 | 
			
		||||
		float initial_fade = curve_fade_in==0.0 ? 1.0 : pow(clamp(grad,0.0,1.0),curve_fade_in);
 | 
			
		||||
		float fade = pow(clamp(1.0-grad,0.0,1.0),distance_fade)*initial_fade;
 | 
			
		||||
		final_pos=pos;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef REFLECT_ROUGHNESS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		vec4 final_color;
 | 
			
		||||
		//if roughness is enabled, do screen space cone tracing
 | 
			
		||||
		if (roughness > 0.001) {
 | 
			
		||||
			///////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
			//use a blurred version (in consecutive mipmaps) of the screen to simulate roughness
 | 
			
		||||
 | 
			
		||||
			float gloss = 1.0-roughness;
 | 
			
		||||
			float cone_angle = roughness * M_PI * 0.5;
 | 
			
		||||
			vec2 cone_dir = final_pos - line_begin;
 | 
			
		||||
			float cone_len = length(cone_dir);
 | 
			
		||||
			cone_dir = normalize(cone_dir); //will be used normalized from now on
 | 
			
		||||
			float max_mipmap = filter_mipmap_levels - 1.0;
 | 
			
		||||
			float gloss_mult=gloss;
 | 
			
		||||
 | 
			
		||||
			float rem_alpha=1.0;
 | 
			
		||||
			final_color = vec4(0.0);
 | 
			
		||||
 | 
			
		||||
			for(int i=0;i<7;i++) {
 | 
			
		||||
 | 
			
		||||
				float op_len = 2.0 * tan(cone_angle) * cone_len; //opposite side of iso triangle
 | 
			
		||||
				float radius;
 | 
			
		||||
				{
 | 
			
		||||
					//fit to sphere inside cone (sphere ends at end of cone), something like this:
 | 
			
		||||
					// ___
 | 
			
		||||
					// \O/
 | 
			
		||||
					//  V
 | 
			
		||||
					//
 | 
			
		||||
					// as it avoids bleeding from beyond the reflection as much as possible. As a plus
 | 
			
		||||
					// it also makes the rough reflection more elongated.
 | 
			
		||||
					float a = op_len;
 | 
			
		||||
					float h = cone_len;
 | 
			
		||||
					float a2 = a * a;
 | 
			
		||||
					float fh2 = 4.0f * h * h;
 | 
			
		||||
					radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				//find the place where screen must be sampled
 | 
			
		||||
				vec2 sample_pos = ( line_begin + cone_dir * (cone_len - radius) ) * pixel_size;
 | 
			
		||||
				//radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels
 | 
			
		||||
				float mipmap = clamp( log2( radius ), 0.0, max_mipmap );
 | 
			
		||||
 | 
			
		||||
				//mipmap = max(mipmap-1.0,0.0);
 | 
			
		||||
				//do sampling
 | 
			
		||||
 | 
			
		||||
				vec4 sample_color;
 | 
			
		||||
				{
 | 
			
		||||
					sample_color = textureLod(source_diffuse,sample_pos,mipmap);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				//multiply by gloss
 | 
			
		||||
				sample_color.rgb*=gloss_mult;
 | 
			
		||||
				sample_color.a=gloss_mult;
 | 
			
		||||
 | 
			
		||||
				rem_alpha -= sample_color.a;
 | 
			
		||||
				if(rem_alpha < 0.0) {
 | 
			
		||||
					sample_color.rgb *= (1.0 - abs(rem_alpha));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				final_color+=sample_color;
 | 
			
		||||
 | 
			
		||||
				if (final_color.a>=0.95) {
 | 
			
		||||
					// This code of accumulating gloss and aborting on near one
 | 
			
		||||
					// makes sense when you think of cone tracing.
 | 
			
		||||
					// Think of it as if roughness was 0, then we could abort on the first
 | 
			
		||||
					// iteration. For lesser roughness values, we need more iterations, but
 | 
			
		||||
					// each needs to have less influence given the sphere is smaller
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				cone_len-=radius*2.0; //go to next (smaller) circle.
 | 
			
		||||
 | 
			
		||||
				gloss_mult*=gloss;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			final_color = textureLod(source_diffuse,final_pos*pixel_size,0.0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		frag_color = vec4(final_color.rgb,fade*margin_blend);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
		frag_color = vec4(textureLod(source_diffuse,final_pos*pixel_size,0.0).rgb,fade*margin_blend);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
		frag_color = vec4(0.0,0.0,0.0,0.0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										293
									
								
								drivers/gles2/shaders/ssao.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								drivers/gles2/shaders/ssao.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,293 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
	gl_Position.z=1.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
#define TWO_PI 6.283185307179586476925286766559
 | 
			
		||||
 | 
			
		||||
#ifdef SSAO_QUALITY_HIGH
 | 
			
		||||
 | 
			
		||||
#define NUM_SAMPLES (80)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SSAO_QUALITY_LOW
 | 
			
		||||
 | 
			
		||||
#define NUM_SAMPLES (15)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH)
 | 
			
		||||
 | 
			
		||||
#define NUM_SAMPLES (40)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower
 | 
			
		||||
// miplevel to maintain reasonable spatial locality in the cache
 | 
			
		||||
// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.
 | 
			
		||||
// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively
 | 
			
		||||
#define LOG_MAX_OFFSET (3)
 | 
			
		||||
 | 
			
		||||
// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp
 | 
			
		||||
#define MAX_MIP_LEVEL (4)
 | 
			
		||||
 | 
			
		||||
// This is the number of turns around the circle that the spiral pattern makes.  This should be prime to prevent
 | 
			
		||||
// taps from lining up.  This particular choice was tuned for NUM_SAMPLES == 9
 | 
			
		||||
 | 
			
		||||
const int ROTATIONS[] = int[]( 1, 1, 2, 3, 2, 5, 2, 3, 2,
 | 
			
		||||
3, 3, 5, 5, 3, 4, 7, 5, 5, 7,
 | 
			
		||||
9, 8, 5, 5, 7, 7, 7, 8, 5, 8,
 | 
			
		||||
11, 12, 7, 10, 13, 8, 11, 8, 7, 14,
 | 
			
		||||
11, 11, 13, 12, 13, 19, 17, 13, 11, 18,
 | 
			
		||||
19, 11, 11, 14, 17, 21, 15, 16, 17, 18,
 | 
			
		||||
13, 17, 11, 17, 19, 18, 25, 18, 19, 19,
 | 
			
		||||
29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
 | 
			
		||||
31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
 | 
			
		||||
19, 27, 21, 25, 39, 29, 17, 21, 27 );
 | 
			
		||||
 | 
			
		||||
//#define NUM_SPIRAL_TURNS (7)
 | 
			
		||||
const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES-1];
 | 
			
		||||
 | 
			
		||||
uniform sampler2D source_depth; //texunit:0
 | 
			
		||||
uniform highp usampler2D source_depth_mipmaps; //texunit:1
 | 
			
		||||
uniform sampler2D source_normal; //texunit:2
 | 
			
		||||
 | 
			
		||||
uniform ivec2 screen_size;
 | 
			
		||||
uniform float camera_z_far;
 | 
			
		||||
uniform float camera_z_near;
 | 
			
		||||
 | 
			
		||||
uniform float intensity_div_r6;
 | 
			
		||||
uniform float radius;
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_RADIUS2
 | 
			
		||||
uniform float intensity_div_r62;
 | 
			
		||||
uniform float radius2;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform float bias;
 | 
			
		||||
uniform float proj_scale;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out float visibility;
 | 
			
		||||
 | 
			
		||||
uniform vec4 proj_info;
 | 
			
		||||
 | 
			
		||||
vec3 reconstructCSPosition(vec2 S, float z) {
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
	return vec3((S.xy * proj_info.xy + proj_info.zw), z);
 | 
			
		||||
#else
 | 
			
		||||
	return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vec3 getPosition(ivec2 ssP) {
 | 
			
		||||
    vec3 P;
 | 
			
		||||
    P.z = texelFetch(source_depth, ssP, 0).r;
 | 
			
		||||
 | 
			
		||||
    P.z = P.z * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
    P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
    P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
 | 
			
		||||
#endif
 | 
			
		||||
    P.z = -P.z;
 | 
			
		||||
 | 
			
		||||
    // Offset to pixel center
 | 
			
		||||
    P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
 | 
			
		||||
    return P;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Reconstructs screen-space unit normal from screen-space position */
 | 
			
		||||
vec3 reconstructCSFaceNormal(vec3 C) {
 | 
			
		||||
    return normalize(cross(dFdy(C), dFdx(C)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */
 | 
			
		||||
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){
 | 
			
		||||
    // Radius relative to ssR
 | 
			
		||||
    float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES));
 | 
			
		||||
    float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle;
 | 
			
		||||
 | 
			
		||||
    ssR = alpha;
 | 
			
		||||
    return vec2(cos(angle), sin(angle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR.  Assumes length(unitOffset) == 1 */
 | 
			
		||||
vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) {
 | 
			
		||||
    // Derivation:
 | 
			
		||||
    //  mipLevel = floor(log(ssR / MAX_OFFSET));
 | 
			
		||||
	int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
 | 
			
		||||
 | 
			
		||||
	ivec2 ssP = ivec2(ssR * unitOffset) + ssC;
 | 
			
		||||
 | 
			
		||||
	vec3 P;
 | 
			
		||||
 | 
			
		||||
	// We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.
 | 
			
		||||
	// Manually clamp to the texture size because texelFetch bypasses the texture unit
 | 
			
		||||
	ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (mipLevel < 1) {
 | 
			
		||||
		//read from depth buffer
 | 
			
		||||
		P.z = texelFetch(source_depth, mipP, 0).r;
 | 
			
		||||
		P.z = P.z * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
		P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
		P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		P.z = -P.z;
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
		//read from mipmaps
 | 
			
		||||
		uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel-1).r;
 | 
			
		||||
		P.z = -(float(d)/65535.0)*camera_z_far;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Offset to pixel center
 | 
			
		||||
	P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
 | 
			
		||||
 | 
			
		||||
	return P;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds
 | 
			
		||||
    to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius
 | 
			
		||||
 | 
			
		||||
    Note that units of H() in the HPG12 paper are meters, not
 | 
			
		||||
    unitless.  The whole falloff/sampling function is therefore
 | 
			
		||||
    unitless.  In this implementation, we factor out (9 / radius).
 | 
			
		||||
 | 
			
		||||
    Four versions of the falloff function are implemented below
 | 
			
		||||
*/
 | 
			
		||||
float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius,in float p_radius, in int tapIndex, in float randomPatternRotationAngle) {
 | 
			
		||||
    // Offset on the unit disk, spun for this pixel
 | 
			
		||||
    float ssR;
 | 
			
		||||
    vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
 | 
			
		||||
    ssR *= ssDiskRadius;
 | 
			
		||||
 | 
			
		||||
    // The occluding point in camera space
 | 
			
		||||
    vec3 Q = getOffsetPosition(ssC, unitOffset, ssR);
 | 
			
		||||
 | 
			
		||||
    vec3 v = Q - C;
 | 
			
		||||
 | 
			
		||||
    float vv = dot(v, v);
 | 
			
		||||
    float vn = dot(v, n_C);
 | 
			
		||||
 | 
			
		||||
    const float epsilon = 0.01;
 | 
			
		||||
    float radius2 = p_radius*p_radius;
 | 
			
		||||
 | 
			
		||||
    // A: From the HPG12 paper
 | 
			
		||||
    // Note large epsilon to avoid overdarkening within cracks
 | 
			
		||||
    //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6;
 | 
			
		||||
 | 
			
		||||
    // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
 | 
			
		||||
    float f=max(radius2 - vv, 0.0);
 | 
			
		||||
    return f * f * f * max((vn - bias) / (epsilon + vv), 0.0);
 | 
			
		||||
 | 
			
		||||
    // C: Medium contrast (which looks better at high radii), no division.  Note that the
 | 
			
		||||
    // contribution still falls off with radius^2, but we've adjusted the rate in a way that is
 | 
			
		||||
    // more computationally efficient and happens to be aesthetically pleasing.
 | 
			
		||||
    // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0);
 | 
			
		||||
 | 
			
		||||
    // D: Low contrast, no division operation
 | 
			
		||||
    // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Pixel being shaded
 | 
			
		||||
	ivec2 ssC = ivec2(gl_FragCoord.xy);
 | 
			
		||||
 | 
			
		||||
	// World space point being shaded
 | 
			
		||||
	vec3 C = getPosition(ssC);
 | 
			
		||||
 | 
			
		||||
/*	if (C.z <= -camera_z_far*0.999) {
 | 
			
		||||
	       // We're on the skybox
 | 
			
		||||
	       visibility=1.0;
 | 
			
		||||
	       return;
 | 
			
		||||
	}*/
 | 
			
		||||
 | 
			
		||||
	//visibility=-C.z/camera_z_far;
 | 
			
		||||
	//return;
 | 
			
		||||
#if 0
 | 
			
		||||
	vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
 | 
			
		||||
#else
 | 
			
		||||
	vec3 n_C = reconstructCSFaceNormal(C);
 | 
			
		||||
	n_C = -n_C;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	// Hash function used in the HPG12 AlchemyAO paper
 | 
			
		||||
	float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI);
 | 
			
		||||
 | 
			
		||||
	// Reconstruct normals from positions. These will lead to 1-pixel black lines
 | 
			
		||||
	// at depth discontinuities, however the blur will wipe those out so they are not visible
 | 
			
		||||
	// in the final image.
 | 
			
		||||
 | 
			
		||||
	// Choose the screen-space sample radius
 | 
			
		||||
	// proportional to the projected area of the sphere
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
	float ssDiskRadius = -proj_scale * radius;
 | 
			
		||||
#else
 | 
			
		||||
	float ssDiskRadius = -proj_scale * radius / C.z;
 | 
			
		||||
#endif
 | 
			
		||||
	float sum = 0.0;
 | 
			
		||||
	for (int i = 0; i < NUM_SAMPLES; ++i) {
 | 
			
		||||
		sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / float(NUM_SAMPLES)));
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_RADIUS2
 | 
			
		||||
 | 
			
		||||
	//go again for radius2
 | 
			
		||||
	randomPatternRotationAngle = mod(float((5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11), TWO_PI);
 | 
			
		||||
 | 
			
		||||
	// Reconstruct normals from positions. These will lead to 1-pixel black lines
 | 
			
		||||
	// at depth discontinuities, however the blur will wipe those out so they are not visible
 | 
			
		||||
	// in the final image.
 | 
			
		||||
 | 
			
		||||
	// Choose the screen-space sample radius
 | 
			
		||||
	// proportional to the projected area of the sphere
 | 
			
		||||
	ssDiskRadius = -proj_scale * radius2 / C.z;
 | 
			
		||||
 | 
			
		||||
	sum = 0.0;
 | 
			
		||||
	for (int i = 0; i < NUM_SAMPLES; ++i) {
 | 
			
		||||
		sum += sampleAO(ssC, C, n_C, ssDiskRadius,radius2, i, randomPatternRotationAngle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES))));
 | 
			
		||||
#endif
 | 
			
		||||
	// Bilateral box-filter over a quad for free, respecting depth edges
 | 
			
		||||
	// (the difference that this makes is subtle)
 | 
			
		||||
	if (abs(dFdx(C.z)) < 0.02) {
 | 
			
		||||
		A -= dFdx(A) * (float(ssC.x & 1) - 0.5);
 | 
			
		||||
	}
 | 
			
		||||
	if (abs(dFdy(C.z)) < 0.02) {
 | 
			
		||||
		A -= dFdy(A) * (float(ssC.y & 1) - 0.5);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	visibility = A;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										124
									
								
								drivers/gles2/shaders/ssao_blur.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								drivers/gles2/shaders/ssao_blur.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
	gl_Position.z=1.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uniform sampler2D source_ssao; //texunit:0
 | 
			
		||||
uniform sampler2D source_depth; //texunit:1
 | 
			
		||||
uniform sampler2D source_normal; //texunit:3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out float visibility;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Tunable Parameters:
 | 
			
		||||
 | 
			
		||||
/** Increase to make depth edges crisper. Decrease to reduce flicker. */
 | 
			
		||||
uniform float edge_sharpness;
 | 
			
		||||
 | 
			
		||||
/** Step in 2-pixel intervals since we already blurred against neighbors in the
 | 
			
		||||
    first AO pass.  This constant can be increased while R decreases to improve
 | 
			
		||||
    performance at the expense of some dithering artifacts.
 | 
			
		||||
 | 
			
		||||
    Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was
 | 
			
		||||
    unobjectionable after shading was applied but eliminated most temporal incoherence
 | 
			
		||||
    from using small numbers of sample taps.
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
uniform int filter_scale;
 | 
			
		||||
 | 
			
		||||
/** Filter radius in pixels. This will be multiplied by SCALE. */
 | 
			
		||||
#define R                   (4)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Gaussian coefficients
 | 
			
		||||
const float gaussian[R + 1] =
 | 
			
		||||
//    float[](0.356642, 0.239400, 0.072410, 0.009869);
 | 
			
		||||
//    float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134);  // stddev = 1.0
 | 
			
		||||
    float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970);  // stddev = 2.0
 | 
			
		||||
//      float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
 | 
			
		||||
 | 
			
		||||
/** (1, 0) or (0, 1)*/
 | 
			
		||||
uniform ivec2       axis;
 | 
			
		||||
 | 
			
		||||
uniform float camera_z_far;
 | 
			
		||||
uniform float camera_z_near;
 | 
			
		||||
 | 
			
		||||
uniform ivec2 screen_size;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	ivec2 ssC = ivec2(gl_FragCoord.xy);
 | 
			
		||||
 | 
			
		||||
	float depth = texelFetch(source_depth, ssC, 0).r;
 | 
			
		||||
	//vec3 normal = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
 | 
			
		||||
 | 
			
		||||
	depth = depth * 2.0 - 1.0;
 | 
			
		||||
	depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
 | 
			
		||||
 | 
			
		||||
	float depth_divide = 1.0 / camera_z_far;
 | 
			
		||||
 | 
			
		||||
//	depth*=depth_divide;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	if (depth > camera_z_far*0.999) {
 | 
			
		||||
		discard;//skybox
 | 
			
		||||
	}
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	float sum = texelFetch(source_ssao, ssC, 0).r;
 | 
			
		||||
 | 
			
		||||
	// Base weight for depth falloff.  Increase this for more blurriness,
 | 
			
		||||
	// decrease it for better edge discrimination
 | 
			
		||||
	float BASE = gaussian[0];
 | 
			
		||||
	float totalWeight = BASE;
 | 
			
		||||
	sum *= totalWeight;
 | 
			
		||||
 | 
			
		||||
	ivec2 clamp_limit = screen_size - ivec2(1);
 | 
			
		||||
 | 
			
		||||
	for (int r = -R; r <= R; ++r) {
 | 
			
		||||
		// We already handled the zero case above.  This loop should be unrolled and the static branch optimized out,
 | 
			
		||||
		// so the IF statement has no runtime cost
 | 
			
		||||
		if (r != 0) {
 | 
			
		||||
 | 
			
		||||
			ivec2 ppos = ssC + axis * (r * filter_scale);
 | 
			
		||||
			float value = texelFetch(source_ssao, clamp(ppos,ivec2(0),clamp_limit), 0).r;
 | 
			
		||||
			ivec2 rpos = clamp(ppos,ivec2(0),clamp_limit);
 | 
			
		||||
			float temp_depth = texelFetch(source_depth, rpos, 0).r;
 | 
			
		||||
			//vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0;
 | 
			
		||||
 | 
			
		||||
			temp_depth = temp_depth * 2.0 - 1.0;
 | 
			
		||||
			temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near));
 | 
			
		||||
//			temp_depth *= depth_divide;
 | 
			
		||||
 | 
			
		||||
			// spatial domain: offset gaussian tap
 | 
			
		||||
			float weight = 0.3 + gaussian[abs(r)];
 | 
			
		||||
			//weight *= max(0.0,dot(temp_normal,normal));
 | 
			
		||||
 | 
			
		||||
			// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
 | 
			
		||||
			weight *= max(0.0, 1.0
 | 
			
		||||
				      - edge_sharpness * abs(temp_depth - depth)
 | 
			
		||||
				      );
 | 
			
		||||
 | 
			
		||||
			sum += value * weight;
 | 
			
		||||
			totalWeight += weight;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const float epsilon = 0.0001;
 | 
			
		||||
	visibility = sum / (totalWeight + epsilon);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								drivers/gles2/shaders/ssao_minify.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								drivers/gles2/shaders/ssao_minify.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef MINIFY_START
 | 
			
		||||
 | 
			
		||||
#define SDEPTH_TYPE highp sampler2D
 | 
			
		||||
uniform float camera_z_far;
 | 
			
		||||
uniform float camera_z_near;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define SDEPTH_TYPE mediump usampler2D
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uniform SDEPTH_TYPE source_depth; //texunit:0
 | 
			
		||||
 | 
			
		||||
uniform ivec2 from_size;
 | 
			
		||||
uniform int source_mipmap;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out mediump uint depth;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	ivec2 ssP = ivec2(gl_FragCoord.xy);
 | 
			
		||||
 | 
			
		||||
	  // Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling.
 | 
			
		||||
	  // On DX9, the bit-and can be implemented with floating-point modulo
 | 
			
		||||
 | 
			
		||||
#ifdef MINIFY_START
 | 
			
		||||
	float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
 | 
			
		||||
	fdepth = fdepth * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
	fdepth = ((fdepth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
	fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near));
 | 
			
		||||
#endif
 | 
			
		||||
	fdepth /= camera_z_far;
 | 
			
		||||
	depth = uint(clamp(fdepth*65535.0,0.0,65535.0));
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
	depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										192
									
								
								drivers/gles2/shaders/subsurf_scattering.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								drivers/gles2/shaders/subsurf_scattering.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,192 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
layout(location=4) in vec2 uv_in;
 | 
			
		||||
 | 
			
		||||
out vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	uv_interp = uv_in;
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
//#define QUALIFIER uniform // some guy on the interweb says it may be faster with this
 | 
			
		||||
#define QUALIFIER const
 | 
			
		||||
 | 
			
		||||
#ifdef USE_25_SAMPLES
 | 
			
		||||
 | 
			
		||||
const int kernel_size=25;
 | 
			
		||||
QUALIFIER vec2 kernel[25] = vec2[] (
 | 
			
		||||
    vec2(0.530605, 0.0),
 | 
			
		||||
    vec2(0.000973794, -3.0),
 | 
			
		||||
    vec2(0.00333804, -2.52083),
 | 
			
		||||
    vec2(0.00500364, -2.08333),
 | 
			
		||||
    vec2(0.00700976,  -1.6875),
 | 
			
		||||
    vec2(0.0094389, -1.33333),
 | 
			
		||||
    vec2(0.0128496,  -1.02083),
 | 
			
		||||
    vec2(0.017924,  -0.75),
 | 
			
		||||
    vec2(0.0263642,  -0.520833),
 | 
			
		||||
    vec2(0.0410172, -0.333333),
 | 
			
		||||
    vec2(0.0493588, -0.1875),
 | 
			
		||||
    vec2(0.0402784, -0.0833333),
 | 
			
		||||
    vec2(0.0211412,  -0.0208333),
 | 
			
		||||
    vec2(0.0211412,  0.0208333),
 | 
			
		||||
    vec2(0.0402784,  0.0833333),
 | 
			
		||||
    vec2(0.0493588,  0.1875),
 | 
			
		||||
    vec2(0.0410172,  0.333333),
 | 
			
		||||
    vec2(0.0263642,  0.520833),
 | 
			
		||||
    vec2(0.017924,  0.75),
 | 
			
		||||
    vec2(0.0128496, 1.02083),
 | 
			
		||||
    vec2(0.0094389,  1.33333),
 | 
			
		||||
    vec2(0.00700976,  1.6875),
 | 
			
		||||
    vec2(0.00500364,  2.08333),
 | 
			
		||||
    vec2(0.00333804,  2.52083),
 | 
			
		||||
    vec2(0.000973794,  3.0)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
#endif //USE_25_SAMPLES
 | 
			
		||||
 | 
			
		||||
#ifdef USE_17_SAMPLES
 | 
			
		||||
 | 
			
		||||
const int kernel_size=17;
 | 
			
		||||
 | 
			
		||||
QUALIFIER vec2 kernel[17] = vec2[](
 | 
			
		||||
    vec2(0.536343,  0.0),
 | 
			
		||||
    vec2(0.00317394,  -2.0),
 | 
			
		||||
    vec2(0.0100386, -1.53125),
 | 
			
		||||
    vec2(0.0144609, -1.125),
 | 
			
		||||
    vec2(0.0216301,  -0.78125),
 | 
			
		||||
    vec2(0.0347317, -0.5),
 | 
			
		||||
    vec2(0.0571056,  -0.28125),
 | 
			
		||||
    vec2(0.0582416,  -0.125),
 | 
			
		||||
    vec2(0.0324462, -0.03125),
 | 
			
		||||
    vec2(0.0324462, 0.03125),
 | 
			
		||||
    vec2(0.0582416, 0.125),
 | 
			
		||||
    vec2(0.0571056,  0.28125),
 | 
			
		||||
    vec2(0.0347317, 0.5),
 | 
			
		||||
    vec2(0.0216301, 0.78125),
 | 
			
		||||
    vec2(0.0144609,  1.125),
 | 
			
		||||
    vec2(0.0100386,  1.53125),
 | 
			
		||||
    vec2(0.00317394,2.0)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
#endif //USE_17_SAMPLES
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef USE_11_SAMPLES
 | 
			
		||||
 | 
			
		||||
const int kernel_size=11;
 | 
			
		||||
 | 
			
		||||
QUALIFIER vec2 kernel[11] = vec2[](
 | 
			
		||||
    vec2(0.560479,  0.0),
 | 
			
		||||
    vec2(0.00471691,  -2.0),
 | 
			
		||||
    vec2(0.0192831, -1.28),
 | 
			
		||||
    vec2(0.03639, -0.72),
 | 
			
		||||
    vec2(0.0821904,  -0.32),
 | 
			
		||||
    vec2(0.0771802, -0.08),
 | 
			
		||||
    vec2(0.0771802,  0.08),
 | 
			
		||||
    vec2(0.0821904, 0.32),
 | 
			
		||||
    vec2(0.03639, 0.72),
 | 
			
		||||
    vec2(0.0192831, 1.28),
 | 
			
		||||
    vec2(0.00471691,2.0)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
#endif //USE_11_SAMPLES
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uniform float max_radius;
 | 
			
		||||
uniform float camera_z_far;
 | 
			
		||||
uniform float camera_z_near;
 | 
			
		||||
uniform float unit_size;
 | 
			
		||||
uniform vec2 dir;
 | 
			
		||||
in vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
uniform sampler2D source_diffuse; //texunit:0
 | 
			
		||||
uniform sampler2D source_sss; //texunit:1
 | 
			
		||||
uniform sampler2D source_depth; //texunit:2
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 frag_color;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	float strength = texture(source_sss,uv_interp).r;
 | 
			
		||||
	strength*=strength; //stored as sqrt
 | 
			
		||||
 | 
			
		||||
	// Fetch color of current pixel:
 | 
			
		||||
	vec4 base_color = texture(source_diffuse, uv_interp);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (strength>0.0) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		// Fetch linear depth of current pixel:
 | 
			
		||||
		float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0;
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
		depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
		float scale = unit_size; //remember depth is negative by default in OpenGL
 | 
			
		||||
#else
 | 
			
		||||
		depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
 | 
			
		||||
		float scale = unit_size / depth; //remember depth is negative by default in OpenGL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		// Calculate the final step to fetch the surrounding pixels:
 | 
			
		||||
		vec2 step = max_radius * scale * dir;
 | 
			
		||||
		step *= strength; // Modulate it using the alpha channel.
 | 
			
		||||
		step *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3.
 | 
			
		||||
 | 
			
		||||
		// Accumulate the center sample:
 | 
			
		||||
		vec3 color_accum = base_color.rgb;
 | 
			
		||||
		color_accum *= kernel[0].x;
 | 
			
		||||
#ifdef ENABLE_STRENGTH_WEIGHTING
 | 
			
		||||
		float color_weight = kernel[0].x;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		// Accumulate the other samples:
 | 
			
		||||
		for (int i = 1; i < kernel_size; i++) {
 | 
			
		||||
			// Fetch color and depth for current sample:
 | 
			
		||||
			vec2 offset = uv_interp + kernel[i].y * step;
 | 
			
		||||
			vec3 color = texture(source_diffuse, offset).rgb;
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_FOLLOW_SURFACE
 | 
			
		||||
			// If the difference in depth is huge, we lerp color back to "colorM":
 | 
			
		||||
			float depth_cmp = texture(source_depth, offset).r *2.0 - 1.0;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ORTHOGONAL_PROJECTION
 | 
			
		||||
			depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
 | 
			
		||||
#else
 | 
			
		||||
			depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			float s = clamp(300.0f * scale *
 | 
			
		||||
					       max_radius * abs(depth - depth_cmp),0.0,1.0);
 | 
			
		||||
			color = mix(color, base_color.rgb, s);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			// Accumulate:
 | 
			
		||||
			color*=kernel[i].x;
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_STRENGTH_WEIGHTING
 | 
			
		||||
			float color_s = texture(source_sss, offset).r;
 | 
			
		||||
			color_weight+=color_s * kernel[i].x;
 | 
			
		||||
			color*=color_s;
 | 
			
		||||
#endif
 | 
			
		||||
			color_accum += color;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_STRENGTH_WEIGHTING
 | 
			
		||||
		color_accum/=color_weight;
 | 
			
		||||
#endif
 | 
			
		||||
		frag_color = vec4(color_accum,base_color.a); //keep alpha (used for SSAO)
 | 
			
		||||
	} else {
 | 
			
		||||
		frag_color = base_color;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										323
									
								
								drivers/gles2/shaders/tonemap.glsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								drivers/gles2/shaders/tonemap.glsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,323 @@
 | 
			
		|||
[vertex]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location=0) in highp vec4 vertex_attrib;
 | 
			
		||||
layout(location=4) in vec2 uv_in;
 | 
			
		||||
 | 
			
		||||
out vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	gl_Position = vertex_attrib;
 | 
			
		||||
	uv_interp = uv_in;
 | 
			
		||||
#ifdef V_FLIP
 | 
			
		||||
	uv_interp.y = 1.0-uv_interp.y;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[fragment]
 | 
			
		||||
 | 
			
		||||
#if !defined(GLES_OVER_GL)
 | 
			
		||||
precision mediump float;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
in vec2 uv_interp;
 | 
			
		||||
 | 
			
		||||
uniform highp sampler2D source; //texunit:0
 | 
			
		||||
 | 
			
		||||
uniform float exposure;
 | 
			
		||||
uniform float white;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_AUTO_EXPOSURE
 | 
			
		||||
 | 
			
		||||
uniform highp sampler2D source_auto_exposure; //texunit:1
 | 
			
		||||
uniform highp float auto_exposure_grey;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
 | 
			
		||||
 | 
			
		||||
uniform highp sampler2D source_glow; //texunit:2
 | 
			
		||||
uniform highp float glow_intensity;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_BCS
 | 
			
		||||
 | 
			
		||||
uniform vec3 bcs;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_COLOR_CORRECTION
 | 
			
		||||
 | 
			
		||||
uniform sampler2D color_correction; //texunit:3
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 frag_color;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_FILTER_BICUBIC
 | 
			
		||||
 | 
			
		||||
// w0, w1, w2, and w3 are the four cubic B-spline basis functions
 | 
			
		||||
float w0(float a)
 | 
			
		||||
{
 | 
			
		||||
    return (1.0/6.0)*(a*(a*(-a + 3.0) - 3.0) + 1.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float w1(float a)
 | 
			
		||||
{
 | 
			
		||||
    return (1.0/6.0)*(a*a*(3.0*a - 6.0) + 4.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float w2(float a)
 | 
			
		||||
{
 | 
			
		||||
    return (1.0/6.0)*(a*(a*(-3.0*a + 3.0) + 3.0) + 1.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float w3(float a)
 | 
			
		||||
{
 | 
			
		||||
    return (1.0/6.0)*(a*a*a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// g0 and g1 are the two amplitude functions
 | 
			
		||||
float g0(float a)
 | 
			
		||||
{
 | 
			
		||||
    return w0(a) + w1(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float g1(float a)
 | 
			
		||||
{
 | 
			
		||||
    return w2(a) + w3(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// h0 and h1 are the two offset functions
 | 
			
		||||
float h0(float a)
 | 
			
		||||
{
 | 
			
		||||
    return -1.0 + w1(a) / (w0(a) + w1(a));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float h1(float a)
 | 
			
		||||
{
 | 
			
		||||
    return 1.0 + w3(a) / (w2(a) + w3(a));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uniform ivec2 glow_texture_size;
 | 
			
		||||
 | 
			
		||||
vec4 texture2D_bicubic(sampler2D tex, vec2 uv,int p_lod)
 | 
			
		||||
{
 | 
			
		||||
	float lod=float(p_lod);
 | 
			
		||||
	vec2 tex_size = vec2(glow_texture_size >> p_lod);
 | 
			
		||||
	vec2 pixel_size =1.0/tex_size;
 | 
			
		||||
	uv = uv*tex_size + 0.5;
 | 
			
		||||
	vec2 iuv = floor( uv );
 | 
			
		||||
	vec2 fuv = fract( uv );
 | 
			
		||||
 | 
			
		||||
	float g0x = g0(fuv.x);
 | 
			
		||||
	float g1x = g1(fuv.x);
 | 
			
		||||
	float h0x = h0(fuv.x);
 | 
			
		||||
	float h1x = h1(fuv.x);
 | 
			
		||||
	float h0y = h0(fuv.y);
 | 
			
		||||
	float h1y = h1(fuv.y);
 | 
			
		||||
 | 
			
		||||
	vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - 0.5) * pixel_size;
 | 
			
		||||
	vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - 0.5) * pixel_size;
 | 
			
		||||
	vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - 0.5) * pixel_size;
 | 
			
		||||
	vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - 0.5) * pixel_size;
 | 
			
		||||
 | 
			
		||||
	return g0(fuv.y) * (g0x * textureLod(tex, p0,lod)  +
 | 
			
		||||
			    g1x * textureLod(tex, p1,lod)) +
 | 
			
		||||
			g1(fuv.y) * (g0x * textureLod(tex, p2,lod)  +
 | 
			
		||||
				     g1x * textureLod(tex, p3,lod));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) texture2D_bicubic(m_tex,m_uv,m_lod)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) textureLod(m_tex,m_uv,float(m_lod))
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vec3 tonemap_filmic(vec3 color,float white) {
 | 
			
		||||
 | 
			
		||||
	float A = 0.15;
 | 
			
		||||
	float B = 0.50;
 | 
			
		||||
	float C = 0.10;
 | 
			
		||||
	float D = 0.20;
 | 
			
		||||
	float E = 0.02;
 | 
			
		||||
	float F = 0.30;
 | 
			
		||||
	float W = 11.2;
 | 
			
		||||
 | 
			
		||||
	vec3 coltn = ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F;
 | 
			
		||||
	float whitetn = ((white*(A*white+C*B)+D*E)/(white*(A*white+B)+D*F))-E/F;
 | 
			
		||||
 | 
			
		||||
	return coltn/whitetn;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vec3 tonemap_aces(vec3 color) {
 | 
			
		||||
	float a = 2.51f;
 | 
			
		||||
	float b = 0.03f;
 | 
			
		||||
	float c = 2.43f;
 | 
			
		||||
	float d = 0.59f;
 | 
			
		||||
	float e = 0.14f;
 | 
			
		||||
	return color = clamp((color*(a*color+b))/(color*(c*color+d)+e),vec3(0.0),vec3(1.0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vec3 tonemap_reindhart(vec3 color,float white) {
 | 
			
		||||
 | 
			
		||||
	return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
 | 
			
		||||
	vec4 color = textureLod(source, uv_interp, 0.0);
 | 
			
		||||
 | 
			
		||||
#ifdef USE_AUTO_EXPOSURE
 | 
			
		||||
 | 
			
		||||
	color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	color*=exposure;
 | 
			
		||||
 | 
			
		||||
#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
 | 
			
		||||
#define USING_GLOW
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(USING_GLOW)
 | 
			
		||||
	vec3 glow = vec3(0.0);
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_LEVEL1
 | 
			
		||||
 | 
			
		||||
	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,1).rgb;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_LEVEL2
 | 
			
		||||
	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,2).rgb;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_LEVEL3
 | 
			
		||||
	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,3).rgb;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_LEVEL4
 | 
			
		||||
	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,4).rgb;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_LEVEL5
 | 
			
		||||
	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,5).rgb;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_LEVEL6
 | 
			
		||||
	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,6).rgb;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_LEVEL7
 | 
			
		||||
	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,7).rgb;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	glow *= glow_intensity;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef USE_REINDHART_TONEMAPPER
 | 
			
		||||
 | 
			
		||||
	color.rgb = tonemap_reindhart(color.rgb,white);
 | 
			
		||||
 | 
			
		||||
# if defined(USING_GLOW)
 | 
			
		||||
	glow = tonemap_reindhart(glow,white);
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_FILMIC_TONEMAPPER
 | 
			
		||||
 | 
			
		||||
	color.rgb = tonemap_filmic(color.rgb,white);
 | 
			
		||||
 | 
			
		||||
# if defined(USING_GLOW)
 | 
			
		||||
	glow = tonemap_filmic(glow,white);
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ACES_TONEMAPPER
 | 
			
		||||
 | 
			
		||||
	color.rgb = tonemap_aces(color.rgb);
 | 
			
		||||
 | 
			
		||||
# if defined(USING_GLOW)
 | 
			
		||||
	glow = tonemap_aces(glow);
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	//regular Linear -> SRGB conversion
 | 
			
		||||
	vec3 a = vec3(0.055);
 | 
			
		||||
	color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308)));
 | 
			
		||||
 | 
			
		||||
#if defined(USING_GLOW)
 | 
			
		||||
	glow = mix( (vec3(1.0)+a)*pow(glow,vec3(1.0/2.4))-a , 12.92*glow , lessThan(glow,vec3(0.0031308)));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//glow needs to be added in SRGB space (together with image space effects)
 | 
			
		||||
 | 
			
		||||
	color.rgb = clamp(color.rgb,0.0,1.0);
 | 
			
		||||
 | 
			
		||||
#if defined(USING_GLOW)
 | 
			
		||||
	glow = clamp(glow,0.0,1.0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_REPLACE
 | 
			
		||||
 | 
			
		||||
	color.rgb = glow;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_SCREEN
 | 
			
		||||
 | 
			
		||||
	color.rgb = max((color.rgb + glow) - (color.rgb * glow), vec3(0.0));
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GLOW_SOFTLIGHT
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		glow = (glow * 0.5) + 0.5;
 | 
			
		||||
		color.r =  (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r)));
 | 
			
		||||
		color.g =  (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g)));
 | 
			
		||||
		color.b =  (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(USING_GLOW) && !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE)
 | 
			
		||||
	//additive
 | 
			
		||||
	color.rgb+=glow;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_BCS
 | 
			
		||||
 | 
			
		||||
	color.rgb = mix(vec3(0.0),color.rgb,bcs.x);
 | 
			
		||||
	color.rgb = mix(vec3(0.5),color.rgb,bcs.y);
 | 
			
		||||
	color.rgb = mix(vec3(dot(vec3(1.0),color.rgb)*0.33333),color.rgb,bcs.z);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_COLOR_CORRECTION
 | 
			
		||||
 | 
			
		||||
	color.r = texture(color_correction,vec2(color.r,0.0)).r;
 | 
			
		||||
	color.g = texture(color_correction,vec2(color.g,0.0)).g;
 | 
			
		||||
	color.b = texture(color_correction,vec2(color.b,0.0)).b;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	frag_color=vec4(color.rgb,1.0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										722
									
								
								methods.py
									
										
									
									
									
								
							
							
						
						
									
										722
									
								
								methods.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -19,637 +19,6 @@ def add_source_files(self, sources, filetype, lib_env=None, shared=False):
 | 
			
		|||
            sources.append(self.Object(f))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_shader_header(target, source, env):
 | 
			
		||||
 | 
			
		||||
    for x in source:
 | 
			
		||||
        print(x)
 | 
			
		||||
 | 
			
		||||
        name = str(x)
 | 
			
		||||
        name = name[name.rfind("/") + 1:]
 | 
			
		||||
        name = name[name.rfind("\\") + 1:]
 | 
			
		||||
        name = name.replace(".", "_")
 | 
			
		||||
 | 
			
		||||
        fs = open(str(x), "r")
 | 
			
		||||
        fd = open(str(x) + ".gen.h", "w")
 | 
			
		||||
        fd.write("/* this file has been generated by SCons, do not edit! */\n")
 | 
			
		||||
        fd.write("static const char *" + name + "=\n")
 | 
			
		||||
        line = fs.readline()
 | 
			
		||||
        while(line):
 | 
			
		||||
            line = line.replace("\r", "")
 | 
			
		||||
            line = line.replace("\n", "")
 | 
			
		||||
            line = line.replace("\\", "\\\\")
 | 
			
		||||
            line = line.replace("\"", "\\\"")
 | 
			
		||||
            fd.write("\"" + line + "\\n\"\n")
 | 
			
		||||
            line = fs.readline()
 | 
			
		||||
 | 
			
		||||
        fd.write(";\n")
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_glsl_header(filename):
 | 
			
		||||
 | 
			
		||||
    fs = open(filename, "r")
 | 
			
		||||
    line = fs.readline()
 | 
			
		||||
 | 
			
		||||
    vertex_lines = []
 | 
			
		||||
    fragment_lines = []
 | 
			
		||||
    uniforms = []
 | 
			
		||||
    attributes = []
 | 
			
		||||
    fbos = []
 | 
			
		||||
    conditionals = []
 | 
			
		||||
    texunits = []
 | 
			
		||||
    texunit_names = []
 | 
			
		||||
    ubos = []
 | 
			
		||||
    ubo_names = []
 | 
			
		||||
 | 
			
		||||
    reading = ""
 | 
			
		||||
    line_offset = 0
 | 
			
		||||
    vertex_offset = 0
 | 
			
		||||
    fragment_offset = 0
 | 
			
		||||
 | 
			
		||||
    while(line):
 | 
			
		||||
 | 
			
		||||
        if (line.find("[vertex]") != -1):
 | 
			
		||||
            reading = "vertex"
 | 
			
		||||
            line = fs.readline()
 | 
			
		||||
            line_offset += 1
 | 
			
		||||
            vertex_offset = line_offset
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if (line.find("[fragment]") != -1):
 | 
			
		||||
            reading = "fragment"
 | 
			
		||||
            line = fs.readline()
 | 
			
		||||
            line_offset += 1
 | 
			
		||||
            fragment_offset = line_offset
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if (line.find("#ifdef ") != -1):
 | 
			
		||||
            ifdefline = line.replace("#ifdef ", "").strip()
 | 
			
		||||
            if (not ifdefline in conditionals):
 | 
			
		||||
                conditionals += [ifdefline]
 | 
			
		||||
 | 
			
		||||
        if (line.find("#elif defined(") != -1):
 | 
			
		||||
            ifdefline = line.replace("#elif defined(", "").strip()
 | 
			
		||||
            ifdefline = ifdefline.replace(")", "").strip()
 | 
			
		||||
            if (not ifdefline in conditionals):
 | 
			
		||||
                conditionals += [ifdefline]
 | 
			
		||||
 | 
			
		||||
        import re
 | 
			
		||||
        if re.search(r"^\s*uniform", line):
 | 
			
		||||
 | 
			
		||||
            if (line.lower().find("texunit:") != -1):
 | 
			
		||||
                # texture unit
 | 
			
		||||
                texunit = str(int(line[line.find(":") + 1:].strip()))
 | 
			
		||||
                uline = line[:line.lower().find("//")]
 | 
			
		||||
                uline = uline.replace("uniform", "")
 | 
			
		||||
                uline = uline.replace(";", "")
 | 
			
		||||
                lines = uline.split(",")
 | 
			
		||||
                for x in lines:
 | 
			
		||||
 | 
			
		||||
                    x = x.strip()
 | 
			
		||||
                    x = x[x.rfind(" ") + 1:]
 | 
			
		||||
                    if (x.find("[") != -1):
 | 
			
		||||
                        # unfiorm array
 | 
			
		||||
                        x = x[:x.find("[")]
 | 
			
		||||
 | 
			
		||||
                    if (not x in texunit_names):
 | 
			
		||||
                        texunits += [(x, texunit)]
 | 
			
		||||
                        texunit_names += [x]
 | 
			
		||||
 | 
			
		||||
            elif (line.lower().find("ubo:") != -1):
 | 
			
		||||
                # ubo
 | 
			
		||||
                uboidx = str(int(line[line.find(":") + 1:].strip()))
 | 
			
		||||
                uline = line[:line.lower().find("//")]
 | 
			
		||||
                uline = uline[uline.find("uniform") + len("uniform"):]
 | 
			
		||||
                uline = uline.replace(";", "")
 | 
			
		||||
                uline = uline.replace("{", "").strip()
 | 
			
		||||
                lines = uline.split(",")
 | 
			
		||||
                for x in lines:
 | 
			
		||||
 | 
			
		||||
                    x = x.strip()
 | 
			
		||||
                    x = x[x.rfind(" ") + 1:]
 | 
			
		||||
                    if (x.find("[") != -1):
 | 
			
		||||
                        # unfiorm array
 | 
			
		||||
                        x = x[:x.find("[")]
 | 
			
		||||
 | 
			
		||||
                    if (not x in ubo_names):
 | 
			
		||||
                        ubos += [(x, uboidx)]
 | 
			
		||||
                        ubo_names += [x]
 | 
			
		||||
 | 
			
		||||
            else:
 | 
			
		||||
                uline = line.replace("uniform", "")
 | 
			
		||||
                uline = uline.replace(";", "")
 | 
			
		||||
                lines = uline.split(",")
 | 
			
		||||
                for x in lines:
 | 
			
		||||
 | 
			
		||||
                    x = x.strip()
 | 
			
		||||
                    x = x[x.rfind(" ") + 1:]
 | 
			
		||||
                    if (x.find("[") != -1):
 | 
			
		||||
                        # unfiorm array
 | 
			
		||||
                        x = x[:x.find("[")]
 | 
			
		||||
 | 
			
		||||
                    if (not x in uniforms):
 | 
			
		||||
                        uniforms += [x]
 | 
			
		||||
 | 
			
		||||
        if ((line.strip().find("in ") == 0 or line.strip().find("attribute ") == 0) and line.find("attrib:") != -1):
 | 
			
		||||
            uline = line.replace("in ", "")
 | 
			
		||||
            uline = uline.replace("attribute ", "")
 | 
			
		||||
            uline = uline.replace(";", "")
 | 
			
		||||
            uline = uline[uline.find(" "):].strip()
 | 
			
		||||
 | 
			
		||||
            if (uline.find("//") != -1):
 | 
			
		||||
                name, bind = uline.split("//")
 | 
			
		||||
                if (bind.find("attrib:") != -1):
 | 
			
		||||
                    name = name.strip()
 | 
			
		||||
                    bind = bind.replace("attrib:", "").strip()
 | 
			
		||||
                    attributes += [(name, bind)]
 | 
			
		||||
 | 
			
		||||
        if (line.strip().find("out ") == 0):
 | 
			
		||||
            uline = line.replace("out", "").strip()
 | 
			
		||||
            uline = uline.replace(";", "")
 | 
			
		||||
            uline = uline[uline.find(" "):].strip()
 | 
			
		||||
 | 
			
		||||
            if (uline.find("//") != -1):
 | 
			
		||||
                name, bind = uline.split("//")
 | 
			
		||||
                if (bind.find("drawbuffer:") != -1):
 | 
			
		||||
                    name = name.strip()
 | 
			
		||||
                    bind = bind.replace("drawbuffer:", "").strip()
 | 
			
		||||
                    fbos += [(name, bind)]
 | 
			
		||||
 | 
			
		||||
        line = line.replace("\r", "")
 | 
			
		||||
        line = line.replace("\n", "")
 | 
			
		||||
        line = line.replace("\\", "\\\\")
 | 
			
		||||
        line = line.replace("\"", "\\\"")
 | 
			
		||||
        # line=line+"\\n\\" no need to anymore
 | 
			
		||||
 | 
			
		||||
        if (reading == "vertex"):
 | 
			
		||||
            vertex_lines += [line]
 | 
			
		||||
        if (reading == "fragment"):
 | 
			
		||||
            fragment_lines += [line]
 | 
			
		||||
 | 
			
		||||
        line = fs.readline()
 | 
			
		||||
        line_offset += 1
 | 
			
		||||
 | 
			
		||||
    fs.close()
 | 
			
		||||
 | 
			
		||||
    out_file = filename + ".gen.h"
 | 
			
		||||
    fd = open(out_file, "w")
 | 
			
		||||
 | 
			
		||||
    fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n")
 | 
			
		||||
 | 
			
		||||
    out_file_base = out_file
 | 
			
		||||
    out_file_base = out_file_base[out_file_base.rfind("/") + 1:]
 | 
			
		||||
    out_file_base = out_file_base[out_file_base.rfind("\\") + 1:]
 | 
			
		||||
#	print("out file "+out_file+" base " +out_file_base)
 | 
			
		||||
    out_file_ifdef = out_file_base.replace(".", "_").upper()
 | 
			
		||||
    fd.write("#ifndef " + out_file_ifdef + "\n")
 | 
			
		||||
    fd.write("#define " + out_file_ifdef + "\n")
 | 
			
		||||
 | 
			
		||||
    out_file_class = out_file_base.replace(".glsl.h", "").title().replace("_", "").replace(".", "") + "ShaderGL"
 | 
			
		||||
    fd.write("\n\n")
 | 
			
		||||
    fd.write("#include \"drivers/opengl/shader_gl.h\"\n\n\n")
 | 
			
		||||
    fd.write("class " + out_file_class + " : public ShaderGL {\n\n")
 | 
			
		||||
    fd.write("\t virtual String get_shader_name() const { return \"" + out_file_class + "\"; }\n")
 | 
			
		||||
    fd.write("public:\n\n")
 | 
			
		||||
 | 
			
		||||
    if (len(conditionals)):
 | 
			
		||||
        fd.write("\tenum Conditionals {\n")
 | 
			
		||||
        for x in conditionals:
 | 
			
		||||
            fd.write("\t\t" + x + ",\n")
 | 
			
		||||
        fd.write("\t};\n\n")
 | 
			
		||||
    if (len(uniforms)):
 | 
			
		||||
        fd.write("\tenum Uniforms {\n")
 | 
			
		||||
        for x in uniforms:
 | 
			
		||||
            fd.write("\t\t" + x.upper() + ",\n")
 | 
			
		||||
        fd.write("\t};\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ int get_uniform(Uniforms p_uniform) const { return _get_uniform(p_uniform); }\n\n")
 | 
			
		||||
    if (len(conditionals)):
 | 
			
		||||
 | 
			
		||||
        fd.write("\t_FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable)  {  _set_conditional(p_conditional,p_enable); }\n\n")
 | 
			
		||||
    fd.write("\t#define _FU if (get_uniform(p_uniform)<0) return; ERR_FAIL_COND( get_active()!=this );\n\n ")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, bool p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value?1:0); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint64_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n");
 | 
			
		||||
    #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int64_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n");
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, unsigned long p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, long p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Plane& p_plane) { _FU GLfloat plane[4]={p_plane.normal.x,p_plane.normal.y,p_plane.normal.z,p_plane.d}; glUniform4fv(get_uniform(p_uniform),1,plane); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU glUniform4f(get_uniform(p_uniform),p_a,p_b,p_c,p_d); }\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) {  _FU
 | 
			
		||||
 | 
			
		||||
		const Transform &tr = p_transform;
 | 
			
		||||
 | 
			
		||||
		GLfloat matrix[16]={ /* build a 16x16 matrix */
 | 
			
		||||
			tr.basis.elements[0][0],
 | 
			
		||||
			tr.basis.elements[1][0],
 | 
			
		||||
			tr.basis.elements[2][0],
 | 
			
		||||
			0,
 | 
			
		||||
			tr.basis.elements[0][1],
 | 
			
		||||
			tr.basis.elements[1][1],
 | 
			
		||||
			tr.basis.elements[2][1],
 | 
			
		||||
			0,
 | 
			
		||||
			tr.basis.elements[0][2],
 | 
			
		||||
			tr.basis.elements[1][2],
 | 
			
		||||
			tr.basis.elements[2][2],
 | 
			
		||||
			0,
 | 
			
		||||
			tr.origin.x,
 | 
			
		||||
			tr.origin.y,
 | 
			
		||||
			tr.origin.z,
 | 
			
		||||
			1
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	""")
 | 
			
		||||
 | 
			
		||||
    fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform2D& p_transform) {  _FU
 | 
			
		||||
 | 
			
		||||
		const Transform2D &tr = p_transform;
 | 
			
		||||
 | 
			
		||||
		GLfloat matrix[16]={ /* build a 16x16 matrix */
 | 
			
		||||
			tr.elements[0][0],
 | 
			
		||||
			tr.elements[0][1],
 | 
			
		||||
			0,
 | 
			
		||||
			0,
 | 
			
		||||
			tr.elements[1][0],
 | 
			
		||||
			tr.elements[1][1],
 | 
			
		||||
			0,
 | 
			
		||||
			0,
 | 
			
		||||
			0,
 | 
			
		||||
			0,
 | 
			
		||||
			1,
 | 
			
		||||
			0,
 | 
			
		||||
			tr.elements[2][0],
 | 
			
		||||
			tr.elements[2][1],
 | 
			
		||||
			0,
 | 
			
		||||
			1
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	""")
 | 
			
		||||
 | 
			
		||||
    fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) {  _FU
 | 
			
		||||
 | 
			
		||||
		GLfloat matrix[16];
 | 
			
		||||
 | 
			
		||||
		for (int i=0;i<4;i++) {
 | 
			
		||||
			for (int j=0;j<4;j++) {
 | 
			
		||||
 | 
			
		||||
				matrix[i*4+j]=p_matrix.matrix[i][j];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
	}; """)
 | 
			
		||||
 | 
			
		||||
    fd.write("\n\n#undef _FU\n\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\tvirtual void init() {\n\n")
 | 
			
		||||
    if (len(conditionals)):
 | 
			
		||||
 | 
			
		||||
        fd.write("\t\tstatic const char* _conditional_strings[]={\n")
 | 
			
		||||
        if (len(conditionals)):
 | 
			
		||||
            for x in conditionals:
 | 
			
		||||
                fd.write("\t\t\t\"#define " + x + "\\n\",\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic const char **_conditional_strings=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(uniforms)):
 | 
			
		||||
 | 
			
		||||
        fd.write("\t\tstatic const char* _uniform_strings[]={\n")
 | 
			
		||||
        if (len(uniforms)):
 | 
			
		||||
            for x in uniforms:
 | 
			
		||||
                fd.write("\t\t\t\"" + x + "\",\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic const char **_uniform_strings=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(attributes)):
 | 
			
		||||
 | 
			
		||||
        fd.write("\t\tstatic AttributePair _attribute_pairs[]={\n")
 | 
			
		||||
        for x in attributes:
 | 
			
		||||
            fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic AttributePair *_attribute_pairs=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(fbos)):
 | 
			
		||||
        fd.write("\t\tstatic FBOPair _fbo_pairs[]={\n")
 | 
			
		||||
        for x in fbos:
 | 
			
		||||
            fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic FBOPair *_fbo_pairs=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(ubos)):
 | 
			
		||||
        fd.write("\t\tstatic UBOPair _ubo_pairs[]={\n")
 | 
			
		||||
        for x in ubos:
 | 
			
		||||
            fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic UBOPair *_ubo_pairs=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(texunits)):
 | 
			
		||||
        fd.write("\t\tstatic TexUnitPair _texunit_pairs[]={\n")
 | 
			
		||||
        for x in texunits:
 | 
			
		||||
            fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic TexUnitPair *_texunit_pairs=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const char* _vertex_code=\"\\\n")
 | 
			
		||||
    for x in vertex_lines:
 | 
			
		||||
        fd.write("\t\t\t" + x + "\n")
 | 
			
		||||
    fd.write("\t\t\";\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const int _vertex_code_start=" + str(vertex_offset) + ";\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const char* _fragment_code=\"\\\n")
 | 
			
		||||
    for x in fragment_lines:
 | 
			
		||||
        fd.write("\t\t\t" + x + "\n")
 | 
			
		||||
    fd.write("\t\t\";\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const int _fragment_code_start=" + str(fragment_offset) + ";\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tsetup(_conditional_strings," + str(len(conditionals)) + ",_uniform_strings," + str(len(uniforms)) + ",_attribute_pairs," + str(len(attributes)) + ",_fbo_pairs," + str(len(fbos)) + ",_ubo_pairs," + str(len(ubos)) + ",_texunit_pairs," + str(len(texunits)) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
    fd.write("\t};\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("};\n\n")
 | 
			
		||||
    fd.write("#endif\n\n")
 | 
			
		||||
    fd.close()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_glsl_headers(target, source, env):
 | 
			
		||||
 | 
			
		||||
    for x in source:
 | 
			
		||||
 | 
			
		||||
        build_glsl_header(str(x))
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_hlsl_dx9_header(filename):
 | 
			
		||||
 | 
			
		||||
    fs = open(filename, "r")
 | 
			
		||||
    line = fs.readline()
 | 
			
		||||
 | 
			
		||||
    vertex_lines = []
 | 
			
		||||
    fragment_lines = []
 | 
			
		||||
    uniforms = []
 | 
			
		||||
    fragment_uniforms = []
 | 
			
		||||
    attributes = []
 | 
			
		||||
    fbos = []
 | 
			
		||||
    conditionals = []
 | 
			
		||||
 | 
			
		||||
    reading = ""
 | 
			
		||||
    line_offset = 0
 | 
			
		||||
    vertex_offset = 0
 | 
			
		||||
    fragment_offset = 0
 | 
			
		||||
 | 
			
		||||
    while(line):
 | 
			
		||||
 | 
			
		||||
        if (line.find("[vertex]") != -1):
 | 
			
		||||
            reading = "vertex"
 | 
			
		||||
            line = fs.readline()
 | 
			
		||||
            line_offset += 1
 | 
			
		||||
            vertex_offset = line_offset
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if (line.find("[fragment]") != -1):
 | 
			
		||||
            reading = "fragment"
 | 
			
		||||
            line = fs.readline()
 | 
			
		||||
            line_offset += 1
 | 
			
		||||
            fragment_offset = line_offset
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if (line.find("#ifdef ") != -1):
 | 
			
		||||
            ifdefline = line.replace("#ifdef ", "").strip()
 | 
			
		||||
            if (not ifdefline in conditionals):
 | 
			
		||||
                conditionals += [ifdefline]
 | 
			
		||||
 | 
			
		||||
        if (line.find("#elif defined(") != -1):
 | 
			
		||||
            ifdefline = line.replace("#elif defined(", "").strip()
 | 
			
		||||
            ifdefline = ifdefline.replace(")", "").strip()
 | 
			
		||||
            if (not ifdefline in conditionals):
 | 
			
		||||
                conditionals += [ifdefline]
 | 
			
		||||
        if (line.find("uniform") != -1):
 | 
			
		||||
            uline = line.replace("uniform", "")
 | 
			
		||||
            uline = uline.replace(";", "")
 | 
			
		||||
            lines = uline.split(",")
 | 
			
		||||
            for x in lines:
 | 
			
		||||
 | 
			
		||||
                x = x.strip()
 | 
			
		||||
                x = x[x.rfind(" ") + 1:]
 | 
			
		||||
                if (x.find("[") != -1):
 | 
			
		||||
                    # unfiorm array
 | 
			
		||||
                    x = x[:x.find("[")]
 | 
			
		||||
 | 
			
		||||
                if (not x in uniforms):
 | 
			
		||||
                    uniforms += [x]
 | 
			
		||||
                    fragment_uniforms += [reading == "fragment"]
 | 
			
		||||
        line = line.replace("\r", "")
 | 
			
		||||
        line = line.replace("\n", "")
 | 
			
		||||
        line = line.replace("\\", "\\\\")
 | 
			
		||||
        line = line.replace("\"", "\\\"")
 | 
			
		||||
        line = line + "\\n\\"
 | 
			
		||||
 | 
			
		||||
        if (reading == "vertex"):
 | 
			
		||||
            vertex_lines += [line]
 | 
			
		||||
        if (reading == "fragment"):
 | 
			
		||||
            fragment_lines += [line]
 | 
			
		||||
 | 
			
		||||
        line = fs.readline()
 | 
			
		||||
        line_offset += 1
 | 
			
		||||
 | 
			
		||||
    fs.close()
 | 
			
		||||
 | 
			
		||||
    out_file = filename + ".gen.h"
 | 
			
		||||
    fd = open(out_file, "w")
 | 
			
		||||
 | 
			
		||||
    fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n")
 | 
			
		||||
 | 
			
		||||
    out_file_base = out_file
 | 
			
		||||
    out_file_base = out_file_base[out_file_base.rfind("/") + 1:]
 | 
			
		||||
    out_file_base = out_file_base[out_file_base.rfind("\\") + 1:]
 | 
			
		||||
#	print("out file "+out_file+" base " +out_file_base)
 | 
			
		||||
    out_file_ifdef = out_file_base.replace(".", "_").upper()
 | 
			
		||||
    fd.write("#ifndef " + out_file_ifdef + "\n")
 | 
			
		||||
    fd.write("#define " + out_file_ifdef + "\n")
 | 
			
		||||
 | 
			
		||||
    out_file_class = out_file_base.replace(".hlsl.h", "").title().replace("_", "").replace(".", "") + "ShaderDX9"
 | 
			
		||||
    fd.write("\n\n")
 | 
			
		||||
    fd.write("#include \"drivers/directx9/shader_dx9.h\"\n\n\n")
 | 
			
		||||
    fd.write("class " + out_file_class + " : public ShaderDX9 {\n\n")
 | 
			
		||||
    fd.write("\t virtual String get_shader_name() const { return \"" + out_file_class + "\"; }\n")
 | 
			
		||||
    fd.write("public:\n\n")
 | 
			
		||||
 | 
			
		||||
    if (len(conditionals)):
 | 
			
		||||
        fd.write("\tenum Conditionals {\n")
 | 
			
		||||
        for x in conditionals:
 | 
			
		||||
            fd.write("\t\t" + x + ",\n")
 | 
			
		||||
        fd.write("\t};\n\n")
 | 
			
		||||
    if (len(uniforms)):
 | 
			
		||||
        fd.write("\tenum Uniforms {\n")
 | 
			
		||||
        for x in uniforms:
 | 
			
		||||
            fd.write("\t\t" + x.upper() + ",\n")
 | 
			
		||||
        fd.write("\t};\n\n")
 | 
			
		||||
 | 
			
		||||
    if (len(conditionals)):
 | 
			
		||||
        fd.write("\t_FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable)  {  _set_conditional(p_conditional,p_enable); }\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t#define _FU if (!_uniform_valid(p_uniform)) return; ERR_FAIL_COND( get_active()!=this );\n\n ")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, bool p_value) { _FU set_uniformb(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU set_uniformf(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU set_uniformf(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint64_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n");
 | 
			
		||||
    #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int64_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n");
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, unsigned long p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, long p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU float col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; set_uniformfv(p_uniform,col); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU float vec2[4]={p_vec2.x,p_vec2.y,0,0}; set_uniformfv(p_uniform,vec2); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU float vec3[4]={p_vec3.x,p_vec3.y,p_vec3.z,0}; set_uniformfv(p_uniform,vec3); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU float vec2[4]={p_a,p_b,0,0}; set_uniformfv(p_uniform,vec2); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU float vec3[4]={p_a,p_b,p_c,0}; set_uniformfv(p_uniform,vec3); }\n\n")
 | 
			
		||||
    fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU float vec4[4]={p_a,p_b,p_c,p_d}; set_uniformfv(p_uniform,vec4); }\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) {  _FU
 | 
			
		||||
 | 
			
		||||
		const Transform &tr = p_transform;
 | 
			
		||||
 | 
			
		||||
		float matrix[16]={ /* build a 16x16 matrix */
 | 
			
		||||
			tr.basis.elements[0][0],
 | 
			
		||||
			tr.basis.elements[0][1],
 | 
			
		||||
			tr.basis.elements[0][2],
 | 
			
		||||
			tr.origin.x,
 | 
			
		||||
			tr.basis.elements[1][0],
 | 
			
		||||
			tr.basis.elements[1][1],
 | 
			
		||||
			tr.basis.elements[1][2],
 | 
			
		||||
			tr.origin.y,
 | 
			
		||||
			tr.basis.elements[2][0],
 | 
			
		||||
			tr.basis.elements[2][1],
 | 
			
		||||
			tr.basis.elements[2][2],
 | 
			
		||||
			tr.origin.z,
 | 
			
		||||
			0,
 | 
			
		||||
			0,
 | 
			
		||||
			0,
 | 
			
		||||
			1
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		set_uniformfv(p_uniform,&matrix[0],4);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	""")
 | 
			
		||||
 | 
			
		||||
    fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) {  _FU
 | 
			
		||||
 | 
			
		||||
		float matrix[16];
 | 
			
		||||
 | 
			
		||||
		for (int i=0;i<4;i++) {
 | 
			
		||||
			for (int j=0;j<4;j++) {
 | 
			
		||||
 | 
			
		||||
				matrix[i*4+j]=p_matrix.matrix[j][i];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		set_uniformfv(p_uniform,&matrix[0],4);
 | 
			
		||||
	}; """)
 | 
			
		||||
 | 
			
		||||
    fd.write("\n\n#undef _FU\n\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\tvirtual void init(IDirect3DDevice9 *p_device,ShaderSupport p_version) {\n\n")
 | 
			
		||||
    if (len(conditionals)):
 | 
			
		||||
 | 
			
		||||
        fd.write("\t\tstatic const char* _conditional_strings[]={\n")
 | 
			
		||||
        if (len(conditionals)):
 | 
			
		||||
            for x in conditionals:
 | 
			
		||||
                fd.write("\t\t\t\"" + x + "\",\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic const char **_conditional_strings=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(uniforms)):
 | 
			
		||||
 | 
			
		||||
        fd.write("\t\tstatic const char* _uniform_strings[]={\n")
 | 
			
		||||
        if (len(uniforms)):
 | 
			
		||||
            for x in uniforms:
 | 
			
		||||
                fd.write("\t\t\t\"" + x + "\",\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
 | 
			
		||||
        fd.write("\t\tstatic const bool _fragment_uniforms[]={\n")
 | 
			
		||||
 | 
			
		||||
        if (len(uniforms)):
 | 
			
		||||
            for x in fragment_uniforms:
 | 
			
		||||
                if (x):
 | 
			
		||||
                    fd.write("\t\t\ttrue,\n")
 | 
			
		||||
                else:
 | 
			
		||||
                    fd.write("\t\t\tfalse,\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic const char **_uniform_strings=NULL;\n")
 | 
			
		||||
        fd.write("\t\tstatic const bool *_fragment_uniforms=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const char* _vertex_code=\"\\\n")
 | 
			
		||||
    for x in vertex_lines:
 | 
			
		||||
        fd.write("\t\t\t" + x + "\n")
 | 
			
		||||
    fd.write("\t\t\";\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const int _vertex_code_start=" + str(vertex_offset) + ";\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const char* _fragment_code=\"\\\n")
 | 
			
		||||
    for x in fragment_lines:
 | 
			
		||||
        fd.write("\t\t\t" + x + "\n")
 | 
			
		||||
    fd.write("\t\t\";\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const int _fragment_code_start=" + str(fragment_offset) + ";\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tsetup(p_device,p_version,_conditional_strings," + str(len(conditionals)) + ",_uniform_strings," + str(len(uniforms)) + ",_fragment_uniforms,_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
    fd.write("\t};\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("};\n\n")
 | 
			
		||||
    fd.write("#endif\n\n")
 | 
			
		||||
    fd.close()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_hlsl_dx9_headers(target, source, env):
 | 
			
		||||
 | 
			
		||||
    for x in source:
 | 
			
		||||
 | 
			
		||||
        build_hlsl_dx9_header(str(x))
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LegacyGLHeaderStruct:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -840,7 +209,7 @@ def include_file_in_legacygl_header(filename, header_data, depth):
 | 
			
		|||
    return header_data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		||||
def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2=False):
 | 
			
		||||
 | 
			
		||||
    header_data = LegacyGLHeaderStruct()
 | 
			
		||||
    include_file_in_legacygl_header(filename, header_data, 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -928,14 +297,14 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
                glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	""")
 | 
			
		||||
 | 
			
		||||
    fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform2D& p_transform) {  _FU
 | 
			
		||||
    fd.write("""_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform2D& p_transform) {  _FU
 | 
			
		||||
 | 
			
		||||
		const Transform2D &tr = p_transform;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -959,14 +328,14 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
                glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	""")
 | 
			
		||||
 | 
			
		||||
    fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) {  _FU
 | 
			
		||||
    fd.write("""_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) {  _FU
 | 
			
		||||
 | 
			
		||||
		GLfloat matrix[16];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -978,7 +347,7 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
 | 
			
		||||
	}; """)
 | 
			
		||||
        } """)
 | 
			
		||||
 | 
			
		||||
    fd.write("\n\n#undef _FU\n\n\n")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1061,7 +430,7 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
 | 
			
		||||
    feedback_count = 0
 | 
			
		||||
 | 
			
		||||
    if (len(header_data.feedbacks)):
 | 
			
		||||
    if (not gles2 and len(header_data.feedbacks)):
 | 
			
		||||
 | 
			
		||||
        fd.write("\t\tstatic const Feedback _feedbacks[]={\n")
 | 
			
		||||
        for x in header_data.feedbacks:
 | 
			
		||||
| 
						 | 
				
			
			@ -1076,7 +445,10 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic const Feedback* _feedbacks=NULL;\n")
 | 
			
		||||
        if gles2:
 | 
			
		||||
            pass
 | 
			
		||||
        else:
 | 
			
		||||
            fd.write("\t\tstatic const Feedback* _feedbacks=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(header_data.texunits)):
 | 
			
		||||
        fd.write("\t\tstatic TexUnitPair _texunit_pairs[]={\n")
 | 
			
		||||
| 
						 | 
				
			
			@ -1086,13 +458,16 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
    else:
 | 
			
		||||
        fd.write("\t\tstatic TexUnitPair *_texunit_pairs=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    if (len(header_data.ubos)):
 | 
			
		||||
    if (not gles2 and len(header_data.ubos)):
 | 
			
		||||
        fd.write("\t\tstatic UBOPair _ubo_pairs[]={\n")
 | 
			
		||||
        for x in header_data.ubos:
 | 
			
		||||
            fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n")
 | 
			
		||||
        fd.write("\t\t};\n\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tstatic UBOPair *_ubo_pairs=NULL;\n")
 | 
			
		||||
        if gles2:
 | 
			
		||||
            pass
 | 
			
		||||
        else:
 | 
			
		||||
            fd.write("\t\tstatic UBOPair *_ubo_pairs=NULL;\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t\tstatic const char _vertex_code[]={\n")
 | 
			
		||||
    for x in header_data.vertex_lines:
 | 
			
		||||
| 
						 | 
				
			
			@ -1115,11 +490,17 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
    fd.write("\t\tstatic const int _fragment_code_start=" + str(header_data.fragment_offset) + ";\n")
 | 
			
		||||
 | 
			
		||||
    if output_attribs:
 | 
			
		||||
        fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_attribute_pairs," + str(len(header_data.attributes)) + ", _texunit_pairs," + str(len(header_data.texunits)) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
        if gles2:
 | 
			
		||||
            fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_attribute_pairs," + str(len(header_data.attributes)) + ", _texunit_pairs," + str(len(header_data.texunits)) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
        else:
 | 
			
		||||
            fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_attribute_pairs," + str(len(header_data.attributes)) + ", _texunit_pairs," + str(len(header_data.texunits)) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
    else:
 | 
			
		||||
        fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_texunit_pairs," + str(len(header_data.texunits)) + ",_enums," + str(len(header_data.enums)) + ",_enum_values," + str(enum_value_count) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
        if gles2:
 | 
			
		||||
            fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_texunit_pairs," + str(len(header_data.texunits)) + ",_enums," + str(len(header_data.enums)) + ",_enum_values," + str(enum_value_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
        else:
 | 
			
		||||
            fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_texunit_pairs," + str(len(header_data.texunits)) + ",_enums," + str(len(header_data.enums)) + ",_enum_values," + str(enum_value_count) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\t};\n\n")
 | 
			
		||||
    fd.write("\t}\n\n")
 | 
			
		||||
 | 
			
		||||
    if (len(enum_constants)):
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1134,21 +515,17 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs):
 | 
			
		|||
    fd.close()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_legacygl_headers(target, source, env):
 | 
			
		||||
 | 
			
		||||
    for x in source:
 | 
			
		||||
 | 
			
		||||
        build_legacygl_header(str(x), include="drivers/legacygl/shader_lgl.h", class_suffix="LGL", output_attribs=False)
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_gles3_headers(target, source, env):
 | 
			
		||||
 | 
			
		||||
    for x in source:
 | 
			
		||||
        build_legacygl_header(str(x), include="drivers/gles3/shader_gles3.h", class_suffix="GLES3", output_attribs=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_gles2_headers(target, source, env):
 | 
			
		||||
 | 
			
		||||
    for x in source:
 | 
			
		||||
        build_legacygl_header(str(x), include="drivers/gles2/shader_gles2.h", class_suffix="GLES2", output_attribs=True, gles2=True)
 | 
			
		||||
 | 
			
		||||
def add_module_version_string(self,s):
 | 
			
		||||
    self.module_version_string += "." + s
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1220,45 +597,6 @@ def parse_cg_file(fname, uniforms, sizes, conditionals):
 | 
			
		|||
 | 
			
		||||
        line = fs.readline()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_cg_shader(sname):
 | 
			
		||||
 | 
			
		||||
    vp_uniforms = []
 | 
			
		||||
    vp_uniform_sizes = []
 | 
			
		||||
    vp_conditionals = []
 | 
			
		||||
 | 
			
		||||
    parse_cg_file("vp_" + sname + ".cg", vp_uniforms, vp_uniform_sizes, vp_conditionals)
 | 
			
		||||
 | 
			
		||||
    fp_uniforms = []
 | 
			
		||||
    fp_uniform_sizes = []
 | 
			
		||||
    fp_conditionals = []
 | 
			
		||||
 | 
			
		||||
    parse_cg_file("fp_" + sname + ".cg", fp_uniforms, fp_uniform_sizes, fp_conditionals)
 | 
			
		||||
 | 
			
		||||
    fd = open("shader_" + sname + ".cg.gen.h", "w")
 | 
			
		||||
 | 
			
		||||
    fd.write('\n#include "shader_cell.h"\n')
 | 
			
		||||
    fd.write("\nclass Shader_" + sname + " : public ShaderCell {\n")
 | 
			
		||||
    fd.write("\n\tstatic struct VertexUniforms[] = {\n")
 | 
			
		||||
 | 
			
		||||
    offset = 0
 | 
			
		||||
    for i in range(0, len(vp_uniforms)):
 | 
			
		||||
 | 
			
		||||
        fd.write('\t\t{ "%s", %d, %d },\n' % (vp_uniforms[i], offset, vp_uniform_sizes[i]))
 | 
			
		||||
        offset = offset + vp_uniform_sizes[i]
 | 
			
		||||
    fd.write("\t};\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("public:\n\n")
 | 
			
		||||
 | 
			
		||||
    fd.write("\tenum {\n")
 | 
			
		||||
 | 
			
		||||
    for i in range(0, len(vp_uniforms)):
 | 
			
		||||
 | 
			
		||||
        fd.write('\t\tVP_%s,\n' % vp_uniforms[i].upper())
 | 
			
		||||
 | 
			
		||||
    fd.write("\t};\n")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import glob
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
def can_build(platform):
 | 
			
		||||
    # should probably change this to only be true on iOS and Android
 | 
			
		||||
    return True
 | 
			
		||||
    return False
 | 
			
		||||
 | 
			
		||||
def configure(env):
 | 
			
		||||
    pass
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,4 +31,5 @@
 | 
			
		|||
#include <alloca.h>
 | 
			
		||||
 | 
			
		||||
#define GLES3_INCLUDE_H "glad/glad.h"
 | 
			
		||||
#define GLES2_INCLUDE_H "glad/glad.h"
 | 
			
		||||
#define PTHREAD_RENAME_SELF
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,3 +33,4 @@
 | 
			
		|||
//#include <alloca.h>
 | 
			
		||||
//#endif
 | 
			
		||||
#define GLES3_INCLUDE_H "glad/glad.h"
 | 
			
		||||
#define GLES2_INCLUDE_H "glad/glad.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -146,20 +146,38 @@ Error ContextGL_X11::initialize() {
 | 
			
		|||
	int (*oldHandler)(Display *, XErrorEvent *) =
 | 
			
		||||
			XSetErrorHandler(&ctxErrorHandler);
 | 
			
		||||
 | 
			
		||||
	if (!opengl_3_context) {
 | 
			
		||||
		//oldstyle context:
 | 
			
		||||
		p->glx_context = glXCreateContext(x11_display, vi, 0, GL_TRUE);
 | 
			
		||||
	} else {
 | 
			
		||||
		static int context_attribs[] = {
 | 
			
		||||
			GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
 | 
			
		||||
			GLX_CONTEXT_MINOR_VERSION_ARB, 3,
 | 
			
		||||
			GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB /*|GLX_CONTEXT_DEBUG_BIT_ARB*/,
 | 
			
		||||
			None
 | 
			
		||||
		};
 | 
			
		||||
	switch (context_type) {
 | 
			
		||||
		case GLES_2_0_COMPATIBLE:
 | 
			
		||||
		case OLDSTYLE: {
 | 
			
		||||
			p->glx_context = glXCreateContext(x11_display, vi, 0, GL_TRUE);
 | 
			
		||||
		} break;
 | 
			
		||||
		/*
 | 
			
		||||
		case ContextType::GLES_2_0_COMPATIBLE: {
 | 
			
		||||
 | 
			
		||||
		p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs);
 | 
			
		||||
		ERR_EXPLAIN("Could not obtain an OpenGL 3.3 context!");
 | 
			
		||||
		ERR_FAIL_COND_V(ctxErrorOccurred || !p->glx_context, ERR_UNCONFIGURED);
 | 
			
		||||
			static int context_attribs[] = {
 | 
			
		||||
				GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
 | 
			
		||||
				GLX_CONTEXT_MINOR_VERSION_ARB, 0,
 | 
			
		||||
				None
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs);
 | 
			
		||||
			ERR_EXPLAIN("Could not obtain an OpenGL 3.0 context!");
 | 
			
		||||
			ERR_FAIL_COND_V(!p->glx_context, ERR_UNCONFIGURED);
 | 
			
		||||
		} break;
 | 
			
		||||
		*/
 | 
			
		||||
		case GLES_3_0_COMPATIBLE: {
 | 
			
		||||
 | 
			
		||||
			static int context_attribs[] = {
 | 
			
		||||
				GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
 | 
			
		||||
				GLX_CONTEXT_MINOR_VERSION_ARB, 3,
 | 
			
		||||
				GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB /*|GLX_CONTEXT_DEBUG_BIT_ARB*/,
 | 
			
		||||
				None
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs);
 | 
			
		||||
			ERR_EXPLAIN("Could not obtain an OpenGL 3.3 context!");
 | 
			
		||||
			ERR_FAIL_COND_V(ctxErrorOccurred || !p->glx_context, ERR_UNCONFIGURED);
 | 
			
		||||
		} break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	XSync(x11_display, False);
 | 
			
		||||
| 
						 | 
				
			
			@ -229,13 +247,13 @@ bool ContextGL_X11::is_using_vsync() const {
 | 
			
		|||
	return use_vsync;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ContextGL_X11::ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, bool p_opengl_3_context) :
 | 
			
		||||
ContextGL_X11::ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, ContextType p_context_type) :
 | 
			
		||||
		x11_window(p_x11_window) {
 | 
			
		||||
 | 
			
		||||
	default_video_mode = p_default_video_mode;
 | 
			
		||||
	x11_display = p_x11_display;
 | 
			
		||||
 | 
			
		||||
	opengl_3_context = p_opengl_3_context;
 | 
			
		||||
	context_type = p_context_type;
 | 
			
		||||
 | 
			
		||||
	double_buffer = false;
 | 
			
		||||
	direct_render = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,14 @@ struct ContextGL_X11_Private;
 | 
			
		|||
 | 
			
		||||
class ContextGL_X11 : public ContextGL {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	enum ContextType {
 | 
			
		||||
		OLDSTYLE,
 | 
			
		||||
		GLES_2_0_COMPATIBLE,
 | 
			
		||||
		GLES_3_0_COMPATIBLE
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	ContextGL_X11_Private *p;
 | 
			
		||||
	OS::VideoMode default_video_mode;
 | 
			
		||||
	//::Colormap x11_colormap;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,8 +62,8 @@ class ContextGL_X11 : public ContextGL {
 | 
			
		|||
	bool double_buffer;
 | 
			
		||||
	bool direct_render;
 | 
			
		||||
	int glx_minor, glx_major;
 | 
			
		||||
	bool opengl_3_context;
 | 
			
		||||
	bool use_vsync;
 | 
			
		||||
	ContextType context_type;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	virtual void release_current();
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +77,7 @@ public:
 | 
			
		|||
	virtual void set_use_vsync(bool p_use);
 | 
			
		||||
	virtual bool is_using_vsync() const;
 | 
			
		||||
 | 
			
		||||
	ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, bool p_opengl_3_context);
 | 
			
		||||
	ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, ContextType p_context_type);
 | 
			
		||||
	~ContextGL_X11();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@
 | 
			
		|||
/*************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "os_x11.h"
 | 
			
		||||
#include "drivers/gles2/rasterizer_gles2.h"
 | 
			
		||||
#include "drivers/gles3/rasterizer_gles3.h"
 | 
			
		||||
#include "errno.h"
 | 
			
		||||
#include "key_mapping_x11.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +82,11 @@ int OS_X11::get_video_driver_count() const {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
const char *OS_X11::get_video_driver_name(int p_driver) const {
 | 
			
		||||
	String driver_name = GLOBAL_GET("rendering/quality/driver/driver_name");
 | 
			
		||||
 | 
			
		||||
	if (driver_name == "GLES2") {
 | 
			
		||||
		return "GLES2";
 | 
			
		||||
	}
 | 
			
		||||
	return "GLES3";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -283,12 +289,29 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
 | 
			
		|||
//print_line("def videomode "+itos(current_videomode.width)+","+itos(current_videomode.height));
 | 
			
		||||
#if defined(OPENGL_ENABLED)
 | 
			
		||||
 | 
			
		||||
	context_gl = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, true));
 | 
			
		||||
	String setting_name = "rendering/quality/driver/driver_name";
 | 
			
		||||
	ProjectSettings::get_singleton()->set_custom_property_info(setting_name, PropertyInfo(Variant::STRING, setting_name, PROPERTY_HINT_ENUM, "GLES3,GLES2"));
 | 
			
		||||
	String video_driver_name = GLOBAL_DEF("rendering/quality/driver/driver_name", "GLES3");
 | 
			
		||||
 | 
			
		||||
	ContextGL_X11::ContextType opengl_api_type = ContextGL_X11::GLES_3_0_COMPATIBLE;
 | 
			
		||||
 | 
			
		||||
	if (video_driver_name == "GLES2") {
 | 
			
		||||
		opengl_api_type = ContextGL_X11::GLES_2_0_COMPATIBLE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	context_gl = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, opengl_api_type));
 | 
			
		||||
	context_gl->initialize();
 | 
			
		||||
 | 
			
		||||
	RasterizerGLES3::register_config();
 | 
			
		||||
 | 
			
		||||
	RasterizerGLES3::make_current();
 | 
			
		||||
	switch (opengl_api_type) {
 | 
			
		||||
		case ContextGL_X11::GLES_2_0_COMPATIBLE: {
 | 
			
		||||
			RasterizerGLES2::register_config();
 | 
			
		||||
			RasterizerGLES2::make_current();
 | 
			
		||||
		} break;
 | 
			
		||||
		case ContextGL_X11::GLES_3_0_COMPATIBLE: {
 | 
			
		||||
			RasterizerGLES3::register_config();
 | 
			
		||||
			RasterizerGLES3::make_current();
 | 
			
		||||
		} break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	context_gl->set_use_vsync(current_videomode.use_vsync);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,3 +37,4 @@
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#define GLES3_INCLUDE_H "glad/glad.h"
 | 
			
		||||
#define GLES2_INCLUDE_H "glad/glad.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue