add GLES 2 renderer for 2D
This commit adds a new rendering backend, GLES2, and adds a project setting to enable it. Currently this backend can only be used on the X11 platform, but integrating into other platforms is planned.
This commit is contained in:
parent
7f3024d343
commit
eac4c984df
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:
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.drivers_sources,"*.cpp")
|
||||
|
||||
SConscript("shaders/SCsub")
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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() {
|
||||
}
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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');
|
|
@ -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() {
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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…
Reference in New Issue