diff options
Diffstat (limited to 'drivers')
45 files changed, 2332 insertions, 7428 deletions
diff --git a/drivers/SCsub b/drivers/SCsub index b50c5afbf..46334468b 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -7,6 +7,7 @@ Export('env') SConscript('unix/SCsub');
SConscript('alsa/SCsub');
+SConscript('pulseaudio/SCsub');
SConscript('windows/SCsub');
SConscript('gles2/SCsub');
SConscript('gles1/SCsub');
@@ -82,7 +83,7 @@ if len(list) > 0: drivers_base=[]
env.add_source_files(drivers_base,"*.cpp")
-lib_list.insert(0, env.Library("drivers", drivers_base, LIBSUFFIX=env['platform_libsuffix']))
+lib_list.insert(0, env.Library("drivers", drivers_base))
env.Prepend(LIBS=lib_list)
diff --git a/drivers/builtin_openssl2/openssl/md5.h b/drivers/builtin_openssl2/openssl/md5.h index 8f392f0ec..765be9433 100644 --- a/drivers/builtin_openssl2/openssl/md5.h +++ b/drivers/builtin_openssl2/openssl/md5.h @@ -105,9 +105,9 @@ typedef struct MD5state_st unsigned int num; } MD5_CTX; -#ifdef OPENSSL_FIPS +//#ifdef OPENSSL_FIPS int private_MD5_Init(MD5_CTX *c); -#endif +//#endif //#define MD5_Init _SSL_MD5_Init #define MD5_Final _SSL_MD5_Final diff --git a/drivers/chibi/cp_loader_s3m.cpp b/drivers/chibi/cp_loader_s3m.cpp index c5f0830ae..8b9871463 100644 --- a/drivers/chibi/cp_loader_s3m.cpp +++ b/drivers/chibi/cp_loader_s3m.cpp @@ -162,7 +162,7 @@ CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) { p_sample->set_default_volume(def_volume); p_sample->set_name(name); - char scrs[4]; + char scrs[5]; file->get_byte_array((uint8_t*)scrs,4); scrs[4]=0; diff --git a/drivers/gl_context/context_gl.cpp b/drivers/gl_context/context_gl.cpp index 77a94f933..82195cc6f 100644 --- a/drivers/gl_context/context_gl.cpp +++ b/drivers/gl_context/context_gl.cpp @@ -12,7 +12,7 @@ #include "context_gl.h" -#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED) || defined(GLES1_ENABLED) +#if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) diff --git a/drivers/gl_context/context_gl.h b/drivers/gl_context/context_gl.h index 4c3d863e8..392f8341a 100644 --- a/drivers/gl_context/context_gl.h +++ b/drivers/gl_context/context_gl.h @@ -29,7 +29,7 @@ #ifndef CONTEXT_GL_H #define CONTEXT_GL_H -#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED) || defined(GLES1_ENABLED) +#if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) #include "typedefs.h" diff --git a/drivers/gles1/rasterizer_gles1.cpp b/drivers/gles1/rasterizer_gles1.cpp deleted file mode 100644 index 02de063bd..000000000 --- a/drivers/gles1/rasterizer_gles1.cpp +++ /dev/null @@ -1,5957 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles1.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* 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. */ -/*************************************************************************/ -#ifdef GLES1_ENABLED - -#include "rasterizer_gles1.h" -#include "os/os.h" -#include "globals.h" -#include <stdio.h> -#include "drivers/gl_context/context_gl.h" -#include "servers/visual/shader_language.h" -#include "servers/visual/particle_system_sw.h" -#include "gl_context/context_gl.h" -#include <string.h> - -_FORCE_INLINE_ static void _gl_load_transform(const Transform& tr) { - - 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 - }; - - glLoadMatrixf(matrix); -}; - - -_FORCE_INLINE_ static void _gl_mult_transform(const Transform& tr) { - - 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 - }; - - glMultMatrixf(matrix); -}; - -_FORCE_INLINE_ static void _gl_mult_transform(const Matrix32& tr) { - - 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 - }; - - glMultMatrixf(matrix); -}; - - -RasterizerGLES1::FX::FX() { - - bgcolor_active=false; - bgcolor=Color(0,1,0,1); - - skybox_active=false; - - glow_active=false; - glow_passes=4; - glow_attenuation=0.7; - glow_bloom=0.0; - - antialias_active=true; - antialias_tolerance=15; - - ssao_active=true; - ssao_attenuation=0.7; - ssao_radius=0.18; - ssao_max_distance=1.0; - ssao_range_min=0.25; - ssao_range_max=0.48; - ssao_only=false; - - - fog_active=false; - fog_near=5; - fog_far=100; - fog_attenuation=1.0; - fog_color_near=Color(1,1,1,1); - fog_color_far=Color(1,1,1,1); - fog_bg=false; - - toon_active=false; - toon_treshold=0.4; - toon_soft=0.001; - - edge_active=false; - edge_color=Color(0,0,0,1); - edge_size=1.0; - -} - -static const GLenum prim_type[]={GL_POINTS,GL_LINES,GL_TRIANGLES,GL_TRIANGLE_FAN}; - -static void _draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color* p_colors, const Vector3 *p_uvs,const Plane *p_tangents=NULL,int p_instanced=1) { - - ERR_FAIL_COND(!p_vertices); - ERR_FAIL_COND(p_points <1 || p_points>4); - - GLenum type = prim_type[p_points - 1]; - - - //if (!p_colors) { - // glColor4f(1, 1, 1, 1); - //}; - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)p_vertices); - - if (p_normals) { - - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, (GLvoid*)p_normals); - }; - - if (p_colors) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4,GL_FLOAT, 0, p_colors); - }; - - if (p_uvs) { - - glClientActiveTexture(GL_TEXTURE0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(3, GL_FLOAT, 0, p_uvs); - }; - - glDrawArrays( type, 0, p_points); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -}; - -/* TEXTURE API */ -#define _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB -#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC -#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE -#define _EXT_ETC1_RGB8_OES 0x8D64 - -/* TEXTURE API */ - -Image RasterizerGLES1::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) { - - r_has_alpha_cache=false; - r_compressed=false; - Image image=p_image; - - switch(p_format) { - - case Image::FORMAT_GRAYSCALE: { - r_gl_components=1; - r_gl_format=GL_LUMINANCE; - - } break; - case Image::FORMAT_INTENSITY: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGBA); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - } break; - case Image::FORMAT_GRAYSCALE_ALPHA: { - - //image.convert(Image::FORMAT_RGBA); - r_gl_components=2; - r_gl_format=GL_LUMINANCE_ALPHA; - r_has_alpha_cache=true; - } break; - - case Image::FORMAT_INDEXED: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGB); - r_gl_components=3; - r_gl_format=GL_RGB; - - } break; - - case Image::FORMAT_INDEXED_ALPHA: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGBA); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - - } break; - case Image::FORMAT_RGB: { - - r_gl_components=3; - r_gl_format=GL_RGB; - } break; - case Image::FORMAT_RGBA: { - - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - } break; - case Image::FORMAT_BC1: { - - r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; - r_compressed=true; - - } break; - case Image::FORMAT_BC2: { - r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; - r_has_alpha_cache=true; - r_compressed=true; - - } break; - case Image::FORMAT_BC3: { - - r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; - r_has_alpha_cache=true; - r_compressed=true; - - } break; - case Image::FORMAT_BC4: { - - r_gl_format=_EXT_COMPRESSED_RED_RGTC1; - r_gl_components=1; //doesn't matter much - r_compressed=true; - - } break; - case Image::FORMAT_BC5: { - - r_gl_format=_EXT_COMPRESSED_RG_RGTC2; - r_gl_components=1; //doesn't matter much - r_compressed=true; - } break; - case Image::FORMAT_PVRTC2: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC2"); - - } else { - - r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC2"); - } - - } break; - case Image::FORMAT_PVRTC2_ALPHA: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC2A"); - - } else { - - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC2A"); - } - - } break; - case Image::FORMAT_PVRTC4: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC4"); - } else { - - r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC4"); - } - - } break; - case Image::FORMAT_PVRTC4_ALPHA: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC4A"); - - } else { - - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC4A"); - } - - } break; - case Image::FORMAT_ETC: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - } else { - - r_gl_format=_EXT_ETC1_RGB8_OES; - r_gl_components=1; //doesn't matter much - r_compressed=true; - } - - } break; - case Image::FORMAT_YUV_422: - case Image::FORMAT_YUV_444: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGB); - r_gl_format=GL_RGB; - r_gl_components=3; - - } break; - - default: { - - ERR_FAIL_V(Image()); - } - } - - return image; -} - - -RID RasterizerGLES1::texture_create() { - - Texture *texture = memnew(Texture); - ERR_FAIL_COND_V(!texture,RID()); - glGenTextures(1, &texture->tex_id); - texture->active=false; - texture->total_data_size=0; - - return texture_owner.make_rid( texture ); - -} - -void RasterizerGLES1::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { - - bool has_alpha_cache; - int components; - GLenum format; - bool compressed; - - int po2_width = nearest_power_of_2(p_width); - int po2_height = nearest_power_of_2(p_height); - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - texture->width=p_width; - texture->height=p_height; - texture->format=p_format; - texture->flags=p_flags; - texture->target = /*(p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP :*/ GL_TEXTURE_2D; - - bool scale_textures = (!npo2_textures_available || p_format&VS::TEXTURE_FLAG_MIPMAPS); - - - if (scale_textures) { - texture->alloc_width = po2_width; - texture->alloc_height = po2_height; - } else { - - texture->alloc_width = texture->width; - texture->alloc_height = texture->height; - }; - - _get_gl_image_and_format(Image(),texture->format,texture->flags,format,components,has_alpha_cache,compressed); - - texture->gl_components_cache=components; - texture->gl_format_cache=format; - texture->format_has_alpha=has_alpha_cache; - texture->compressed=compressed; - texture->data_size=0; - - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - - - - if (compressed) { - - glTexParameteri( texture->target, GL_GENERATE_MIPMAP, GL_FALSE ); - } else { - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) { - glTexParameteri( texture->target, GL_GENERATE_MIPMAP, GL_TRUE ); - } else { - glTexParameteri( texture->target, GL_GENERATE_MIPMAP, GL_FALSE ); - } - - } - - - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - - if (texture->flags&VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // raw Filtering - - } - bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); - - if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT) { - - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } else { - - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - } - - texture->active=true; -} - -void RasterizerGLES1::texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->format != p_image.get_format() ); - - int components; - GLenum format; - bool alpha; - bool compressed; - - if (keep_copies && !(texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && !(use_reload_hooks && texture->reloader)) { - texture->image[p_cube_side]=p_image; - } - - - Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,components,alpha,compressed); - if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) { - - img.resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); - }; - - - GLenum blit_target = /*(texture->target == GL_TEXTURE_CUBE_MAP)?_cube_side_enum[p_cube_side]:*/GL_TEXTURE_2D; - - texture->data_size=img.get_data().size(); - DVector<uint8_t>::Read read = img.get_data().read(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - int mipmaps=(texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1; - - int w=img.get_width(); - int h=img.get_height(); - - int tsize=0; - for(int i=0;i<mipmaps;i++) { - - int size,ofs; - img.get_mipmap_offset_and_size(i,ofs,size); - - if (texture->compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] ); - - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -// glTexImage2D(blit_target, i, format==GL_RGB?GL_RGB8:format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); - glTexImage2D(blit_target, i, format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); - //glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] ); - } - tsize+=size; - - w = MAX(1,w>>1); - h = MAX(1,h>>1); - - } - - _rinfo.texture_mem-=texture->total_data_size; - texture->total_data_size=tsize; - _rinfo.texture_mem+=texture->total_data_size; - - printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem); - - - if (mipmaps==1 && texture->flags&VS::TEXTURE_FLAG_MIPMAPS) { - glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); - - } else { - glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE ); - - } - - if (mipmaps>1) { - - //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmaps-1 ); - assumed to have all, always - } - - //texture_set_flags(p_texture,texture->flags); - - -} - -Image RasterizerGLES1::texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image()); - ERR_FAIL_COND_V(!texture->active,Image()); - - return texture->image[p_cube_side]; -#if 0 - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image()); - ERR_FAIL_COND_V(!texture->active,Image()); - ERR_FAIL_COND_V(texture->data_size==0,Image()); - - DVector<uint8_t> data; - GLenum format,type=GL_UNSIGNED_BYTE; - Image::Format fmt; - int pixelsize=0; - int pixelshift=0; - int minw=1,minh=1; - bool compressed=false; - - fmt=texture->format; - - switch(texture->format) { - - case Image::FORMAT_GRAYSCALE: { - - format=GL_LUMINANCE; - type=GL_UNSIGNED_BYTE; - data.resize(texture->alloc_width*texture->alloc_height); - pixelsize=1; - - } break; - case Image::FORMAT_INTENSITY: { - return Image(); - } break; - case Image::FORMAT_GRAYSCALE_ALPHA: { - - format=GL_LUMINANCE_ALPHA; - type=GL_UNSIGNED_BYTE; - pixelsize=2; - - } break; - case Image::FORMAT_RGB: { - format=GL_RGB; - type=GL_UNSIGNED_BYTE; - pixelsize=3; - } break; - case Image::FORMAT_RGBA: { - - format=GL_RGBA; - type=GL_UNSIGNED_BYTE; - pixelsize=4; - } break; - case Image::FORMAT_INDEXED: { - - format=GL_RGB; - type=GL_UNSIGNED_BYTE; - fmt=Image::FORMAT_RGB; - pixelsize=3; - } break; - case Image::FORMAT_INDEXED_ALPHA: { - - format=GL_RGBA; - type=GL_UNSIGNED_BYTE; - fmt=Image::FORMAT_RGBA; - pixelsize=4; - - } break; - case Image::FORMAT_BC1: { - - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - compressed=true; - pixelshift=1; - minw=minh=4; - - } break; - case Image::FORMAT_BC2: { - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - compressed=true; - minw=minh=4; - - } break; - case Image::FORMAT_BC3: { - - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - compressed=true; - minw=minh=4; - - } break; - case Image::FORMAT_BC4: { - - format=GL_COMPRESSED_RED_RGTC1; - pixelsize=1; //doesn't matter much - compressed=true; - pixelshift=1; - minw=minh=4; - - } break; - case Image::FORMAT_BC5: { - - format=GL_COMPRESSED_RG_RGTC2; - pixelsize=1; //doesn't matter much - compressed=true; - minw=minh=4; - - } break; - - default:{} - } - - data.resize(texture->data_size); - DVector<uint8_t>::Write wb = data.write(); - - glActiveTexture(GL_TEXTURE0); - int ofs=0; - glBindTexture(texture->target,texture->tex_id); - - int w=texture->alloc_width; - int h=texture->alloc_height; - for(int i=0;i<texture->mipmaps+1;i++) { - - if (compressed) { - - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetCompressedTexImage(texture->target,i,&wb[ofs]); - - } else { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glGetTexImage(texture->target,i,format,type,&wb[ofs]); - } - - int size = (w*h*pixelsize)>>pixelshift; - ofs+=size; - - w=MAX(minw,w>>1); - h=MAX(minh,h>>1); - - } - - - wb=DVector<uint8_t>::Write(); - - Image img(texture->alloc_width,texture->alloc_height,texture->mipmaps,fmt,data); - - if (texture->format<Image::FORMAT_INDEXED && (texture->alloc_width!=texture->width || texture->alloc_height!=texture->height)) - img.resize(texture->width,texture->height); - - return img; -#endif -} - -void RasterizerGLES1::texture_set_flags(RID p_texture,uint32_t p_flags) { - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; - texture->flags=p_flags|cube; // can't remove a cube from being a cube - - bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); - - if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT) { - - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } else { - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - - } - - - if (texture->flags&VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // nearest - } -} -uint32_t RasterizerGLES1::texture_get_flags(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->flags; - -} -Image::Format RasterizerGLES1::texture_get_format(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image::FORMAT_GRAYSCALE); - - return texture->format; -} -uint32_t RasterizerGLES1::texture_get_width(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->width; -} -uint32_t RasterizerGLES1::texture_get_height(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->height; -} - -bool RasterizerGLES1::texture_has_alpha(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return false; - -} - -void RasterizerGLES1::texture_set_size_override(RID p_texture,int p_width, int p_height) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - - ERR_FAIL_COND(p_width<=0 || p_width>4096); - ERR_FAIL_COND(p_height<=0 || p_height>4096); - //real texture size is in alloc width and height - texture->width=p_width; - texture->height=p_height; - -} - -void RasterizerGLES1::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - - texture->reloader=p_owner; - texture->reloader_func=p_function; - if (use_reload_hooks && p_owner && keep_copies) { - - for(int i=0;i<6;i++) - texture->image[i]=Image(); - } - - -} - -/* SHADER API */ - -/* SHADER API */ - -RID RasterizerGLES1::shader_create(VS::ShaderMode p_mode) { - - Shader *shader = memnew( Shader ); - shader->mode=p_mode; - shader->valid=false; - shader->has_alpha=false; - shader->fragment_line=0; - shader->vertex_line=0; - shader->light_line=0; - RID rid = shader_owner.make_rid(shader); - shader_set_mode(rid,p_mode); -// _shader_make_dirty(shader); - - return rid; - -} - - - -void RasterizerGLES1::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { - - ERR_FAIL_INDEX(p_mode,3); - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); -// if (shader->custom_code_id && p_mode==shader->mode) -// return; - - shader->mode=p_mode; - -} -VS::ShaderMode RasterizerGLES1::shader_get_mode(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,VS::SHADER_MATERIAL); - return shader->mode; -} - - - -void RasterizerGLES1::shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs,int p_fragment_ofs,int p_light_ofs) { - - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - -#ifdef DEBUG_ENABLED - if (shader->vertex_code==p_vertex && shader->fragment_code==p_fragment && shader->light_code==p_light) - return; -#endif - shader->fragment_code=p_fragment; - shader->vertex_code=p_vertex; - shader->light_code=p_light; - shader->fragment_line=p_fragment_ofs; - shader->vertex_line=p_vertex_ofs; - shader->light_line=p_light_ofs; - -} - -String RasterizerGLES1::shader_get_vertex_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->vertex_code; - -} - -String RasterizerGLES1::shader_get_fragment_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->fragment_code; - -} - -String RasterizerGLES1::shader_get_light_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->light_code; - -} - -void RasterizerGLES1::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); -#if 0 - - if (shader->dirty_list.in_list()) - _update_shader(shader); // ok should be not anymore dirty - - - Map<int,StringName> order; - - - for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { - - - order[E->get().order]=E->key(); - } - - - for(Map<int,StringName>::Element *E=order.front();E;E=E->next()) { - - PropertyInfo pi; - ShaderLanguage::Uniform &u=shader->uniforms[E->get()]; - pi.name=E->get(); - switch(u.type) { - - case ShaderLanguage::TYPE_VOID: - case ShaderLanguage::TYPE_BOOL: - case ShaderLanguage::TYPE_FLOAT: - case ShaderLanguage::TYPE_VEC2: - case ShaderLanguage::TYPE_VEC3: - case ShaderLanguage::TYPE_MAT3: - case ShaderLanguage::TYPE_MAT4: - case ShaderLanguage::TYPE_VEC4: - pi.type=u.default_value.get_type(); - break; - case ShaderLanguage::TYPE_TEXTURE: - pi.type=Variant::_RID; - pi.hint=PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string="Texture"; - break; - case ShaderLanguage::TYPE_CUBEMAP: - pi.type=Variant::_RID; - pi.hint=PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string="Texture"; - break; - }; - - p_param_list->push_back(pi); - - } -#endif - -} - -/* COMMON MATERIAL API */ - - -RID RasterizerGLES1::material_create() { - - return material_owner.make_rid( memnew( Material ) ); -} - -void RasterizerGLES1::material_set_shader(RID p_material, RID p_shader) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->shader=p_shader; - -} - -RID RasterizerGLES1::material_get_shader(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,RID()); - return material->shader; -} - -#if 0 - -void RasterizerGLES1::_material_check_alpha(Material *p_material) { - - p_material->has_alpha=false; - Color diffuse=p_material->parameters[VS::FIXED_MATERIAL_PARAM_DIFFUSE]; - if (diffuse.a<0.98) { - - p_material->has_alpha=true; - return; - } - - if (p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE].is_valid()) { - - Texture *tex = texture_owner.get(p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE]); - if (!tex) - return; - if (tex->has_alpha) { - - p_material->has_alpha=true; - return; - } - } -} - -#endif -void RasterizerGLES1::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type()==Variant::NIL) - material->shader_params.erase(p_param); - else - material->shader_params[p_param]=p_value; -} -Variant RasterizerGLES1::material_get_param(RID p_material, const StringName& p_param) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,Variant()); - - if (material->shader_params.has(p_param)) - return material->shader_params[p_param]; - else - return Variant(); -} - - -void RasterizerGLES1::material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - ERR_FAIL_INDEX(p_flag,VS::MATERIAL_FLAG_MAX); - material->flags[p_flag]=p_enabled; - -} -bool RasterizerGLES1::material_get_flag(RID p_material,VS::MaterialFlag p_flag) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,false); - ERR_FAIL_INDEX_V(p_flag,VS::MATERIAL_FLAG_MAX,false); - return material->flags[p_flag]; - - -} - -void RasterizerGLES1::material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->depth_draw_mode=p_mode; -} - -VS::MaterialDepthDrawMode RasterizerGLES1::material_get_depth_draw_mode(RID p_material) const{ - - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_DEPTH_DRAW_ALWAYS); - return material->depth_draw_mode; -} - - -void RasterizerGLES1::material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->blend_mode=p_mode; - -} -VS::MaterialBlendMode RasterizerGLES1::material_get_blend_mode(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_BLEND_MODE_ADD); - return material->blend_mode; -} - -void RasterizerGLES1::material_set_line_width(RID p_material,float p_line_width) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->line_width=p_line_width; - -} -float RasterizerGLES1::material_get_line_width(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,0); - - return material->line_width; -} - -/* FIXED MATERIAL */ - - -RID RasterizerGLES1::fixed_material_create() { - - return material_create(); -} - -void RasterizerGLES1::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_flag, 3); - m->fixed_flags[p_flag]=p_enabled; -} - -bool RasterizerGLES1::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m,false); - ERR_FAIL_INDEX_V(p_flag,VS::FIXED_MATERIAL_FLAG_MAX, false); - return m->fixed_flags[p_flag]; -} - -void RasterizerGLES1::fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX); - - m->parameters[p_parameter] = p_value; - -} - -Variant RasterizerGLES1::fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, Variant()); - ERR_FAIL_INDEX_V(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX, Variant()); - - return m->parameters[p_parameter]; -} - -void RasterizerGLES1::fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX); - - m->textures[p_parameter] = p_texture; - -} -RID RasterizerGLES1::fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, RID()); - ERR_FAIL_INDEX_V(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX, Variant()); - - return m->textures[p_parameter]; -} - - -void RasterizerGLES1::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX); - ERR_FAIL_INDEX(p_mode,4); - - m->texcoord_mode[p_parameter] = p_mode; -} - -VS::FixedMaterialTexCoordMode RasterizerGLES1::fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, VS::FIXED_MATERIAL_TEXCOORD_UV); - ERR_FAIL_INDEX_V(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX, VS::FIXED_MATERIAL_TEXCOORD_UV); - - return m->texcoord_mode[p_parameter]; // for now -} - -void RasterizerGLES1::fixed_material_set_uv_transform(RID p_material,const Transform& p_transform) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - - m->uv_transform = p_transform; -} - -Transform RasterizerGLES1::fixed_material_get_uv_transform(RID p_material) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, Transform()); - - return m->uv_transform; -} - -void RasterizerGLES1::fixed_material_set_point_size(RID p_material,float p_size) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - m->point_size=p_size; - -} -float RasterizerGLES1::fixed_material_get_point_size(RID p_material) const { - - const Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, 0); - return m->point_size; -} - - -/* MESH API */ - - -RID RasterizerGLES1::mesh_create() { - - - return mesh_owner.make_rid( memnew( Mesh ) ); -} - - - -void RasterizerGLES1::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX ); - ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX); - - uint32_t format=0; - - // validation - int index_array_len=0; - int array_len=0; - - for(int i=0;i<p_arrays.size();i++) { - - if (p_arrays[i].get_type()==Variant::NIL) - continue; - - format|=(1<<i); - - if (i==VS::ARRAY_VERTEX) { - - array_len=Vector3Array(p_arrays[i]).size(); - ERR_FAIL_COND(array_len==0); - } else if (i==VS::ARRAY_INDEX) { - - index_array_len=IntArray(p_arrays[i]).size(); - } - } - - ERR_FAIL_COND((format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory - - - Surface *surface = memnew( Surface ); - ERR_FAIL_COND( !surface ); - - bool use_VBO=true; //glGenBuffersARB!=NULL; // TODO detect if it's in there - if (format&VS::ARRAY_FORMAT_WEIGHTS || mesh->morph_target_count>0) { - - use_VBO=false; - } - - surface->packed=pack_arrays && use_VBO; - - int total_elem_size=0; - - for (int i=0;i<VS::ARRAY_MAX;i++) { - - - Surface::ArrayData&ad=surface->array[i]; - ad.size=0; - ad.ofs=0; - int elem_size=0; - int elem_count=0; - bool valid_local=true; - GLenum datatype; - bool normalize=false; - bool bind=false; - - if (!(format&(1<<i))) // no array - continue; - - - switch(i) { - - case VS::ARRAY_VERTEX: { - - if (surface->packed) { - elem_size=3*sizeof(int16_t); // vertex - datatype=GL_SHORT; - normalize=true; - - } else { - elem_size=3*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=3; - - } break; - case VS::ARRAY_NORMAL: { - - if (surface->packed) { - elem_size=3*sizeof(int8_t); // vertex - datatype=GL_BYTE; - normalize=true; - } else { - elem_size=3*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=3; - } break; - case VS::ARRAY_TANGENT: { - if (surface->packed) { - elem_size=4*sizeof(int8_t); // vertex - datatype=GL_BYTE; - normalize=true; - } else { - elem_size=4*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=4; - - } break; - case VS::ARRAY_COLOR: { - - elem_size=4*sizeof(uint8_t); /* RGBA */ - datatype=GL_UNSIGNED_BYTE; - elem_count=4; - bind=true; - normalize=true; - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - if (surface->packed) { - elem_size=2*sizeof(int16_t); // vertex - datatype=GL_SHORT; - normalize=true; - } else { - elem_size=2*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=2; - - } break; - case VS::ARRAY_WEIGHTS: { - - elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLfloat); - elem_count=VS::ARRAY_WEIGHTS_SIZE; - valid_local=false; - datatype=GL_FLOAT; - - } break; - case VS::ARRAY_BONES: { - - elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLuint); - elem_count=VS::ARRAY_WEIGHTS_SIZE; - valid_local=false; - datatype=GL_FLOAT; - - - } break; - case VS::ARRAY_INDEX: { - - if (index_array_len<=0) { - ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); - break; - } - /* determine wether using 16 or 32 bits indices */ - elem_size=2; - datatype=GL_UNSIGNED_SHORT; - -/* - if (use_VBO) { - - glGenBuffers(1,&surface->index_id); - ERR_FAIL_COND(surface->index_id==0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_len*elem_size,NULL,GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - } else { - surface->index_array_local = (uint8_t*)memalloc(index_array_len*elem_size); - }; -*/ - surface->index_array_len=index_array_len; // only way it can exist - ad.ofs=0; - ad.size=elem_size; - - - continue; - } break; - default: { - ERR_FAIL( ); - } - } - - ad.ofs=total_elem_size; - ad.size=elem_size; - ad.datatype=datatype; - ad.normalize=normalize; - ad.bind=bind; - ad.count=elem_count; - total_elem_size+=elem_size; - if (valid_local) { - surface->local_stride+=elem_size; - surface->morph_format|=(1<<i); - } - - - } - - surface->stride=total_elem_size; - surface->array_len=array_len; - surface->format=format; - surface->primitive=p_primitive; - surface->configured_format=0; - if (keep_copies) { - surface->data=p_arrays; - surface->morph_data=p_blend_shapes; - } - - uint8_t *array_ptr=NULL; - uint8_t *index_array_ptr=NULL; - DVector<uint8_t> array_pre_vbo; - DVector<uint8_t>::Write vaw; - DVector<uint8_t> index_array_pre_vbo; - DVector<uint8_t>::Write iaw; - - /* create pointers */ - if (use_VBO) { - - array_pre_vbo.resize(surface->array_len*surface->stride); - vaw = array_pre_vbo.write(); - array_ptr=vaw.ptr(); - - if (surface->index_array_len) { - - index_array_pre_vbo.resize(surface->index_array_len*surface->array[VS::ARRAY_INDEX].size); - iaw = index_array_pre_vbo.write(); - index_array_ptr=iaw.ptr(); - } - } else { - - surface->array_local = (uint8_t*)memalloc(surface->array_len*surface->stride); - array_ptr=(uint8_t*)surface->array_local; - if (surface->index_array_len) { - surface->index_array_local = (uint8_t*)memalloc(index_array_len*surface->array[VS::ARRAY_INDEX].size); - index_array_ptr=(uint8_t*)surface->index_array_local; - } - } - - - - _surface_set_arrays(surface,array_ptr,index_array_ptr,p_arrays,true); - - - /* create buffers!! */ - if (use_VBO) { - glGenBuffers(1,&surface->vertex_id); - ERR_FAIL_COND(surface->vertex_id==0); - glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - glBufferData(GL_ARRAY_BUFFER,surface->array_len*surface->stride,array_ptr,GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER,0); //unbind - if (surface->index_array_len) { - - glGenBuffers(1,&surface->index_id); - ERR_FAIL_COND(surface->index_id==0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_len*surface->array[VS::ARRAY_INDEX].size,index_array_ptr,GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - - } - } - - mesh->surfaces.push_back(surface); - -} - -Error RasterizerGLES1::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem,uint8_t *p_index_mem,const Array& p_arrays,bool p_main) { - - uint32_t stride = p_main ? p_surface->stride : p_surface->local_stride; - - for(int ai=0;ai<VS::ARRAY_MAX;ai++) { - if (ai>=p_arrays.size()) - break; - if (p_arrays[ai].get_type()==Variant::NIL) - continue; - Surface::ArrayData &a=p_surface->array[ai]; - - switch(ai) { - - - case VS::ARRAY_VERTEX: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<Vector3> array = p_arrays[ai]; - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector<Vector3>::Read read = array.read(); - const Vector3* src=read.ptr(); - - // setting vertices means regenerating the AABB - AABB aabb; - - float scale=1; - float max=0; - - - for (int i=0;i<p_surface->array_len;i++) { - - - GLfloat vector[3]={ src[i].x, src[i].y, src[i].z }; - - copymem(&p_mem[a.ofs+i*stride], vector, a.size); - - if (i==0) { - - aabb=AABB(src[i],Vector3()); - } else { - - aabb.expand_to( src[i] ); - } - } - - if (p_main) { - p_surface->aabb=aabb; - p_surface->vertex_scale=scale; - } - - - } break; - case VS::ARRAY_NORMAL: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<Vector3> array = p_arrays[ai]; - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector<Vector3>::Read read = array.read(); - const Vector3* src=read.ptr(); - - // setting vertices means regenerating the AABB - - for (int i=0;i<p_surface->array_len;i++) { - - - GLfloat vector[3]={ src[i].x, src[i].y, src[i].z }; - copymem(&p_mem[a.ofs+i*stride], vector, a.size); - - } - - - } break; - case VS::ARRAY_TANGENT: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<real_t> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len*4, ERR_INVALID_PARAMETER ); - - - DVector<real_t>::Read read = array.read(); - const real_t* src = read.ptr(); - - for (int i=0;i<p_surface->array_len;i++) { - - GLfloat xyzw[4]={ - src[i*4+0], - src[i*4+1], - src[i*4+2], - src[i*4+3] - }; - - copymem(&p_mem[a.ofs+i*stride], xyzw, a.size); - - } - - } break; - case VS::ARRAY_COLOR: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::COLOR_ARRAY, ERR_INVALID_PARAMETER ); - - - DVector<Color> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector<Color>::Read read = array.read(); - const Color* src = read.ptr(); - bool alpha=false; - - for (int i=0;i<p_surface->array_len;i++) { - - if (src[i].a<0.98) // tolerate alpha a bit, for crappy exporters - alpha=true; - - uint8_t colors[4]; - - for(int j=0;j<4;j++) { - - colors[j]=CLAMP( int((src[i][j])*255.0), 0,255 ); - } - - copymem(&p_mem[a.ofs+i*stride], colors, a.size); - - } - - if (p_main) - p_surface->has_alpha=alpha; - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::VECTOR2_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<Vector2> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len , ERR_INVALID_PARAMETER); - - DVector<Vector2>::Read read = array.read(); - - const Vector2 * src=read.ptr(); - float scale=1.0; - - - for (int i=0;i<p_surface->array_len;i++) { - - GLfloat uv[2]={ src[i].x , src[i].y }; - - copymem(&p_mem[a.ofs+i*stride], uv, a.size); - - } - - if (p_main) { - - if (ai==VS::ARRAY_TEX_UV) { - - p_surface->uv_scale=scale; - } - if (ai==VS::ARRAY_TEX_UV2) { - - p_surface->uv2_scale=scale; - } - } - - } break; - case VS::ARRAY_BONES: - case VS::ARRAY_WEIGHTS: { - - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<real_t> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); - - - DVector<real_t>::Read read = array.read(); - - const real_t * src = read.ptr(); - - p_surface->max_bone=0; - - for (int i=0;i<p_surface->array_len;i++) { - - GLfloat data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j]; - if (ai==VS::ARRAY_BONES) { - - p_surface->max_bone=MAX(data[j],p_surface->max_bone); - } - } - - copymem(&p_mem[a.ofs+i*stride], data, a.size); - - - } - - } break; - case VS::ARRAY_INDEX: { - - ERR_FAIL_COND_V( p_surface->index_array_len<=0, ERR_INVALID_DATA ); - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::INT_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<int> indices = p_arrays[ai]; - ERR_FAIL_COND_V( indices.size() == 0, ERR_INVALID_PARAMETER ); - ERR_FAIL_COND_V( indices.size() != p_surface->index_array_len, ERR_INVALID_PARAMETER ); - - /* determine wether using 16 or 32 bits indices */ - - DVector<int>::Read read = indices.read(); - const int *src=read.ptr(); - - for (int i=0;i<p_surface->index_array_len;i++) { - - - if (a.size==2) { - uint16_t v=src[i]; - - copymem(&p_index_mem[i*a.size], &v, a.size); - } else { - uint32_t v=src[i]; - - copymem(&p_index_mem[i*a.size], &v, a.size); - } - } - - - } break; - - - default: { ERR_FAIL_V(ERR_INVALID_PARAMETER);} - } - - p_surface->configured_format|=(1<<ai); - } - - return OK; -} - - - -void RasterizerGLES1::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) { - - ERR_EXPLAIN("OpenGL Rasterizer does not support custom surfaces. Running on wrong platform?"); - ERR_FAIL_V(); -} - -Array RasterizerGLES1::mesh_get_surface_arrays(RID p_mesh,int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->data; - - -} -Array RasterizerGLES1::mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->morph_data; - -} - - -void RasterizerGLES1::mesh_set_morph_target_count(RID p_mesh,int p_amount) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_COND( mesh->surfaces.size()!=0 ); - - mesh->morph_target_count=p_amount; - -} - -int RasterizerGLES1::mesh_get_morph_target_count(RID p_mesh) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->morph_target_count; - -} - -void RasterizerGLES1::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode) { - - ERR_FAIL_INDEX(p_mode,2); - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->morph_target_mode=p_mode; - -} - -VS::MorphTargetMode RasterizerGLES1::mesh_get_morph_target_mode(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::MORPH_MODE_NORMALIZED); - - return mesh->morph_target_mode; - -} - - - -void RasterizerGLES1::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND( !surface); - - if (surface->material_owned && surface->material.is_valid()) - free(surface->material); - - surface->material_owned=p_owned; - - surface->material=p_material; -} - -RID RasterizerGLES1::mesh_surface_get_material(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,RID()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, RID() ); - - return surface->material; -} - -int RasterizerGLES1::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - return surface->array_len; -} -int RasterizerGLES1::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - return surface->index_array_len; -} -uint32_t RasterizerGLES1::mesh_surface_get_format(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, 0 ); - - return surface->format; -} -VS::PrimitiveType RasterizerGLES1::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::PRIMITIVE_POINTS); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_POINTS ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, VS::PRIMITIVE_POINTS ); - - return surface->primitive; -} - -void RasterizerGLES1::mesh_remove_surface(RID p_mesh,int p_index) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_index, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_index]; - ERR_FAIL_COND( !surface); - - if (mesh->morph_target_count) { - for(int i=0;i<mesh->morph_target_count;i++) - memfree(surface->morph_targets_local[i].array); - memfree( surface->morph_targets_local ); - } - - memdelete( mesh->surfaces[p_index] ); - mesh->surfaces.remove(p_index); - -} -int RasterizerGLES1::mesh_get_surface_count(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->surfaces.size(); -} - -AABB RasterizerGLES1::mesh_get_aabb(RID p_mesh,RID p_skeleton) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - if (mesh->custom_aabb!=AABB()) - return mesh->custom_aabb; - - AABB aabb; - - for (int i=0;i<mesh->surfaces.size();i++) { - - if (i==0) - aabb=mesh->surfaces[i]->aabb; - else - aabb.merge_with(mesh->surfaces[i]->aabb); - } - - return aabb; -} - -void RasterizerGLES1::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->custom_aabb=p_aabb; - -} - -AABB RasterizerGLES1::mesh_get_custom_aabb(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - return mesh->custom_aabb; -} - - -/* MULTIMESH API */ - -RID RasterizerGLES1::multimesh_create() { - - return multimesh_owner.make_rid( memnew( MultiMesh )); -} - -void RasterizerGLES1::multimesh_set_instance_count(RID p_multimesh,int p_count) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->elements.clear(); // make sure to delete everything, so it "fails" in all implementations - multimesh->elements.resize(p_count); - -} -int RasterizerGLES1::multimesh_get_instance_count(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - - return multimesh->elements.size(); -} - -void RasterizerGLES1::multimesh_set_mesh(RID p_multimesh,RID p_mesh) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->mesh=p_mesh; - -} -void RasterizerGLES1::multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->aabb=p_aabb; -} -void RasterizerGLES1::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - MultiMesh::Element &e=multimesh->elements[p_index]; - - e.matrix[0]=p_transform.basis.elements[0][0]; - e.matrix[1]=p_transform.basis.elements[1][0]; - e.matrix[2]=p_transform.basis.elements[2][0]; - e.matrix[3]=0; - e.matrix[4]=p_transform.basis.elements[0][1]; - e.matrix[5]=p_transform.basis.elements[1][1]; - e.matrix[6]=p_transform.basis.elements[2][1]; - e.matrix[7]=0; - e.matrix[8]=p_transform.basis.elements[0][2]; - e.matrix[9]=p_transform.basis.elements[1][2]; - e.matrix[10]=p_transform.basis.elements[2][2]; - e.matrix[11]=0; - e.matrix[12]=p_transform.origin.x; - e.matrix[13]=p_transform.origin.y; - e.matrix[14]=p_transform.origin.z; - e.matrix[15]=1; - -} -void RasterizerGLES1::multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh) - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - MultiMesh::Element &e=multimesh->elements[p_index]; - e.color[0]=CLAMP(p_color.r*255,0,255); - e.color[1]=CLAMP(p_color.g*255,0,255); - e.color[2]=CLAMP(p_color.b*255,0,255); - e.color[3]=CLAMP(p_color.a*255,0,255); - - -} - -RID RasterizerGLES1::multimesh_get_mesh(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,RID()); - - return multimesh->mesh; -} -AABB RasterizerGLES1::multimesh_get_aabb(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,AABB()); - - return multimesh->aabb; -} - -Transform RasterizerGLES1::multimesh_instance_get_transform(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Transform()); - - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Transform()); - MultiMesh::Element &e=multimesh->elements[p_index]; - - Transform tr; - - tr.basis.elements[0][0]=e.matrix[0]; - tr.basis.elements[1][0]=e.matrix[1]; - tr.basis.elements[2][0]=e.matrix[2]; - tr.basis.elements[0][1]=e.matrix[4]; - tr.basis.elements[1][1]=e.matrix[5]; - tr.basis.elements[2][1]=e.matrix[6]; - tr.basis.elements[0][2]=e.matrix[8]; - tr.basis.elements[1][2]=e.matrix[9]; - tr.basis.elements[2][2]=e.matrix[10]; - tr.origin.x=e.matrix[12]; - tr.origin.y=e.matrix[13]; - tr.origin.z=e.matrix[14]; - - return tr; -} -Color RasterizerGLES1::multimesh_instance_get_color(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Color()); - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Color()); - MultiMesh::Element &e=multimesh->elements[p_index]; - Color c; - c.r=e.color[0]/255.0; - c.g=e.color[1]/255.0; - c.b=e.color[2]/255.0; - c.a=e.color[3]/255.0; - - return c; - -} - -void RasterizerGLES1::multimesh_set_visible_instances(RID p_multimesh,int p_visible) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->visible=p_visible; - -} - -int RasterizerGLES1::multimesh_get_visible_instances(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - return multimesh->visible; - -} - -/* IMMEDIATE API */ - - -RID RasterizerGLES1::immediate_create() { - - Immediate *im = memnew( Immediate ); - return immediate_owner.make_rid(im); - -} - -void RasterizerGLES1::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){ - - -} -void RasterizerGLES1::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ - - -} -void RasterizerGLES1::immediate_normal(RID p_immediate,const Vector3& p_normal){ - - -} -void RasterizerGLES1::immediate_tangent(RID p_immediate,const Plane& p_tangent){ - - -} -void RasterizerGLES1::immediate_color(RID p_immediate,const Color& p_color){ - - -} -void RasterizerGLES1::immediate_uv(RID p_immediate,const Vector2& tex_uv){ - - -} -void RasterizerGLES1::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ - - -} - -void RasterizerGLES1::immediate_end(RID p_immediate){ - - -} -void RasterizerGLES1::immediate_clear(RID p_immediate) { - - -} - -AABB RasterizerGLES1::immediate_get_aabb(RID p_immediate) const { - - return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); -} - -void RasterizerGLES1::immediate_set_material(RID p_immediate,RID p_material) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - im->material=p_material; -} - -RID RasterizerGLES1::immediate_get_material(RID p_immediate) const { - - const Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND_V(!im,RID()); - return im->material; - -} - - -/* PARTICLES API */ - -RID RasterizerGLES1::particles_create() { - - Particles *particles = memnew( Particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles_owner.make_rid(particles); -} - -void RasterizerGLES1::particles_set_amount(RID p_particles, int p_amount) { - - ERR_FAIL_COND(p_amount<1); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.amount=p_amount; - -} - -int RasterizerGLES1::particles_get_amount(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.amount; - -} - -void RasterizerGLES1::particles_set_emitting(RID p_particles, bool p_emitting) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.emitting=p_emitting;; - -} -bool RasterizerGLES1::particles_is_emitting(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.emitting; - -} - -void RasterizerGLES1::particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.visibility_aabb=p_visibility; - -} - -void RasterizerGLES1::particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_half_extents=p_half_extents; -} -Vector3 RasterizerGLES1::particles_get_emission_half_extents(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_half_extents; -} - -void RasterizerGLES1::particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_base_velocity=p_base_velocity; -} - -Vector3 RasterizerGLES1::particles_get_emission_base_velocity(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_base_velocity; -} - - -void RasterizerGLES1::particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_points=p_points; -} - -DVector<Vector3> RasterizerGLES1::particles_get_emission_points(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,DVector<Vector3>()); - - return particles->data.emission_points; - -} - -void RasterizerGLES1::particles_set_gravity_normal(RID p_particles, const Vector3& p_normal) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.gravity_normal=p_normal; - -} -Vector3 RasterizerGLES1::particles_get_gravity_normal(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.gravity_normal; -} - - -AABB RasterizerGLES1::particles_get_visibility_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; - -} - -void RasterizerGLES1::particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value) { - - ERR_FAIL_INDEX(p_variable,VS::PARTICLE_VAR_MAX); - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_vars[p_variable]=p_value; - -} -float RasterizerGLES1::particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_vars[p_variable]; -} - -void RasterizerGLES1::particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_randomness[p_variable]=p_randomness; - -} -float RasterizerGLES1::particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_randomness[p_variable]; - -} - -void RasterizerGLES1::particles_set_color_phases(RID p_particles, int p_phases) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_phases<0 || p_phases>VS::MAX_PARTICLE_COLOR_PHASES ); - particles->data.color_phase_count=p_phases; - -} -int RasterizerGLES1::particles_get_color_phases(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phase_count; -} - - -void RasterizerGLES1::particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - if (p_pos<0.0) - p_pos=0.0; - if (p_pos>1.0) - p_pos=1.0; - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].pos=p_pos; - -} -float RasterizerGLES1::particles_get_color_phase_pos(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, -1.0); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phases[p_phase].pos; - -} - -void RasterizerGLES1::particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].color=p_color; - - //update alpha - particles->has_alpha=false; - for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) { - if (particles->data.color_phases[i].color.a<0.99) - particles->has_alpha=true; - } - -} - -Color RasterizerGLES1::particles_get_color_phase_color(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, Color()); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Color()); - return particles->data.color_phases[p_phase].color; - -} - -void RasterizerGLES1::particles_set_attractors(RID p_particles, int p_attractors) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_attractors<0 || p_attractors>VisualServer::MAX_PARTICLE_ATTRACTORS ); - particles->data.attractor_count=p_attractors; - -} -int RasterizerGLES1::particles_get_attractors(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.attractor_count; -} - -void RasterizerGLES1::particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].pos=p_pos;; -} -Vector3 RasterizerGLES1::particles_get_attractor_pos(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,Vector3()); - return particles->data.attractors[p_attractor].pos; -} - -void RasterizerGLES1::particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].force=p_force; -} - -float RasterizerGLES1::particles_get_attractor_strength(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,0); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,0); - return particles->data.attractors[p_attractor].force; -} - -void RasterizerGLES1::particles_set_material(RID p_particles, RID p_material,bool p_owned) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - if (particles->material_owned && particles->material.is_valid()) - free(particles->material); - - particles->material_owned=p_owned; - - particles->material=p_material; - -} -RID RasterizerGLES1::particles_get_material(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles->material; - -} - -void RasterizerGLES1::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.local_coordinates=p_enable; - -} - -bool RasterizerGLES1::particles_is_using_local_coordinates(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.local_coordinates; -} -bool RasterizerGLES1::particles_has_height_from_velocity(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.height_from_velocity; -} - -void RasterizerGLES1::particles_set_height_from_velocity(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.height_from_velocity=p_enable; - -} - -AABB RasterizerGLES1::particles_get_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; -} - -/* SKELETON API */ - -RID RasterizerGLES1::skeleton_create() { - - Skeleton *skeleton = memnew( Skeleton ); - ERR_FAIL_COND_V(!skeleton,RID()); - return skeleton_owner.make_rid( skeleton ); -} -void RasterizerGLES1::skeleton_resize(RID p_skeleton,int p_bones) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - if (p_bones == skeleton->bones.size()) { - return; - }; - - skeleton->bones.resize(p_bones); - -} -int RasterizerGLES1::skeleton_get_bone_count(RID p_skeleton) const { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, -1); - return skeleton->bones.size(); -} -void RasterizerGLES1::skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX( p_bone, skeleton->bones.size() ); - - skeleton->bones[p_bone] = p_transform; -} - -Transform RasterizerGLES1::skeleton_bone_get_transform(RID p_skeleton,int p_bone) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, Transform()); - ERR_FAIL_INDEX_V( p_bone, skeleton->bones.size(), Transform() ); - - // something - return skeleton->bones[p_bone]; -} - - -/* LIGHT API */ - -RID RasterizerGLES1::light_create(VS::LightType p_type) { - - Light *light = memnew( Light ); - light->type=p_type; - return light_owner.make_rid(light); -} - -VS::LightType RasterizerGLES1::light_get_type(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI); - return light->type; -} - -void RasterizerGLES1::light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_type, 3 ); - light->colors[p_type]=p_color; -} -Color RasterizerGLES1::light_get_color(RID p_light,VS::LightColor p_type) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, Color()); - ERR_FAIL_INDEX_V( p_type, 3, Color() ); - return light->colors[p_type]; -} - -void RasterizerGLES1::light_set_shadow(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->shadow_enabled=p_enabled; -} - -bool RasterizerGLES1::light_has_shadow(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->shadow_enabled; -} - -void RasterizerGLES1::light_set_volumetric(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->volumetric_enabled=p_enabled; - -} -bool RasterizerGLES1::light_is_volumetric(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->volumetric_enabled; -} - -void RasterizerGLES1::light_set_projector(RID p_light,RID p_texture) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->projector=p_texture; -} -RID RasterizerGLES1::light_get_projector(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,RID()); - return light->projector; -} - -void RasterizerGLES1::light_set_var(RID p_light, VS::LightParam p_var, float p_value) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_var, VS::LIGHT_PARAM_MAX ); - - light->vars[p_var]=p_value; -} -float RasterizerGLES1::light_get_var(RID p_light, VS::LightParam p_var) const { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,0); - - ERR_FAIL_INDEX_V( p_var, VS::LIGHT_PARAM_MAX,0 ); - - return light->vars[p_var]; -} - -void RasterizerGLES1::light_set_operator(RID p_light,VS::LightOp p_op) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - - -}; - -VS::LightOp RasterizerGLES1::light_get_operator(RID p_light) const { - - return VS::LightOp(0); -}; - -void RasterizerGLES1::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { - - -} - -VS::LightOmniShadowMode RasterizerGLES1::light_omni_get_shadow_mode(RID p_light) const{ - - return VS::LightOmniShadowMode(0); -} - -void RasterizerGLES1::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) { - - -} - -VS::LightDirectionalShadowMode RasterizerGLES1::light_directional_get_shadow_mode(RID p_light) const { - - return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; -} - -void RasterizerGLES1::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) { - - -} - -float RasterizerGLES1::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const { - - return 0; -} - - -AABB RasterizerGLES1::light_get_aabb(RID p_light) const { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,AABB()); - - switch( light->type ) { - - case VS::LIGHT_SPOT: { - - float len=light->vars[VS::LIGHT_PARAM_RADIUS]; - float size=Math::tan(Math::deg2rad(light->vars[VS::LIGHT_PARAM_SPOT_ANGLE]))*len; - return AABB( Vector3( -size,-size,-len ), Vector3( size*2, size*2, len ) ); - } break; - case VS::LIGHT_OMNI: { - - float r = light->vars[VS::LIGHT_PARAM_RADIUS]; - return AABB( -Vector3(r,r,r), Vector3(r,r,r)*2 ); - } break; - case VS::LIGHT_DIRECTIONAL: { - - return AABB(); - } break; - default: {} - } - - ERR_FAIL_V( AABB() ); -} - - -RID RasterizerGLES1::light_instance_create(RID p_light) { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light, RID()); - - LightInstance *light_instance = memnew( LightInstance ); - - light_instance->light=p_light; - light_instance->base=light; - light_instance->last_pass=0; - - return light_instance_owner.make_rid( light_instance ); -} -void RasterizerGLES1::light_instance_set_transform(RID p_light_instance,const Transform& p_transform) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - lighti->transform=p_transform; - -} - -bool RasterizerGLES1::light_instance_has_shadow(RID p_light_instance) const { - - return false; - - /* - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND_V(!lighti, false); - - if (!lighti->base->shadow_enabled) - return false; - - if (lighti->base->type==VS::LIGHT_DIRECTIONAL) { - if (lighti->shadow_pass!=scene_pass) - return false; - - } else { - if (lighti->shadow_pass!=frame) - return false; - }*/ - - - - //return !lighti->shadow_buffers.empty(); - -} - - -bool RasterizerGLES1::light_instance_assign_shadow(RID p_light_instance) { - - return false; - -} - - -Rasterizer::ShadowType RasterizerGLES1::light_instance_get_shadow_type(RID p_light_instance) const { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND_V(!lighti,Rasterizer::SHADOW_NONE); - - switch(lighti->base->type) { - - case VS::LIGHT_DIRECTIONAL: return SHADOW_PSM; break; - case VS::LIGHT_OMNI: return SHADOW_DUAL_PARABOLOID; break; - case VS::LIGHT_SPOT: return SHADOW_SIMPLE; break; - } - - return Rasterizer::SHADOW_NONE; -} - -Rasterizer::ShadowType RasterizerGLES1::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const { - - return SHADOW_NONE; -} -void RasterizerGLES1::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - -} - -int RasterizerGLES1::light_instance_get_shadow_passes(RID p_light_instance) const { - - return 0; -} - -bool RasterizerGLES1::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { - - return false; -} - -void RasterizerGLES1::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - - ERR_FAIL_COND(lighti->base->type!=VS::LIGHT_DIRECTIONAL); - ERR_FAIL_INDEX(p_index,1); - - lighti->custom_projection=p_camera; - lighti->custom_transform=p_transform; - -} -void RasterizerGLES1::shadow_clear_near() { - - -} - -bool RasterizerGLES1::shadow_allocate_near(RID p_light) { - - return false; -} - -bool RasterizerGLES1::shadow_allocate_far(RID p_light) { - - return false; -} - -/* PARTICLES INSTANCE */ - -RID RasterizerGLES1::particles_instance_create(RID p_particles) { - - ERR_FAIL_COND_V(!particles_owner.owns(p_particles),RID()); - ParticlesInstance *particles_instance = memnew( ParticlesInstance ); - ERR_FAIL_COND_V(!particles_instance, RID() ); - particles_instance->particles=p_particles; - return particles_instance_owner.make_rid(particles_instance); -} - -void RasterizerGLES1::particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform) { - - ParticlesInstance *particles_instance=particles_instance_owner.get(p_particles_instance); - ERR_FAIL_COND(!particles_instance); - particles_instance->transform=p_transform; -} - - -/* RENDER API */ -/* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - -RID RasterizerGLES1::viewport_data_create() { - - return RID(); -} - -RID RasterizerGLES1::render_target_create(){ - - return RID(); - -} -void RasterizerGLES1::render_target_set_size(RID p_render_target, int p_width, int p_height){ - - -} -RID RasterizerGLES1::render_target_get_texture(RID p_render_target) const{ - - return RID(); - -} -bool RasterizerGLES1::render_target_renedered_in_frame(RID p_render_target){ - - return false; -} - - -void RasterizerGLES1::begin_frame() { - - - window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height ); - //print_line("begin frame - winsize: "+window_size); - - double time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec - time/=1000.0; // make secs - time_delta=time-last_time; - last_time=time; - frame++; - clear_viewport(Color(1,0,0.5)); - - _rinfo.vertex_count=0; - _rinfo.object_count=0; - _rinfo.mat_change_count=0; - _rinfo.shader_change_count=0; - - -// material_shader.set_uniform_default(MaterialShaderGLES1::SCREENZ_SCALE, Math::fmod(time, 3600.0)); - /* nehe ?*/ - -// glClearColor(0,0,1,1); -// glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared.. -} - -void RasterizerGLES1::capture_viewport(Image* r_capture) { - - -} - - -void RasterizerGLES1::clear_viewport(const Color& p_color) { - - glScissor( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); - glEnable(GL_SCISSOR_TEST); - glClearColor(p_color.r,p_color.g,p_color.b,p_color.a); - glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared.. - glDisable(GL_SCISSOR_TEST); - -}; - -void RasterizerGLES1::set_viewport(const VS::ViewportRect& p_viewport) { - - - - viewport=p_viewport; - //print_line("viewport: "+itos(p_viewport.x)+","+itos(p_viewport.y)+","+itos(p_viewport.width)+","+itos(p_viewport.height)); - - glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); -} - -void RasterizerGLES1::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) { - - -} - - -void RasterizerGLES1::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) { - - - opaque_render_list.clear(); - alpha_render_list.clear(); - light_instance_count=0; - scene_fx = NULL; // p_env.is_valid() ? fx_owner.get(p_env) : NULL; - scene_pass++; - last_light_id=0; - directional_light_count=0; - - - //set state - - glCullFace(GL_FRONT); - cull_front=true; -}; - -void RasterizerGLES1::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) { - -} - -void RasterizerGLES1::set_camera(const Transform& p_world,const CameraMatrix& p_projection) { - - camera_transform=p_world; - camera_transform_inverse=camera_transform.inverse(); - camera_projection=p_projection; - camera_plane = Plane( camera_transform.origin, camera_transform.basis.get_axis(2) ); - camera_z_near=camera_projection.get_z_near(); - camera_z_far=camera_projection.get_z_far(); - camera_projection.get_viewport_size(camera_vp_size.x,camera_vp_size.y); -} - -void RasterizerGLES1::add_light( RID p_light_instance ) { - -#define LIGHT_FADE_TRESHOLD 0.05 - - ERR_FAIL_COND( light_instance_count >= MAX_SCENE_LIGHTS ); - - LightInstance *li = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND(!li); - - - /* make light hash */ - - // actually, not really a hash, but helps to sort the lights - // and avoid recompiling redudant shader versions - - - li->last_pass=scene_pass; - li->sort_key=light_instance_count; - - switch(li->base->type) { - - case VisualServer::LIGHT_DIRECTIONAL: { - - li->light_vector = camera_transform_inverse.basis.xform(li->transform.basis.get_axis(2)).normalized(); - if (directional_light_count<MAX_HW_LIGHTS) { - - directional_lights[directional_light_count++]=li; - } - - } break; - case VisualServer::LIGHT_OMNI: { - - float radius = li->base->vars[VisualServer::LIGHT_PARAM_RADIUS]; - if (radius==0) - radius=0.0001; - li->linear_att=(1/LIGHT_FADE_TRESHOLD)/radius; - li->light_vector = camera_transform_inverse.xform(li->transform.origin); - - } break; - case VisualServer::LIGHT_SPOT: { - - float radius = li->base->vars[VisualServer::LIGHT_PARAM_RADIUS]; - if (radius==0) - radius=0.0001; - li->linear_att=(1/LIGHT_FADE_TRESHOLD)/radius; - li->light_vector = camera_transform_inverse.xform(li->transform.origin); - li->spot_vector = -camera_transform_inverse.basis.xform(li->transform.basis.get_axis(2)).normalized(); - //li->sort_key|=LIGHT_SPOT_BIT; // this way, omnis go first, spots go last and less shader versions are generated - - /* - if (li->base->projector.is_valid()) { - - float far = li->base->vars[ VS::LIGHT_VAR_RADIUS ]; - ERR_FAIL_COND( far<=0 ); - float near= far/200.0; - if (near<0.05) - near=0.05; - - float angle = li->base->vars[ VS::LIGHT_VAR_SPOT_ANGLE ]; - - //CameraMatrix proj; - //proj.set_perspective( angle*2.0, 1.0, near, far ); - - //Transform modelview=Transform(camera_transform_inverse * li->transform).inverse(); - //li->projector_mtx= proj * modelview; - - }*/ - } break; - } - - light_instances[light_instance_count++]=li; - -} - -void RasterizerGLES1::_add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner) { - - Material *m=NULL; - RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override : p_geometry->material; - - if (m_src) - m=material_owner.get( m_src ); - - if (!m) { - m=material_owner.get( default_material ); - } - - ERR_FAIL_COND(!m); - - - if (m->last_pass!=frame) { - - m->last_pass=frame; - } - - - LightInstance *lights[RenderList::MAX_LIGHTS]; - int light_count=0; - - RenderList *render_list=&opaque_render_list; - if (m->fixed_flags[VS::FIXED_MATERIAL_FLAG_USE_ALPHA] || m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX) { - render_list = &alpha_render_list; - }; - - if (!m->flags[VS::MATERIAL_FLAG_UNSHADED]) { - - int lis = p_instance->light_instances.size(); - - for(int i=0;i<lis;i++) { - if (light_count>=RenderList::MAX_LIGHTS) - break; - - LightInstance *li=light_instance_owner.get( p_instance->light_instances[i] ); - - if (!li || li->last_pass!=scene_pass) //lit by light not in visible scene - continue; - lights[light_count++]=li; - } - } - - RenderList::Element *e = render_list->add_element(); - - e->geometry=p_geometry; -// e->geometry_cmp=p_geometry_cmp; - e->material=m; - e->instance=p_instance; - //e->depth=camera_plane.distance_to(p_world->origin); - e->depth=camera_transform.origin.distance_to(p_instance->transform.origin); - e->owner=p_owner; - if (p_instance->skeleton.is_valid()) - e->skeleton=skeleton_owner.get(p_instance->skeleton); - else - e->skeleton=NULL; - e->mirror=p_instance->mirror; - if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES]) - e->mirror=!e->mirror; - - e->light_key=0; - e->light_count=0; - - - if (!shadow) { - - - if (m->flags[VS::MATERIAL_FLAG_UNSHADED]) { - - - e->light_key--; //special key for all the shadeless people - } else if (light_count) { - - for(int i=0;i<light_count;i++) { - - e->lights[i]=lights[i]->sort_key; - } - - e->light_count=light_count; - int poslight_count=light_count; - if (poslight_count>1) { - SortArray<uint16_t> light_sort; - light_sort.sort(&e->lights[0],poslight_count); //generate an equal sort key - } - } - - } - -} - - -void RasterizerGLES1::add_mesh( const RID& p_mesh, const InstanceData *p_data) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - - int ssize = mesh->surfaces.size(); - - for (int i=0;i<ssize;i++) { - - Surface *s = mesh->surfaces[i]; - _add_geometry(s,p_data,s,NULL); - } - - mesh->last_pass=frame; - -} - -void RasterizerGLES1::add_multimesh( const RID& p_multimesh, const InstanceData *p_data){ - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (!multimesh->mesh.is_valid()) - return; - if (multimesh->elements.empty()) - return; - - Mesh *mesh = mesh_owner.get(multimesh->mesh); - ERR_FAIL_COND(!mesh); - - int surf_count = mesh->surfaces.size(); - if (multimesh->last_pass!=scene_pass) { - - multimesh->cache_surfaces.resize(surf_count); - for(int i=0;i<surf_count;i++) { - - multimesh->cache_surfaces[i].material=mesh->surfaces[i]->material; - multimesh->cache_surfaces[i].has_alpha=mesh->surfaces[i]->has_alpha; - multimesh->cache_surfaces[i].surface=mesh->surfaces[i]; - } - - multimesh->last_pass=scene_pass; - } - - for(int i=0;i<surf_count;i++) { - - _add_geometry(&multimesh->cache_surfaces[i],p_data,multimesh->cache_surfaces[i].surface,multimesh); - } - - -} - -void RasterizerGLES1::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ - - //print_line("adding particles"); - ParticlesInstance *particles_instance = particles_instance_owner.get(p_particle_instance); - ERR_FAIL_COND(!particles_instance); - Particles *p=particles_owner.get( particles_instance->particles ); - ERR_FAIL_COND(!p); - - _add_geometry(p,p_data,p,particles_instance); - -} - - -void RasterizerGLES1::_set_cull(bool p_front,bool p_reverse_cull) { - - bool front = p_front; - if (p_reverse_cull) - front=!front; - - if (front!=cull_front) { - - glCullFace(front?GL_FRONT:GL_BACK); - cull_front=front; - } -} - - -void RasterizerGLES1::_setup_fixed_material(const Geometry *p_geometry,const Material *p_material) { - - if (!shadow) { - - ///ambient @TODO offer global ambient group option - - //GLenum side = use_shaders?GL_FRONT:GL_FRONT_AND_BACK; - GLenum side = GL_FRONT_AND_BACK; - - - ///diffuse - Color diffuse_color=p_material->parameters[VS::FIXED_MATERIAL_PARAM_DIFFUSE]; - float diffuse_rgba[4]={ - diffuse_color.r, - diffuse_color.g, - diffuse_color.b, - diffuse_color.a - }; - - //color array overrides this - glColor4f( diffuse_rgba[0],diffuse_rgba[1],diffuse_rgba[2],diffuse_rgba[3]); - last_color=diffuse_color; - glMaterialfv(side,GL_AMBIENT,diffuse_rgba); - glMaterialfv(side,GL_DIFFUSE,diffuse_rgba); - //specular - - const Color specular_color=p_material->parameters[VS::FIXED_MATERIAL_PARAM_SPECULAR]; - float specular_rgba[4]={ - specular_color.r, - specular_color.g, - specular_color.b, - 1.0 - }; - - glMaterialfv(side,GL_SPECULAR,specular_rgba); - - const Color emission=p_material->parameters[VS::FIXED_MATERIAL_PARAM_EMISSION]; - - - float emission_rgba[4]={ - emission.r, - emission.g, - emission.b, - 1.0 //p_material->parameters[VS::FIXED_MATERIAL_PARAM_DETAIL_MIX] - }; - - glMaterialfv(side,GL_EMISSION,emission_rgba); - - glMaterialf(side,GL_SHININESS,p_material->parameters[VS::FIXED_MATERIAL_PARAM_SPECULAR_EXP]); - - Plane sparams=p_material->parameters[VS::FIXED_MATERIAL_PARAM_SHADE_PARAM]; - //depth test? - - - } - - - if (p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE].is_valid()) { - - Texture *texture = texture_owner.get( p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE] ); - ERR_FAIL_COND(!texture); - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - } else { - - glDisable(GL_TEXTURE_2D); - } - -} - -void RasterizerGLES1::_setup_material(const Geometry *p_geometry,const Material *p_material) { - - if (p_material->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED]) - glDisable(GL_CULL_FACE); - else { - glEnable(GL_CULL_FACE); - } - -/* if (p_material->flags[VS::MATERIAL_FLAG_WIREFRAME]) - glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - else - glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);*/ - - if (p_material->line_width > 0) - glLineWidth(p_material->line_width); - - if (!shadow) { - - - if (blend_mode!=p_material->blend_mode) { - switch(p_material->blend_mode) { - - - case VS::MATERIAL_BLEND_MODE_MIX: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - case VS::MATERIAL_BLEND_MODE_ADD: { - - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - - } break; - case VS::MATERIAL_BLEND_MODE_SUB: { - - //glBlendEquation(GL_FUNC_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - } break; - case VS::MATERIAL_BLEND_MODE_MUL: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - - } - blend_mode=p_material->blend_mode; - } - - if (lighting!=!p_material->flags[VS::MATERIAL_FLAG_UNSHADED]) { - if (p_material->flags[VS::MATERIAL_FLAG_UNSHADED]) { - glDisable(GL_LIGHTING); - } else { - glEnable(GL_LIGHTING); - } - lighting=!p_material->flags[VS::MATERIAL_FLAG_UNSHADED]; - } - - } - - bool current_depth_write=p_material->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_ALWAYS; //broken - bool current_depth_test=!p_material->flags[VS::MATERIAL_FLAG_ONTOP]; - - - _setup_fixed_material(p_geometry,p_material); - - if (current_depth_write!=depth_write) { - - depth_write=current_depth_write; - glDepthMask(depth_write); - } - - if (current_depth_test!=depth_test) { - - depth_test=current_depth_test; - if (depth_test) - glEnable(GL_DEPTH_TEST); - else - glDisable(GL_DEPTH_TEST); - } -} -/* -static const MaterialShaderGLES1::Conditionals _gl_light_version[4][3]={ - {MaterialShaderGLES1::LIGHT_0_DIRECTIONAL,MaterialShaderGLES1::LIGHT_0_OMNI,MaterialShaderGLES1::LIGHT_0_SPOT}, - {MaterialShaderGLES1::LIGHT_1_DIRECTIONAL,MaterialShaderGLES1::LIGHT_1_OMNI,MaterialShaderGLES1::LIGHT_1_SPOT}, - {MaterialShaderGLES1::LIGHT_2_DIRECTIONAL,MaterialShaderGLES1::LIGHT_2_OMNI,MaterialShaderGLES1::LIGHT_2_SPOT}, - {MaterialShaderGLES1::LIGHT_3_DIRECTIONAL,MaterialShaderGLES1::LIGHT_3_OMNI,MaterialShaderGLES1::LIGHT_3_SPOT} -}; - -static const MaterialShaderGLES1::Conditionals _gl_light_shadow[4]={ - MaterialShaderGLES1::LIGHT_0_SHADOW, - MaterialShaderGLES1::LIGHT_1_SHADOW, - MaterialShaderGLES1::LIGHT_2_SHADOW, - MaterialShaderGLES1::LIGHT_3_SHADOW -}; -*/ - - -void RasterizerGLES1::_setup_light(LightInstance* p_instance, int p_idx) { - - Light* ld = p_instance->base; - -// material_shader.set_conditional(MaterialShaderGLES1::LIGHT_0_DIRECTIONAL, true); - - //material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_DIFFUSE, ld->colors[VS::LIGHT_COLOR_DIFFUSE]); - //material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_SPECULAR, ld->colors[VS::LIGHT_COLOR_SPECULAR]); - //material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_AMBIENT, ld->colors[VS::LIGHT_COLOR_AMBIENT]); - - GLenum glid = GL_LIGHT0+p_idx; - - Color diff_color = ld->colors[VS::LIGHT_COLOR_DIFFUSE]; - float emult = ld->vars[VS::LIGHT_PARAM_ENERGY]; - - if (ld->type!=VS::LIGHT_DIRECTIONAL) - emult*=4.0; - - GLfloat diffuse_sdark[4]={ - diff_color.r*emult, - diff_color.g*emult, - diff_color.b*emult, - 1.0 - }; - - glLightfv(glid , GL_DIFFUSE, diffuse_sdark); - - Color amb_color = Color(0,0,0); - GLfloat amb_stexsize[4]={ - amb_color.r, - amb_color.g, - amb_color.b, - 1.0 - }; - - glLightfv(glid , GL_AMBIENT, amb_stexsize ); - - Color spec_color = ld->colors[VS::LIGHT_COLOR_SPECULAR]; - GLfloat spec_op[4]={ - spec_color.r, - spec_color.g, - spec_color.b, - 1.0 - }; - - glLightfv(glid , GL_SPECULAR, spec_op ); - - switch(ld->type) { - - case VS::LIGHT_DIRECTIONAL: { - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glLightf(glid,GL_CONSTANT_ATTENUATION, 1); - glLightf(glid,GL_LINEAR_ATTENUATION, 0); - glLightf(glid,GL_QUADRATIC_ATTENUATION,0); // energy - - float lightdir[4]={ - p_instance->light_vector.x, - p_instance->light_vector.y, - p_instance->light_vector.z, - 0.0 - }; - - glLightfv(glid,GL_POSITION,lightdir); //at modelview - glLightf(glid,GL_SPOT_CUTOFF,180.0); - glLightf(glid,GL_SPOT_EXPONENT, 0); - - float sdir[4]={ - 0, - 0, - -1, - 0 - }; - - glLightfv(glid,GL_SPOT_DIRECTION,sdir); //at modelview - -// material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_DIRECTION, p_instance->light_vector); - glPopMatrix(); - - } break; - - case VS::LIGHT_OMNI: { - - - glLightf(glid,GL_SPOT_CUTOFF,180.0); - glLightf(glid,GL_SPOT_EXPONENT, 0); - - - glLightf(glid,GL_CONSTANT_ATTENUATION, 0); - glLightf(glid,GL_LINEAR_ATTENUATION, p_instance->linear_att); - glLightf(glid,GL_QUADRATIC_ATTENUATION, 0); // wut? - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - float lightpos[4]={ - p_instance->light_vector.x, - p_instance->light_vector.y, - p_instance->light_vector.z, - 1.0 - }; - - glLightfv(glid,GL_POSITION,lightpos); //at modelview - - glPopMatrix(); - - - } break; - case VS::LIGHT_SPOT: { - - glLightf(glid,GL_SPOT_CUTOFF, ld->vars[VS::LIGHT_PARAM_SPOT_ANGLE]); - glLightf(glid,GL_SPOT_EXPONENT, ld->vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]); - - - glLightf(glid,GL_CONSTANT_ATTENUATION, 0); - glLightf(glid,GL_LINEAR_ATTENUATION, p_instance->linear_att); - glLightf(glid,GL_QUADRATIC_ATTENUATION, 0); // wut? - - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - float lightpos[4]={ - p_instance->light_vector.x, - p_instance->light_vector.y, - p_instance->light_vector.z, - 1.0 - }; - - glLightfv(glid,GL_POSITION,lightpos); //at modelview - - float lightdir[4]={ - p_instance->spot_vector.x, - p_instance->spot_vector.y, - p_instance->spot_vector.z, - 1.0 - }; - - glLightfv(glid,GL_SPOT_DIRECTION,lightdir); //at modelview - - glPopMatrix(); - - - - } break; - - default: break; - } -}; - - - - - -void RasterizerGLES1::_setup_lights(const uint16_t * p_lights,int p_light_count) { - - if (shadow) - return; - - - - for (int i=directional_light_count; i<MAX_HW_LIGHTS; i++) { - - if (i<(directional_light_count+p_light_count)) { - - - glEnable(GL_LIGHT0 + i); - _setup_light(light_instances[p_lights[i]], i); - - } else { - glDisable(GL_LIGHT0 + i); - - } - } - -} - - - -static const GLenum gl_client_states[] = { - - GL_VERTEX_ARRAY, - GL_NORMAL_ARRAY, - 0, // ARRAY_TANGENT - 0,//GL_COLOR_ARRAY, - GL_TEXTURE_COORD_ARRAY, // ARRAY_TEX_UV - 0,//GL_TEXTURE_COORD_ARRAY, // ARRAY_TEX_UV2 - 0, // ARRAY_BONES - 0, // ARRAY_WEIGHTS -}; - -static const int gl_texcoord_index[VS::ARRAY_MAX-1] = { - - -1, - -1, - -1, // ARRAY_TANGENT - -1, - 0, // ARRAY_TEX_UV - -1,//1, // ARRAY_TEX_UV2 - -1, // ARRAY_BONES - -1, // ARRAY_WEIGHTS -}; - - -Error RasterizerGLES1::_setup_geometry(const Geometry *p_geometry, const Material* p_material, const Skeleton *p_skeleton,const float *p_morphs) { - - - switch(p_geometry->type) { - - case Geometry::GEOMETRY_MULTISURFACE: - case Geometry::GEOMETRY_SURFACE: { - - - - const Surface *surf=NULL; - if (p_geometry->type==Geometry::GEOMETRY_SURFACE) - surf=static_cast<const Surface*>(p_geometry); - else if (p_geometry->type==Geometry::GEOMETRY_MULTISURFACE) - surf=static_cast<const MultiMeshSurface*>(p_geometry)->surface; - - - if (surf->format != surf->configured_format) { - if (OS::get_singleton()->is_stdout_verbose()) { - - print_line("has format: "+itos(surf->format)); - print_line("configured format: "+itos(surf->configured_format)); - } - ERR_EXPLAIN("Missing arrays (not set) in surface"); - } - ERR_FAIL_COND_V( surf->format != surf->configured_format, ERR_UNCONFIGURED ); - uint8_t *base=0; - int stride=surf->stride; - bool use_VBO = (surf->array_local==0); - _setup_geometry_vinfo=surf->array_len; - - bool skeleton_valid = p_skeleton && (surf->format&VS::ARRAY_FORMAT_BONES) && (surf->format&VS::ARRAY_FORMAT_WEIGHTS) && !p_skeleton->bones.empty() && p_skeleton->bones.size() > surf->max_bone; - - - - if (!use_VBO) { - - base = surf->array_local; - glBindBuffer(GL_ARRAY_BUFFER, 0); - bool can_copy_to_local=surf->local_stride * surf->array_len <= skinned_buffer_size; - if (!can_copy_to_local) - skeleton_valid=false; - - /* compute morphs */ - - if (p_morphs && surf->morph_target_count && can_copy_to_local) { - - base = skinned_buffer; - stride=surf->local_stride; - - //copy all first - float coef=1.0; - - for(int i=0;i<surf->morph_target_count;i++) { - if (surf->mesh->morph_target_mode==VS::MORPH_MODE_NORMALIZED) - coef-=p_morphs[i]; - ERR_FAIL_COND_V( surf->morph_format != surf->morph_targets_local[i].configured_format, ERR_INVALID_DATA ); - - } - - - for(int i=0;i<VS::ARRAY_MAX-1;i++) { - - const Surface::ArrayData& ad=surf->array[i]; - if (ad.size==0) - continue; - - int ofs = ad.ofs; - int src_stride=surf->stride; - int dst_stride=surf->local_stride; - int count = surf->array_len; - - switch(i) { - - case VS::ARRAY_VERTEX: - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: - { - - for(int k=0;k<count;k++) { - - const float *src = (const float*)&surf->array_local[ofs+k*src_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]= src[0]*coef; - dst[1]= src[1]*coef; - dst[2]= src[2]*coef; - } break; - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - for(int k=0;k<count;k++) { - - const float *src = (const float*)&surf->array_local[ofs+k*src_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]= src[0]*coef; - dst[1]= src[1]*coef; - } break; - - } break; - } - } - - - for(int j=0;j<surf->morph_target_count;j++) { - - for(int i=0;i<VS::ARRAY_MAX-1;i++) { - - const Surface::ArrayData& ad=surf->array[i]; - if (ad.size==0) - continue; - - - int ofs = ad.ofs; - int dst_stride=surf->local_stride; - int count = surf->array_len; - const uint8_t *morph=surf->morph_targets_local[j].array; - float w = p_morphs[j]; - - switch(i) { - - case VS::ARRAY_VERTEX: - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: - { - - for(int k=0;k<count;k++) { - - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]+= src_morph[0]*w; - dst[1]+= src_morph[1]*w; - dst[2]+= src_morph[2]*w; - } break; - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - for(int k=0;k<count;k++) { - - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]+= src_morph[0]*w; - dst[1]+= src_morph[1]*w; - } break; - - } break; - } - } - } - - } else if (skeleton_valid) { - - base = skinned_buffer; - //copy stuff and get it ready for the skeleton - - int len = surf->array_len; - int src_stride = surf->stride; - int dst_stride = surf->stride - ( surf->array[VS::ARRAY_BONES].size + surf->array[VS::ARRAY_WEIGHTS].size ); - - for(int i=0;i<len;i++) { - const uint8_t *src = &surf->array_local[i*src_stride]; - uint8_t *dst = &base[i*dst_stride]; - memcpy(dst,src,dst_stride); - } - - - stride=dst_stride; - } - - - if (skeleton_valid) { - //transform stuff - - const uint8_t *src_weights=&surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs]; - const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; - int src_stride = surf->stride; - int count = surf->array_len; - const Transform *skeleton = &p_skeleton->bones[0]; - - for(int i=0;i<VS::ARRAY_MAX-1;i++) { - - const Surface::ArrayData& ad=surf->array[i]; - if (ad.size==0) - continue; - - int ofs = ad.ofs; - - - switch(i) { - - case VS::ARRAY_VERTEX: { - for(int k=0;k<count;k++) { - - float *ptr= (float*)&base[ofs+k*stride]; - const GLfloat* weights = reinterpret_cast<const GLfloat*>(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast<const GLfloat*>(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - - float w = weights[j]; - if (w==0) - break; - - //print_line("accum "+itos(i)+" += "+rtos(Math::ftoi(bones[j]))+" * "+skeleton[ Math::ftoi(bones[j]) ]+" * "+rtos(w)); - dst+=skeleton[ Math::fast_ftoi(bones[j]) ].xform(src) * w; - } - - ptr[0]=dst.x; - ptr[1]=dst.y; - ptr[2]=dst.z; - - } break; - - } break; - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: { - for(int k=0;k<count;k++) { - - float *ptr= (float*)&base[ofs+k*stride]; - const GLfloat* weights = reinterpret_cast<const GLfloat*>(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast<const GLfloat*>(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - - float w = weights[j]; - if (w==0) - break; - - //print_line("accum "+itos(i)+" += "+rtos(Math::ftoi(bones[j]))+" * "+skeleton[ Math::ftoi(bones[j]) ]+" * "+rtos(w)); - dst+=skeleton[ Math::fast_ftoi(bones[j]) ].basis.xform(src) * w; - } - - ptr[0]=dst.x; - ptr[1]=dst.y; - ptr[2]=dst.z; - - } break; - - } break; - } - } - - } - - } else { - - glBindBuffer(GL_ARRAY_BUFFER, surf->vertex_id); - }; - - - for (int i=0;i<(VS::ARRAY_MAX-1);i++) { - - const Surface::ArrayData& ad=surf->array[i]; - -// if (!gl_texcoord_shader[i]) -// continue; - - if (ad.size==0 || i==VS::ARRAY_BONES || i==VS::ARRAY_WEIGHTS || gl_client_states[i]==0 ) { - - if (gl_texcoord_index[i] != -1) { - glClientActiveTexture(GL_TEXTURE0+gl_texcoord_index[i]); - } - - if (gl_client_states[i] != 0) - glDisableClientState(gl_client_states[i]); - - if (i == VS::ARRAY_COLOR) { - glColor4f(last_color.r,last_color.g,last_color.b,last_color.a); - }; - continue; // this one is disabled. - } - - if (gl_texcoord_index[i] != -1) { - glClientActiveTexture(GL_TEXTURE0+gl_texcoord_index[i]); - } - - glEnableClientState(gl_client_states[i]); - - switch (i) { - - case VS::ARRAY_VERTEX: { - - glVertexPointer(3,ad.datatype,stride,&base[ad.ofs]); - - } break; /* fallthrough to normal */ - case VS::ARRAY_NORMAL: { - - glNormalPointer(ad.datatype,stride,&base[ad.ofs]); - } break; - case VS::ARRAY_COLOR: { - glColorPointer(4,ad.datatype,stride,&base[ad.ofs]); - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - glTexCoordPointer(2,ad.datatype,stride,&base[ad.ofs]); - } break; - case VS::ARRAY_TANGENT: { - - //glVertexAttribPointer(i, 4, use_VBO?GL_BYTE:GL_FLOAT, use_VBO?GL_TRUE:GL_FALSE, stride, &base[ad.ofs]); - - } break; - case VS::ARRAY_BONES: - case VS::ARRAY_WEIGHTS: { - - //do none - //glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, surf->stride, &base[ad.ofs]); - - } break; - case VS::ARRAY_INDEX: - ERR_PRINT("Bug"); - break; - }; - } - - - } break; - - default: break; - - }; - - return OK; -}; - -static const GLenum gl_primitive[]={ - GL_POINTS, - GL_LINES, - GL_LINE_STRIP, - GL_LINE_LOOP, - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN -}; - -static const GLenum gl_poly_primitive[4]={ - GL_POINTS, - GL_LINES, - GL_TRIANGLES, - //GL_QUADS - -}; - - -void RasterizerGLES1::_render(const Geometry *p_geometry,const Material *p_material, const Skeleton* p_skeleton, const GeometryOwner *p_owner) { - - - _rinfo.object_count++; - - switch(p_geometry->type) { - - case Geometry::GEOMETRY_SURFACE: { - - Surface *s = (Surface*)p_geometry; - - _rinfo.vertex_count+=s->array_len; - - if (s->packed && s->array_local==0) { - - float sc = (1.0/32767.0)*s->vertex_scale; - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glScalef(sc,sc,sc); - if (s->format&VS::ARRAY_FORMAT_TEX_UV) { - float uvs=(1.0/32767.0)*s->uv_scale; - //glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glScalef(uvs,uvs,uvs); - } - - - } - - - if (s->index_array_len>0) { - - if (s->index_array_local) { - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_SHORT:GL_UNSIGNED_SHORT, s->index_array_local); - - } else { - // print_line("indices: "+itos(s->index_array_local) ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); - glDrawElements(gl_primitive[s->primitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_SHORT:GL_UNSIGNED_SHORT,0); - } - - - } else { - - glDrawArrays(gl_primitive[s->primitive],0,s->array_len); - - }; - - if (s->packed && s->array_local==0) { - if (s->format&VS::ARRAY_FORMAT_TEX_UV) { - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - } - glPopMatrix(); - }; - } break; - - case Geometry::GEOMETRY_MULTISURFACE: { - - Surface *s = static_cast<const MultiMeshSurface*>(p_geometry)->surface; - const MultiMesh *mm = static_cast<const MultiMesh*>(p_owner); - int element_count=mm->elements.size(); - - if (element_count==0) - return; - - const MultiMesh::Element *elements=&mm->elements[0]; - - _rinfo.vertex_count+=s->array_len*element_count; - - - if (s->index_array_len>0) { - - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); - for(int i=0;i<element_count;i++) { - //glUniformMatrix4fv(material_shader.get_uniform_location(MaterialShaderGLES1::INSTANCE_TRANSFORM), 1, false, elements[i].matrix); - glDrawElements(gl_primitive[s->primitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_SHORT:GL_UNSIGNED_SHORT,0); - } - - - } else { - - for(int i=0;i<element_count;i++) { -// glUniformMatrix4fv(material_shader.get_uniform_location(MaterialShaderGLES1::INSTANCE_TRANSFORM), 1, false, elements[i].matrix); - glDrawArrays(gl_primitive[s->primitive],0,s->array_len); - } - - - }; - } break; - case Geometry::GEOMETRY_PARTICLES: { - - - //print_line("particulinas"); - const Particles *particles = static_cast<const Particles*>( p_geometry ); - ERR_FAIL_COND(!p_owner); - ParticlesInstance *particles_instance = (ParticlesInstance*)p_owner; - - ParticleSystemProcessSW &pp = particles_instance->particles_process; - float td = time_delta; //MIN(time_delta,1.0/10.0); - pp.process(&particles->data,particles_instance->transform,td); - ERR_EXPLAIN("A parameter in the particle system is not correct."); - ERR_FAIL_COND(!pp.valid); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - glBindBuffer(GL_ARRAY_BUFFER,0); - - - Transform camera; - if (shadow) - camera=shadow->transform; - else - camera=camera_transform; - - particle_draw_info.prepare(&particles->data,&pp,particles_instance->transform,camera); - - _rinfo.vertex_count+=4*particles->data.amount; - - { - static const Vector3 points[4]={ - Vector3(-1.0,1.0,0), - Vector3(1.0,1.0,0), - Vector3(1.0,-1.0,0), - Vector3(-1.0,-1.0,0) - }; - static const Vector3 uvs[4]={ - Vector3(0.0,0.0,0.0), - Vector3(1.0,0.0,0.0), - Vector3(1.0,1.0,0.0), - Vector3(0,1.0,0.0) - }; - static const Vector3 normals[4]={ - Vector3(0,0,1), - Vector3(0,0,1), - Vector3(0,0,1), - Vector3(0,0,1) - }; - - static const Plane tangents[4]={ - Plane(Vector3(1,0,0),0), - Plane(Vector3(1,0,0),0), - Plane(Vector3(1,0,0),0), - Plane(Vector3(1,0,0),0) - }; - - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - _gl_load_transform(camera_transform_inverse); - for(int i=0;i<particles->data.amount;i++) { - - ParticleSystemDrawInfoSW::ParticleDrawInfo &pinfo=*particle_draw_info.draw_info_order[i]; - if (!pinfo.data->active) - continue; - glPushMatrix(); - _gl_mult_transform(pinfo.transform); - - glColor4f(pinfo.color.r*last_color.r,pinfo.color.g*last_color.g,pinfo.color.b*last_color.b,pinfo.color.a*last_color.a); - _draw_primitive(4,points,normals,NULL,uvs,tangents); - glPopMatrix(); - - } - glPopMatrix(); - - } - - } break; - default: break; - }; - -}; - -void RasterizerGLES1::_setup_shader_params(const Material *p_material) { -#if 0 - int idx=0; - int tex_idx=0; - - for(Map<StringName,Variant>::Element *E=p_material->shader_cache->params.front();E;E=E->next(),idx++) { - - Variant v; // - v = E->get(); - const Map<StringName,Variant>::Element *F=p_material->shader_params.find(E->key()); - if (F) - v=F->get(); - - switch(v.get_type() ) { - case Variant::OBJECT: - case Variant::_RID: { - - RID tex=v; - if (!tex.is_valid()) - break; - - Texture *texture = texture_owner.get(tex); - if (!texture) - break; - glUniform1i( material_shader.get_custom_uniform_location(idx), tex_idx); - glActiveTexture(tex_idx); - glBindTexture(texture->target,texture->tex_id); - - } break; - case Variant::COLOR: { - - Color c=v; - material_shader.set_custom_uniform(idx,Vector3(c.r,c.g,c.b)); - } break; - default: { - - material_shader.set_custom_uniform(idx,v); - } break; - } - - } -#endif - -} - -void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reverse_cull) { - - const Material *prev_material=NULL; - uint64_t prev_light_key=0; - const Skeleton *prev_skeleton=NULL; - const Geometry *prev_geometry=NULL; - - Geometry::Type prev_geometry_type=Geometry::GEOMETRY_INVALID; - - for (int i=0;i<p_render_list->element_count;i++) { - - RenderList::Element *e = p_render_list->elements[i]; - const Material *material = e->material; - uint64_t light_key = e->light_key; - const Skeleton *skeleton = e->skeleton; - const Geometry *geometry = e->geometry; - - if (material!=prev_material || geometry->type!=prev_geometry_type) { - _setup_material(e->geometry,material); - _rinfo.mat_change_count++; - //_setup_material_overrides(e->material,NULL,material_overrides); - //_setup_material_skeleton(material,skeleton); - } else { - - if (prev_skeleton!=skeleton) { - //_setup_material_skeleton(material,skeleton); - }; - } - - - if (geometry!=prev_geometry || geometry->type!=prev_geometry_type || prev_skeleton!=skeleton) { - - _setup_geometry(geometry, material,e->skeleton,e->instance->morph_values.ptr()); - }; - - if (i==0 || light_key!=prev_light_key) - _setup_lights(e->lights,e->light_count); - - _set_cull(e->mirror,p_reverse_cull); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glPushMatrix(); - - - if (e->instance->billboard || e->instance->depth_scale) { - - Transform xf=e->instance->transform; - if (e->instance->depth_scale) { - - if (camera_projection.matrix[3][3]) { - //orthogonal matrix, try to do about the same - //with viewport size - //real_t w = Math::abs( 1.0/(2.0*(p_projection.matrix[0][0])) ); - real_t h = Math::abs( 1.0/(2.0*camera_projection.matrix[1][1]) ); - float sc = (h*2.0); //consistent with Y-fov - xf.basis.scale( Vector3(sc,sc,sc)); - } else { - //just scale by depth - real_t sc = -camera_plane.distance_to(xf.origin); - xf.basis.scale( Vector3(sc,sc,sc)); - } - } - - if (e->instance->billboard) { - - Vector3 scale = xf.basis.get_scale(); - xf.set_look_at(xf.origin,xf.origin+camera_transform.get_basis().get_axis(2),camera_transform.get_basis().get_axis(1)); - xf.basis.scale(scale); - } - _gl_mult_transform(xf); // for fixed pipeline - - } else { - _gl_mult_transform(e->instance->transform); // for fixed pipeline - } - - - - //bool changed_shader = material_shader.bind(); - //if ( changed_shader && material->shader_cache && !material->shader_cache->params.empty()) - // _setup_shader_params(material); - - _render(geometry, material, skeleton,e->owner); - - - - prev_material=material; - prev_skeleton=skeleton; - prev_geometry=geometry; - prev_light_key=e->light_key; - prev_geometry_type=geometry->type; - } - - - -}; - - - -void RasterizerGLES1::end_scene() { - - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - depth_write=true; - depth_test=true; - - if (scene_fx && scene_fx->skybox_active) { - - //skybox - } else if (scene_fx && scene_fx->bgcolor_active) { - - glClearColor(scene_fx->bgcolor.r,scene_fx->bgcolor.g,scene_fx->bgcolor.b,1.0); - - } else { - - glClearColor(0.3,0.3,0.3,1.0); - } -#ifdef GLES_OVER_GL - //glClearDepth(1.0); -#else - //glClearDepthf(1.0); -#endif - - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - if (scene_fx && scene_fx->fog_active) { - - /* - glEnable(GL_FOG); - glFogf(GL_FOG_MODE,GL_LINEAR); - glFogf(GL_FOG_DENSITY,scene_fx->fog_attenuation); - glFogf(GL_FOG_START,scene_fx->fog_near); - glFogf(GL_FOG_END,scene_fx->fog_far); - glFogfv(GL_FOG_COLOR,scene_fx->fog_color_far.components); - glLightfv(GL_LIGHT5,GL_DIFFUSE,scene_fx->fog_color_near.components); - - material_shader.set_conditional( MaterialShaderGLES1::USE_FOG,true); - */ - } - - - - for(int i=0;i<directional_light_count;i++) { - - glEnable(GL_LIGHT0+i); - _setup_light(directional_lights[i],i); - } - - opaque_render_list.sort_mat_light(); - - //material_shader.set_uniform_camera(MaterialShaderGLES1::PROJECTION_MATRIX, camera_projection); - - /* - printf("setting projection to "); - for (int i=0; i<16; i++) { - printf("%f, ", ((float*)camera_projection.matrix)[i]); - }; - printf("\n"); - - print_line(String("setting camera to ")+camera_transform_inverse); - */ -// material_shader.set_uniform_default(MaterialShaderGLES1::CAMERA_INVERSE, camera_transform_inverse); - - //projection - //glEnable(GL_RESCALE_NORMAL); - glEnable(GL_NORMALIZE); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(&camera_projection.matrix[0][0]); - //modelview (fixedpipie) - glMatrixMode(GL_MODELVIEW); - _gl_load_transform(camera_transform_inverse); - glPushMatrix(); - - glDisable(GL_BLEND); - - blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - lighting=true; - glEnable(GL_LIGHTING); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - _render_list_forward(&opaque_render_list); - - - alpha_render_list.sort_z(); - glEnable(GL_BLEND); - - _render_list_forward(&alpha_render_list); - - glPopMatrix(); - - -// material_shader.set_conditional( MaterialShaderGLES1::USE_FOG,false); - - _debug_shadows(); -} -void RasterizerGLES1::end_shadow_map() { -#if 0 - ERR_FAIL_COND(!shadow); - ERR_FAIL_INDEX(shadow_pass,shadow->shadow_buffers.size()); - - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); - glEnable(GL_DEPTH_TEST); - glDepthMask(true); - - - ShadowBuffer *sb = shadow->shadow_buffers[shadow_pass]; - - ERR_FAIL_COND(!sb); - - glBindFramebuffer(GL_FRAMEBUFFER, sb->fbo); - glViewport(0, 0, sb->size, sb->size); - - glColorMask(0, 0, 0, 0); - - glEnable(GL_POLYGON_OFFSET_FILL); - //glPolygonOffset(4,8); - glPolygonOffset( 4.0f, 4096.0f); - glPolygonOffset( 8.0f, 16.0f); - - glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); - CameraMatrix cm; - float z_near,z_far; - Transform light_transform; - - float dp_direction=0.0; - bool flip_facing=false; - - switch(shadow->base->type) { - - case VS::LIGHT_DIRECTIONAL: { - - cm = shadow->custom_projection; - light_transform=shadow->custom_transform; - z_near=cm.get_z_near(); - z_far=cm.get_z_far(); - - } break; - case VS::LIGHT_OMNI: { - - material_shader.set_conditional(MaterialShaderGLES1::USE_DUAL_PARABOLOID,true); - dp_direction = shadow_pass?1.0:0.0; - flip_facing = (shadow_pass == 1); - light_transform=shadow->transform; - z_near=0; - z_far=shadow->base->vars[ VS::LIGHT_VAR_RADIUS ]; - } break; - case VS::LIGHT_SPOT: { - - float far = shadow->base->vars[ VS::LIGHT_VAR_RADIUS ]; - ERR_FAIL_COND( far<=0 ); - float near= far/200.0; - if (near<0.05) - near=0.05; - - float angle = shadow->base->vars[ VS::LIGHT_VAR_SPOT_ANGLE ]; - - cm.set_perspective( angle*2.0, 1.0, near, far ); - shadow->projection=cm; // cache - light_transform=shadow->transform; - z_near=cm.get_z_near(); - z_far=cm.get_z_far(); - - } break; - } - - Transform light_transform_inverse = light_transform.inverse(); - - opaque_render_list.sort_mat(); - - glLightf(GL_LIGHT5,GL_LINEAR_ATTENUATION,z_near); - glLightf(GL_LIGHT5,GL_QUADRATIC_ATTENUATION,z_far); - glLightf(GL_LIGHT5,GL_CONSTANT_ATTENUATION,dp_direction); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(&cm.matrix[0][0]); - glMatrixMode(GL_MODELVIEW); - _gl_load_transform(light_transform_inverse); - glPushMatrix(); - - for(int i=0;i<4;i++) { - for(int j=0;j<3;j++) { - - material_shader.set_conditional(_gl_light_version[i][j],false); //start false by default - } - material_shader.set_conditional(_gl_light_shadow[i],false); - } - - _render_list_forward(&opaque_render_list,flip_facing); - - material_shader.set_conditional(MaterialShaderGLES1::USE_DUAL_PARABOLOID,false); - glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); - if (framebuffer.active) - glBindFramebufferEXT(GL_FRAMEBUFFER,framebuffer.fbo); - else - glBindFramebufferEXT(GL_FRAMEBUFFER,0); - - glDisable(GL_POLYGON_OFFSET_FILL); - - glColorMask(1, 1, 1, 1); - shadow=NULL; -#endif -} - -void RasterizerGLES1::_debug_draw_shadow(ShadowBuffer *p_buffer, const Rect2& p_rect) { - -/* - - Transform modelview; - modelview.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f); - modelview.scale( Vector3( 2.0f / viewport.width, -2.0f / viewport.height, 1.0f ) ); - modelview.translate(p_rect.pos.x, p_rect.pos.y, 0); - material_shader.set_uniform_default(MaterialShaderGLES1::MODELVIEW_TRANSFORM, *e->transform); - glBindTexture(GL_TEXTURE_2D,p_buffer->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - - Vector3 coords[4]= { - Vector3(p_rect.pos.x, p_rect.pos.y, 0 ), - Vector3(p_rect.pos.x+p_rect.size.width, - p_rect.pos.y, 0 ), - Vector3(p_rect.pos.x+p_rect.size.width, - p_rect.pos.y+p_rect.size.height, 0 ), - Vector3(p_rect.pos.x, - p_rect.pos.y+p_rect.size.height, 0 ) - }; - - Vector3 texcoords[4]={ - Vector3( 0.0f,0.0f, 0), - Vector3( 1.0f,0.0f, 0), - Vector3( 1.0f, 1.0f, 0), - Vector3( 0.0f, 1.0f, 0), - }; - - _draw_primitive(4,coords,0,0,texcoords); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); -*/ -} - -void RasterizerGLES1::_debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,Point2& ofs) { - - -// Size2 debug_size(128,128); - Size2 debug_size(512,512); - - for (int i=0;i<p_shadows.size();i++) { - - ShadowBuffer *sb=&p_shadows[i]; - - if (!sb->owner) - continue; - - if (sb->owner->base->type==VS::LIGHT_DIRECTIONAL) { - - if (sb->owner->shadow_pass!=scene_pass-1) - continue; - } else { - - if (sb->owner->shadow_pass!=frame) - continue; - } - _debug_draw_shadow(sb, Rect2( ofs, debug_size )); - ofs.x+=debug_size.x; - if ( (ofs.x+debug_size.x) > viewport.width ) { - - ofs.x=0; - ofs.y+=debug_size.y; - } - } - -} - - -void RasterizerGLES1::_debug_shadows() { - - return; -#if 0 - canvas_begin(); - glUseProgram(0); - glDisable(GL_BLEND); - Size2 ofs; - - /* - for(int i=0;i<16;i++) { - glActiveTexture(GL_TEXTURE0+i); - //glDisable(GL_TEXTURE_2D); - } - glActiveTexture(GL_TEXTURE0); - //glEnable(GL_TEXTURE_2D); - */ - - - _debug_draw_shadows_type(near_shadow_buffers,ofs); - _debug_draw_shadows_type(far_shadow_buffers,ofs); -#endif -} - -void RasterizerGLES1::end_frame() { - - /* - if (framebuffer.active) { - - canvas_begin(); //resets stuff and goes back to fixedpipe - glBindFramebuffer(GL_FRAMEBUFFER,0); - - //copy to main bufferz - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D,framebuffer.color); - glBegin(GL_QUADS); - glTexCoord2f(0,0); - glVertex2f(-1,-1); - glTexCoord2f(0,1); - glVertex2f(-1,+1); - glTexCoord2f(1,1); - glVertex2f(+1,+1); - glTexCoord2f(1,0); - glVertex2f(+1,-1); - glEnd(); - - - } - */ - - //print_line("VTX: "+itos(_rinfo.vertex_count)+" OBJ: "+itos(_rinfo.object_count)+" MAT: "+itos(_rinfo.mat_change_count)+" SHD: "+itos(_rinfo.shader_change_count)); - - OS::get_singleton()->swap_buffers(); -} - -/* CANVAS API */ - - -void RasterizerGLES1::reset_state() { - - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - glBindBuffer(GL_ARRAY_BUFFER,0); - - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glColor4f(1,1,1,1); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); -// glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); - canvas_blend=VS::MATERIAL_BLEND_MODE_MIX; - glLineWidth(1.0); - glDisable(GL_LIGHTING); - -} - -_FORCE_INLINE_ static void _set_glcoloro(const Color& p_color,const float p_opac) { - - glColor4f(p_color.r, p_color.g, p_color.b, p_color.a*p_opac); -} - - -void RasterizerGLES1::canvas_begin() { - - - reset_state(); - canvas_opacity=1.0; - glEnable(GL_BLEND); - - -} - -void RasterizerGLES1::canvas_disable_blending() { - - glDisable(GL_BLEND); -} - -void RasterizerGLES1::canvas_set_opacity(float p_opacity) { - - canvas_opacity = p_opacity; -} - -void RasterizerGLES1::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { - - switch(p_mode) { - - case VS::MATERIAL_BLEND_MODE_MIX: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - case VS::MATERIAL_BLEND_MODE_ADD: { - - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - - } break; - case VS::MATERIAL_BLEND_MODE_SUB: { - - //glBlendEquation(GL_FUNC_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - } break; - case VS::MATERIAL_BLEND_MODE_MUL: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - - } - -} - - -void RasterizerGLES1::canvas_begin_rect(const Matrix32& p_transform) { - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(2.0 / viewport.width, -2.0 / viewport.height, 0); - glTranslatef((-(viewport.width / 2.0)), (-(viewport.height / 2.0)), 0); - _gl_mult_transform(p_transform); - - glPushMatrix(); - -} - -void RasterizerGLES1::canvas_set_clip(bool p_clip, const Rect2& p_rect) { - - if (p_clip) { - - glEnable(GL_SCISSOR_TEST); - // glScissor(viewport.x+p_rect.pos.x,viewport.y+ (viewport.height-(p_rect.pos.y+p_rect.size.height)), - //p_rect.size.width,p_rect.size.height); - //glScissor(p_rect.pos.x,(viewport.height-(p_rect.pos.y+p_rect.size.height)),p_rect.size.width,p_rect.size.height); - glScissor(viewport.x+p_rect.pos.x,viewport.y+ (window_size.y-(p_rect.pos.y+p_rect.size.height)), - p_rect.size.width,p_rect.size.height); - } else { - - glDisable(GL_SCISSOR_TEST); - } - - -} - -void RasterizerGLES1::canvas_end_rect() { - - glPopMatrix(); -} - -void RasterizerGLES1::canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width) { - - glDisable(GL_TEXTURE_2D); - _set_glcoloro( p_color,canvas_opacity ); - - Vector3 verts[2]={ - Vector3(p_from.x,p_from.y,0), - Vector3(p_to.x,p_to.y,0) - }; - Color colors[2]={ - p_color, - p_color - }; - colors[0].a*=canvas_opacity; - colors[1].a*=canvas_opacity; - glLineWidth(p_width); - _draw_primitive(2,verts,0,colors,0); - -} - -static void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_flip_h=false,bool p_flip_v=false ) { - - - Vector3 texcoords[4]= { - Vector3( p_src_region.pos.x/p_tex_size.width, - p_src_region.pos.y/p_tex_size.height, 0), - - Vector3((p_src_region.pos.x+p_src_region.size.width)/p_tex_size.width, - p_src_region.pos.y/p_tex_size.height, 0), - - Vector3( (p_src_region.pos.x+p_src_region.size.width)/p_tex_size.width, - (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height, 0), - - Vector3( p_src_region.pos.x/p_tex_size.width, - (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height, 0) - }; - - - if (p_flip_h) { - SWAP( texcoords[0], texcoords[1] ); - SWAP( texcoords[2], texcoords[3] ); - } - if (p_flip_v) { - SWAP( texcoords[1], texcoords[2] ); - SWAP( texcoords[0], texcoords[3] ); - } - - Vector3 coords[4]= { - Vector3( p_rect.pos.x, p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width, p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height, 0 ), - Vector3( p_rect.pos.x,p_rect.pos.y+p_rect.size.height, 0 ) - }; - - _draw_primitive(4,coords,0,0,texcoords); -} - -static void _draw_quad(const Rect2& p_rect) { - - Vector3 coords[4]= { - Vector3( p_rect.pos.x,p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width,p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width,p_rect.pos.y+p_rect.size.height, 0 ), - Vector3( p_rect.pos.x,p_rect.pos.y+p_rect.size.height, 0 ) - }; - - _draw_primitive(4,coords,0,0,0); - -} - - -void RasterizerGLES1::canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate) { - - _set_glcoloro( p_modulate,canvas_opacity ); - - if ( p_texture.is_valid() ) { - - glEnable(GL_TEXTURE_2D); - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - - if (!(p_flags&CANVAS_RECT_REGION)) { - - Rect2 region = Rect2(0,0,texture->width,texture->height); - _draw_textured_quad(p_rect,region,region.size,p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V); - - } else { - - - _draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V ); - - } - } else { - - glDisable(GL_TEXTURE_2D); - _draw_quad( p_rect ); - - } - - -} -void RasterizerGLES1::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) { - - _set_glcoloro( p_modulate,canvas_opacity ); - - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - - - /* CORNERS */ - - _draw_textured_quad( // top left - Rect2( p_rect.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])), - Rect2( Point2(), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // top right - Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])), - Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],0), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])), - Size2( texture->width, texture->height ) ); - - - _draw_textured_quad( // bottom left - Rect2( Point2(p_rect.pos.x,p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])), - Rect2( Point2(0,texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // bottom right - Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])), - Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])), - Size2( texture->width, texture->height ) ); - - Rect2 rect_center( p_rect.pos+Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( p_rect.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], p_rect.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] )); - - Rect2 src_center( Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( texture->width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], texture->height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] )); - - - _draw_textured_quad( // top - Rect2( Point2(rect_center.pos.x,p_rect.pos.y),Size2(rect_center.size.width,p_margin[MARGIN_TOP])), - Rect2( Point2(p_margin[MARGIN_LEFT],0), Size2(src_center.size.width,p_margin[MARGIN_TOP])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // bottom - Rect2( Point2(rect_center.pos.x,rect_center.pos.y+rect_center.size.height),Size2(rect_center.size.width,p_margin[MARGIN_BOTTOM])), - Rect2( Point2(p_margin[MARGIN_LEFT],src_center.pos.y+src_center.size.height), Size2(src_center.size.width,p_margin[MARGIN_BOTTOM])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // left - Rect2( Point2(p_rect.pos.x,rect_center.pos.y),Size2(p_margin[MARGIN_LEFT],rect_center.size.height)), - Rect2( Point2(0,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_LEFT],src_center.size.height)), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // right - Rect2( Point2(rect_center.pos.x+rect_center.size.width,rect_center.pos.y),Size2(p_margin[MARGIN_RIGHT],rect_center.size.height)), - Rect2( Point2(src_center.pos.x+src_center.size.width,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_RIGHT],src_center.size.height)), - Size2( texture->width, texture->height ) ); - - if (p_draw_center) { - - _draw_textured_quad( - rect_center, - src_center, - Size2( texture->width, texture->height )); - } - -} -void RasterizerGLES1::canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width) { - - ERR_FAIL_COND(p_points.size()<1); - Vector3 verts[4]; - Vector3 uvs[4]; - - _set_glcoloro( Color(1,1,1),canvas_opacity ); - - for(int i=0;i<p_points.size();i++) { - - verts[i]=Vector3(p_points[i].x,p_points[i].y,0); - } - - for(int i=0;i<p_uvs.size();i++) { - - uvs[i]=Vector3(p_uvs[i].x,p_uvs[i].y,0); - } - - if (p_texture.is_valid()) { - glEnable(GL_TEXTURE_2D); - Texture *texture = texture_owner.get( p_texture ); - if (texture) { - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - } - } - - glLineWidth(p_width); - _draw_primitive(p_points.size(),&verts[0],NULL,p_colors.size()?&p_colors[0]:NULL,p_uvs.size()?uvs:NULL); - -} - -static const int _max_draw_poly_indices = 8*1024; -static uint16_t _draw_poly_indices[_max_draw_poly_indices]; -static float _verts3[_max_draw_poly_indices]; - -void RasterizerGLES1::canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) { - - bool do_colors=false; - - //reset_state(); - if (p_singlecolor) { - Color m = *p_colors; - m.a*=canvas_opacity; - glColor4f(m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glColor4f(1, 1, 1, canvas_opacity); - } else - do_colors=true; - - glColor4f(1, 1, 1, 1); - - Texture* texture = NULL; - if (p_texture.is_valid()) { - glEnable(GL_TEXTURE_2D); - texture = texture_owner.get( p_texture ); - if (texture) { - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - } - } - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)p_vertices); - if (do_colors) { - - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4,GL_FLOAT, 0, p_colors); - - } else { - glDisableClientState(GL_COLOR_ARRAY); - } - - if (texture && p_uvs) { - - glClientActiveTexture(GL_TEXTURE0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, p_uvs); - - } else { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - - if (p_indices) { - - for (int i=0; i<p_vertex_count; i++) { - _draw_poly_indices[i] = p_indices[i]; - }; - glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, _draw_poly_indices ); - } else { - - glDrawArrays(GL_TRIANGLES,0,p_vertex_count); - } - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - -} - -void RasterizerGLES1::canvas_set_transform(const Matrix32& p_transform) { - - //restore - glPopMatrix(); - glPushMatrix(); - //set - _gl_mult_transform(p_transform); -} - -/* FX */ - -RID RasterizerGLES1::fx_create() { - - FX *fx = memnew( FX ); - ERR_FAIL_COND_V(!fx,RID()); - return fx_owner.make_rid(fx); - -} -void RasterizerGLES1::fx_get_effects(RID p_fx,List<String> *p_effects) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - p_effects->clear(); - p_effects->push_back("bgcolor"); - p_effects->push_back("skybox"); - p_effects->push_back("antialias"); - //p_effects->push_back("hdr"); - p_effects->push_back("glow"); // glow has a bloom parameter, too - p_effects->push_back("ssao"); - p_effects->push_back("fog"); - p_effects->push_back("dof_blur"); - p_effects->push_back("toon"); - p_effects->push_back("edge"); - -} -void RasterizerGLES1::fx_set_active(RID p_fx,const String& p_effect, bool p_active) { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - if (p_effect=="bgcolor") - fx->bgcolor_active=p_active; - else if (p_effect=="skybox") - fx->skybox_active=p_active; - else if (p_effect=="antialias") - fx->antialias_active=p_active; - else if (p_effect=="glow") - fx->glow_active=p_active; - else if (p_effect=="ssao") - fx->ssao_active=p_active; - else if (p_effect=="fog") - fx->fog_active=p_active; -// else if (p_effect=="dof_blur") -// fx->dof_blur_active=p_active; - else if (p_effect=="toon") - fx->toon_active=p_active; - else if (p_effect=="edge") - fx->edge_active=p_active; -} -bool RasterizerGLES1::fx_is_active(RID p_fx,const String& p_effect) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND_V(!fx,false); - - if (p_effect=="bgcolor") - return fx->bgcolor_active; - else if (p_effect=="skybox") - return fx->skybox_active; - else if (p_effect=="antialias") - return fx->antialias_active; - else if (p_effect=="glow") - return fx->glow_active; - else if (p_effect=="ssao") - return fx->ssao_active; - else if (p_effect=="fog") - return fx->fog_active; - //else if (p_effect=="dof_blur") - // return fx->dof_blur_active; - else if (p_effect=="toon") - return fx->toon_active; - else if (p_effect=="edge") - return fx->edge_active; - - return false; -} -void RasterizerGLES1::fx_get_effect_params(RID p_fx,const String& p_effect,List<PropertyInfo> *p_params) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - - if (p_effect=="bgcolor") { - - p_params->push_back( PropertyInfo( Variant::COLOR, "color" ) ); - } else if (p_effect=="skybox") { - p_params->push_back( PropertyInfo( Variant::_RID, "cubemap" ) ); - } else if (p_effect=="antialias") { - - p_params->push_back( PropertyInfo( Variant::REAL, "tolerance", PROPERTY_HINT_RANGE,"1,128,1" ) ); - - } else if (p_effect=="glow") { - - p_params->push_back( PropertyInfo( Variant::INT, "passes", PROPERTY_HINT_RANGE,"1,4,1" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "attenuation", PROPERTY_HINT_RANGE,"0.01,8.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "bloom", PROPERTY_HINT_RANGE,"-1.0,1.0,0.01" ) ); - - } else if (p_effect=="ssao") { - - p_params->push_back( PropertyInfo( Variant::REAL, "radius", PROPERTY_HINT_RANGE,"0.0,16.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "max_distance", PROPERTY_HINT_RANGE,"0.0,256.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "range_max", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "range_min", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "attenuation", PROPERTY_HINT_RANGE,"0.0,8.0,0.01" ) ); - - } else if (p_effect=="fog") { - - p_params->push_back( PropertyInfo( Variant::REAL, "begin", PROPERTY_HINT_RANGE,"0.0,8192,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "end", PROPERTY_HINT_RANGE,"0.0,8192,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "attenuation", PROPERTY_HINT_RANGE,"0.0,8.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::COLOR, "color_begin" ) ); - p_params->push_back( PropertyInfo( Variant::COLOR, "color_end" ) ); - p_params->push_back( PropertyInfo( Variant::BOOL, "fog_bg" ) ); - -// } else if (p_effect=="dof_blur") { -// return fx->dof_blur_active; - } else if (p_effect=="toon") { - p_params->push_back( PropertyInfo( Variant::REAL, "treshold", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "soft", PROPERTY_HINT_RANGE,"0.001,1.0,0.001" ) ); - } else if (p_effect=="edge") { - - } -} -Variant RasterizerGLES1::fx_get_effect_param(RID p_fx,const String& p_effect,const String& p_param) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND_V(!fx,Variant()); - - if (p_effect=="bgcolor") { - - if (p_param=="color") - return fx->bgcolor; - } else if (p_effect=="skybox") { - if (p_param=="cubemap") - return fx->skybox_cubemap; - } else if (p_effect=="antialias") { - - if (p_param=="tolerance") - return fx->antialias_tolerance; - - } else if (p_effect=="glow") { - - if (p_param=="passes") - return fx->glow_passes; - if (p_param=="attenuation") - return fx->glow_attenuation; - if (p_param=="bloom") - return fx->glow_bloom; - - } else if (p_effect=="ssao") { - - if (p_param=="attenuation") - return fx->ssao_attenuation; - if (p_param=="max_distance") - return fx->ssao_max_distance; - if (p_param=="range_max") - return fx->ssao_range_max; - if (p_param=="range_min") - return fx->ssao_range_min; - if (p_param=="radius") - return fx->ssao_radius; - - } else if (p_effect=="fog") { - - if (p_param=="begin") - return fx->fog_near; - if (p_param=="end") - return fx->fog_far; - if (p_param=="attenuation") - return fx->fog_attenuation; - if (p_param=="color_begin") - return fx->fog_color_near; - if (p_param=="color_end") - return fx->fog_color_far; - if (p_param=="fog_bg") - return fx->fog_bg; -// } else if (p_effect=="dof_blur") { -// return fx->dof_blur_active; - } else if (p_effect=="toon") { - if (p_param=="treshold") - return fx->toon_treshold; - if (p_param=="soft") - return fx->toon_soft; - - } else if (p_effect=="edge") { - - } - return Variant(); -} -void RasterizerGLES1::fx_set_effect_param(RID p_fx,const String& p_effect, const String& p_param, const Variant& p_value) { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - if (p_effect=="bgcolor") { - - if (p_param=="color") - fx->bgcolor=p_value; - } else if (p_effect=="skybox") { - if (p_param=="cubemap") - fx->skybox_cubemap=p_value; - - } else if (p_effect=="antialias") { - - if (p_param=="tolerance") - fx->antialias_tolerance=p_value; - - } else if (p_effect=="glow") { - - if (p_param=="passes") - fx->glow_passes=p_value; - if (p_param=="attenuation") - fx->glow_attenuation=p_value; - if (p_param=="bloom") - fx->glow_bloom=p_value; - - } else if (p_effect=="ssao") { - - if (p_param=="attenuation") - fx->ssao_attenuation=p_value; - if (p_param=="radius") - fx->ssao_radius=p_value; - if (p_param=="max_distance") - fx->ssao_max_distance=p_value; - if (p_param=="range_max") - fx->ssao_range_max=p_value; - if (p_param=="range_min") - fx->ssao_range_min=p_value; - - } else if (p_effect=="fog") { - - if (p_param=="begin") - fx->fog_near=p_value; - if (p_param=="end") - fx->fog_far=p_value; - if (p_param=="attenuation") - fx->fog_attenuation=p_value; - if (p_param=="color_begin") - fx->fog_color_near=p_value; - if (p_param=="color_end") - fx->fog_color_far=p_value; - if (p_param=="fog_bg") - fx->fog_bg=p_value; -// } else if (p_effect=="dof_blur") { -// fx->dof_blur_active=p_value; - } else if (p_effect=="toon") { - - if (p_param=="treshold") - fx->toon_treshold=p_value; - if (p_param=="soft") - fx->toon_soft=p_value; - - } else if (p_effect=="edge") { - - } - -} - -/* ENVIRONMENT */ - -RID RasterizerGLES1::environment_create() { - - Environment * env = memnew( Environment ); - return environment_owner.make_rid(env); -} - -void RasterizerGLES1::environment_set_background(RID p_env,VS::EnvironmentBG p_bg) { - - ERR_FAIL_INDEX(p_bg,VS::ENV_BG_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_mode=p_bg; -} - -VS::EnvironmentBG RasterizerGLES1::environment_get_background(RID p_env) const{ - - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,VS::ENV_BG_MAX); - return env->bg_mode; -} - -void RasterizerGLES1::environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_BG_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_param[p_param]=p_value; - -} -Variant RasterizerGLES1::environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_BG_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->bg_param[p_param]; - -} - -void RasterizerGLES1::environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled){ - - ERR_FAIL_INDEX(p_effect,VS::ENV_FX_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_enabled[p_effect]=p_enabled; -} -bool RasterizerGLES1::environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const{ - - ERR_FAIL_INDEX_V(p_effect,VS::ENV_FX_MAX,false); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,false); - return env->fx_enabled[p_effect]; - -} - -void RasterizerGLES1::environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_FX_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_param[p_param]=p_value; -} -Variant RasterizerGLES1::environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_FX_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->fx_param[p_param]; - -} - -/*MISC*/ - -bool RasterizerGLES1::is_texture(const RID& p_rid) const { - - return texture_owner.owns(p_rid); -} -bool RasterizerGLES1::is_material(const RID& p_rid) const { - - return material_owner.owns(p_rid); -} -bool RasterizerGLES1::is_mesh(const RID& p_rid) const { - - return mesh_owner.owns(p_rid); -} - -bool RasterizerGLES1::is_immediate(const RID& p_rid) const { - - return immediate_owner.owns(p_rid); -} - -bool RasterizerGLES1::is_multimesh(const RID& p_rid) const { - - return multimesh_owner.owns(p_rid); -} -bool RasterizerGLES1::is_particles(const RID &p_beam) const { - - return particles_owner.owns(p_beam); -} - -bool RasterizerGLES1::is_light(const RID& p_rid) const { - - return light_owner.owns(p_rid); -} -bool RasterizerGLES1::is_light_instance(const RID& p_rid) const { - - return light_instance_owner.owns(p_rid); -} -bool RasterizerGLES1::is_particles_instance(const RID& p_rid) const { - - return particles_instance_owner.owns(p_rid); -} -bool RasterizerGLES1::is_skeleton(const RID& p_rid) const { - - return skeleton_owner.owns(p_rid); -} -bool RasterizerGLES1::is_environment(const RID& p_rid) const { - - return environment_owner.owns(p_rid); -} -bool RasterizerGLES1::is_fx(const RID& p_rid) const { - - return fx_owner.owns(p_rid); -} -bool RasterizerGLES1::is_shader(const RID& p_rid) const { - - return false; -} - -void RasterizerGLES1::free(const RID& p_rid) { - - if (texture_owner.owns(p_rid)) { - - // delete the texture - Texture *texture = texture_owner.get(p_rid); - - glDeleteTextures( 1,&texture->tex_id ); - _rinfo.texture_mem-=texture->total_data_size; - texture_owner.free(p_rid); - memdelete(texture); - - } else if (shader_owner.owns(p_rid)) { - - // delete the texture - Shader *shader = shader_owner.get(p_rid); - - - - shader_owner.free(p_rid); - memdelete(shader); - - } else if (material_owner.owns(p_rid)) { - - Material *material = material_owner.get( p_rid ); - ERR_FAIL_COND(!material); - - material_owner.free(p_rid); - memdelete(material); - - } else if (mesh_owner.owns(p_rid)) { - - Mesh *mesh = mesh_owner.get(p_rid); - ERR_FAIL_COND(!mesh); - for (int i=0;i<mesh->surfaces.size();i++) { - - Surface *surface = mesh->surfaces[i]; - if (surface->array_local != 0) { - memfree(surface->array_local); - }; - if (surface->index_array_local != 0) { - memfree(surface->index_array_local); - }; - - if (mesh->morph_target_count>0) { - - for(int i=0;i<mesh->morph_target_count;i++) { - - memfree(surface->morph_targets_local[i].array); - } - memfree(surface->morph_targets_local); - surface->morph_targets_local=NULL; - } - - if (surface->vertex_id) - glDeleteBuffers(1,&surface->vertex_id); - if (surface->index_id) - glDeleteBuffers(1,&surface->index_id); - - memdelete( surface ); - }; - - mesh->surfaces.clear(); - - mesh_owner.free(p_rid); - memdelete(mesh); - - } else if (multimesh_owner.owns(p_rid)) { - - MultiMesh *multimesh = multimesh_owner.get(p_rid); - ERR_FAIL_COND(!multimesh); - - multimesh_owner.free(p_rid); - memdelete(multimesh); - - } else if (particles_owner.owns(p_rid)) { - - Particles *particles = particles_owner.get(p_rid); - ERR_FAIL_COND(!particles); - - particles_owner.free(p_rid); - memdelete(particles); - } else if (immediate_owner.owns(p_rid)) { - - Immediate *immediate = immediate_owner.get(p_rid); - ERR_FAIL_COND(!immediate); - - immediate_owner.free(p_rid); - memdelete(immediate); - } else if (particles_instance_owner.owns(p_rid)) { - - ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); - ERR_FAIL_COND(!particles_isntance); - - particles_instance_owner.free(p_rid); - memdelete(particles_isntance); - - } else if (skeleton_owner.owns(p_rid)) { - - Skeleton *skeleton = skeleton_owner.get( p_rid ); - ERR_FAIL_COND(!skeleton) - - skeleton_owner.free(p_rid); - memdelete(skeleton); - - } else if (light_owner.owns(p_rid)) { - - Light *light = light_owner.get( p_rid ); - ERR_FAIL_COND(!light) - - light_owner.free(p_rid); - memdelete(light); - - } else if (light_instance_owner.owns(p_rid)) { - - LightInstance *light_instance = light_instance_owner.get( p_rid ); - ERR_FAIL_COND(!light_instance); - light_instance->clear_shadow_buffers(); - light_instance_owner.free(p_rid); - memdelete( light_instance ); - - } else if (fx_owner.owns(p_rid)) { - - FX *fx = fx_owner.get( p_rid ); - ERR_FAIL_COND(!fx); - - fx_owner.free(p_rid); - memdelete( fx ); - - } else if (environment_owner.owns(p_rid)) { - - Environment *env = environment_owner.get( p_rid ); - ERR_FAIL_COND(!env); - - environment_owner.free(p_rid); - memdelete( env ); - }; -} - - -void RasterizerGLES1::custom_shade_model_set_shader(int p_model, RID p_shader) { - - -}; - -RID RasterizerGLES1::custom_shade_model_get_shader(int p_model) const { - - return RID(); -}; - -void RasterizerGLES1::custom_shade_model_set_name(int p_model, const String& p_name) { - -}; - -String RasterizerGLES1::custom_shade_model_get_name(int p_model) const { - - return String(); -}; - -void RasterizerGLES1::custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info) { - -}; - -void RasterizerGLES1::custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const { - -}; - - -void RasterizerGLES1::ShadowBuffer::init(int p_size) { - - -#if 0 - size=p_size; - - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &depth); - ERR_FAIL_COND(depth==0); - - /* Setup Depth Texture */ - glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, p_size, p_size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - float border_color[]={1.0f, 1.0f, 1.0f, 1.0f}; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); - - /* Create FBO */ - glGenFramebuffers(1, &fbo); - - ERR_FAIL_COND( fbo==0 ); - - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0); - glDrawBuffer(GL_FALSE); - glReadBuffer(GL_FALSE); - - /* Check FBO creation */ - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); - - ERR_FAIL_COND( status==GL_FRAMEBUFFER_UNSUPPORTED ); - - glBindFramebufferEXT(GL_FRAMEBUFFER, 0); -#endif - -} - -void RasterizerGLES1::_init_shadow_buffers() { - - int near_shadow_size=GLOBAL_DEF("rasterizer/near_shadow_size",512); - int far_shadow_size=GLOBAL_DEF("rasterizer/far_shadow_size",64); - - near_shadow_buffers.resize( GLOBAL_DEF("rasterizer/near_shadow_count",4) ); - far_shadow_buffers.resize( GLOBAL_DEF("rasterizer/far_shadow_count",16) ); - - shadow_near_far_split_size_ratio = GLOBAL_DEF("rasterizer/shadow_near_far_split_size_ratio",0.3); - - for (int i=0;i<near_shadow_buffers.size();i++) { - - near_shadow_buffers[i].init(near_shadow_size ); - } - - for (int i=0;i<far_shadow_buffers.size();i++) { - - far_shadow_buffers[i].init(far_shadow_size); - } - -} - - -void RasterizerGLES1::_update_framebuffer() { - - return; - -#if 0 - bool want_16 = GLOBAL_DEF("rasterizer/support_hdr",true); - int blur_buffer_div=GLOBAL_DEF("rasterizer/blur_buffer_div",4); - bool use_fbo = GLOBAL_DEF("rasterizer/use_fbo",true); - - - if (blur_buffer_div<1) - blur_buffer_div=2; - - - if (use_fbo==framebuffer.active && framebuffer.width==window_size.width && framebuffer.height==window_size.height && framebuffer.buff16==want_16) - return; //nuthin to change - - if (framebuffer.fbo!=0) { - - WARN_PRINT("Resizing the screen multiple times while using to FBOs may decrease performance on some hardware."); - //free the framebuffarz - glDeleteRenderbuffers(1,&framebuffer.fbo); - glDeleteTextures(1,&framebuffer.depth); - glDeleteTextures(1,&framebuffer.color); - for(int i=0;i<2;i++) { - glDeleteRenderbuffers(1,&framebuffer.blur[i].fbo); - glDeleteTextures(1,&framebuffer.blur[i].color); - - } - - framebuffer.fbo=0; - } - - framebuffer.active=use_fbo; - framebuffer.width=window_size.width; - framebuffer.height=window_size.height; - framebuffer.buff16=want_16; - - - if (!use_fbo) - return; - - - glGenFramebuffers(1, &framebuffer.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); - - print_line("generating fbo, id: "+itos(framebuffer.fbo)); - //depth - glGenTextures(1, &framebuffer.depth); - - glBindTexture(GL_TEXTURE_2D, framebuffer.depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, framebuffer.width, framebuffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, framebuffer.depth, 0); - //color - glGenTextures(1, &framebuffer.color); - glBindTexture(GL_TEXTURE_2D, framebuffer.color); - glTexImage2D(GL_TEXTURE_2D, 0, want_16?GL_RGB16F:GL_RGBA8, framebuffer.width, framebuffer.height, 0, GL_RGBA, want_16?GL_HALF_FLOAT:GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer.color, 0); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - - for(int i=0;i<2;i++) { - - glGenFramebuffers(1, &framebuffer.blur[i].fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.blur[i].fbo); - - glGenTextures(1, &framebuffer.blur[i].color); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[i].color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, framebuffer.width/blur_buffer_div, framebuffer.height/blur_buffer_div, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer.blur[i].color, 0); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); -#endif -} - -void RasterizerGLES1::init() { - -#ifdef GLES_OVER_GL - glewInit(); -#endif - - - - - scene_pass=1; - if (ContextGL::get_singleton()) - ContextGL::get_singleton()->make_current(); - - - - Set<String> extensions; - Vector<String> strings = String((const char*)glGetString( GL_EXTENSIONS )).split(" ",false); - for(int i=0;i<strings.size();i++) { - - extensions.insert(strings[i]); -// print_line(strings[i]); - } - - - - GLint tmp = 0; -// glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &tmp); -// print_line("GL_MAX_VERTEX_ATTRIBS "+itos(tmp)); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glFrontFace(GL_CW); - //glEnable(GL_TEXTURE_2D); - - default_material=create_default_material(); - - _init_shadow_buffers(); - - shadow=NULL; - shadow_pass=0; - - framebuffer.fbo=0; - framebuffer.width=0; - framebuffer.height=0; - framebuffer.buff16=false; - framebuffer.blur[0].fbo=false; - framebuffer.blur[1].fbo=false; - framebuffer.active=false; - - //do a single initial clear - glClearColor(0,0,0,1); - //glClearDepth(1.0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - skinned_buffer_size = GLOBAL_DEF("rasterizer/skinned_buffer_size",DEFAULT_SKINNED_BUFFER_SIZE); - skinned_buffer = memnew_arr( uint8_t, skinned_buffer_size ); - - glGenTextures(1, &white_tex); - unsigned char whitetexdata[8*8*3]; - for(int i=0;i<8*8*3;i++) { - whitetexdata[i]=255; - } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,white_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,whitetexdata); - - npo2_textures_available=false; - pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc"); - etc_supported=true; - s3tc_supported=false; - _rinfo.texture_mem=0; - - -} - -void RasterizerGLES1::finish() { - - memdelete(skinned_buffer); -} - -int RasterizerGLES1::get_render_info(VS::RenderInfo p_info) { - - switch(p_info) { - - case VS::INFO_OBJECTS_IN_FRAME: { - - return _rinfo.object_count; - } break; - case VS::INFO_VERTICES_IN_FRAME: { - - return _rinfo.vertex_count; - } break; - case VS::INFO_MATERIAL_CHANGES_IN_FRAME: { - - return _rinfo.mat_change_count; - } break; - case VS::INFO_SHADER_CHANGES_IN_FRAME: { - - return _rinfo.shader_change_count; - } break; - case VS::INFO_USAGE_VIDEO_MEM_TOTAL: { - - return 0; - } break; - case VS::INFO_VIDEO_MEM_USED: { - - return get_render_info(VS::INFO_TEXTURE_MEM_USED)+get_render_info(VS::INFO_VERTEX_MEM_USED); - } break; - case VS::INFO_TEXTURE_MEM_USED: { - - _rinfo.texture_mem; - } break; - case VS::INFO_VERTEX_MEM_USED: { - - return 0; - } break; - } - - return false; -} - -bool RasterizerGLES1::needs_to_draw_next_frame() const { - - return false; -} - -void RasterizerGLES1::reload_vram() { - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glFrontFace(GL_CW); - - //do a single initial clear - glClearColor(0,0,0,1); - //glClearDepth(1.0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - -/* - glGenTextures(1, &white_tex); - unsigned char whitetexdata[8*8*3]; - for(int i=0;i<8*8*3;i++) { - whitetexdata[i]=255; - } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,white_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,whitetexdata); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D,0); - -*/ - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - - List<RID> textures; - texture_owner.get_owned_list(&textures); - keep_copies=false; - for(List<RID>::Element *E=textures.front();E;E=E->next()) { - - RID tid = E->get(); - Texture *t=texture_owner.get(tid); - ERR_CONTINUE(!t); - t->tex_id=0; - t->data_size=0; - glGenTextures(1, &t->tex_id); - t->active=false; - texture_allocate(tid,t->width,t->height,t->format,t->flags); - bool had_image=false; - for(int i=0;i<6;i++) { - if (!t->image[i].empty()) { - texture_set_data(tid,t->image[i],VS::CubeMapSide(i)); - had_image=true; - } - } - - if (!had_image && t->reloader) { - Object *rl = ObjectDB::get_instance(t->reloader); - if (rl) - rl->call(t->reloader_func,tid); - } - } - - keep_copies=true; - - -} - -bool RasterizerGLES1::has_feature(VS::Features p_feature) const { - - switch( p_feature) { - case VS::FEATURE_SHADERS: return false; - case VS::FEATURE_NEEDS_RELOAD_HOOK: return use_reload_hooks; - default: return false; - - } - -} - - -RasterizerGLES1::RasterizerGLES1(bool p_keep_copies,bool p_use_reload_hooks) { - keep_copies=p_keep_copies; - pack_arrays=false; - use_reload_hooks=p_use_reload_hooks; - - frame = 0; -}; - -RasterizerGLES1::~RasterizerGLES1() { - -}; - - -#endif diff --git a/drivers/gles1/rasterizer_gles1.h b/drivers/gles1/rasterizer_gles1.h deleted file mode 100644 index cca953eed..000000000 --- a/drivers/gles1/rasterizer_gles1.h +++ /dev/null @@ -1,1242 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles1.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* 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 RASTERIZER_GLES1_H -#define RASTERIZER_GLES1_H - -#include "servers/visual/rasterizer.h" - -#ifdef GLES1_ENABLED - -#include "image.h" -#include "rid.h" -#include "servers/visual_server.h" -#include "list.h" -#include "map.h" -#include "camera_matrix.h" -#include "sort.h" - -#include "platform_config.h" -#ifndef GLES1_INCLUDE_H -#include <GLES/gl.h> -#else -#include GLES1_INCLUDE_H -#endif - - - -#include "servers/visual/particle_system_sw.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class RasterizerGLES1 : public Rasterizer { - - enum { - - MAX_SCENE_LIGHTS=2048, - LIGHT_SPOT_BIT=0x80, - DEFAULT_SKINNED_BUFFER_SIZE = 1024 * 1024, // 10k vertices - MAX_HW_LIGHTS = 1, - }; - - - uint8_t *skinned_buffer; - int skinned_buffer_size; - bool pvr_supported; - bool s3tc_supported; - bool etc_supported; - bool npo2_textures_available; - bool pack_arrays; - bool use_reload_hooks; - - Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed); - - - struct Texture { - - uint32_t flags; - int width,height; - int alloc_width, alloc_height; - Image::Format format; - - GLenum target; - GLenum gl_format_cache; - int gl_components_cache; - int data_size; //original data size, useful for retrieving back - bool format_has_alpha; - bool compressed; - bool disallow_mipmaps; - int total_data_size; - - Image image[6]; - - bool active; - GLuint tex_id; - - ObjectID reloader; - StringName reloader_func; - - Texture() { - - flags=width=height=0; - tex_id=0; - data_size=0; - format=Image::FORMAT_GRAYSCALE; - gl_components_cache=0; - format_has_alpha=false; - active=false; - disallow_mipmaps=false; -// gen_mipmap=true; - compressed=false; - total_data_size=0; - } - - ~Texture() { - - if (tex_id!=0) { - - glDeleteTextures(1,&tex_id); - } - } - }; - - mutable RID_Owner<Texture> texture_owner; - - struct Shader { - - String vertex_code; - String fragment_code; - String light_code; - VS::ShaderMode mode; - Map<StringName,Variant> params; - int fragment_line; - int vertex_line; - int light_line; - bool valid; - bool has_alpha; - bool use_world_transform; - - }; - - mutable RID_Owner<Shader> shader_owner; - - - struct Material { - - bool fixed_flags[VS::FIXED_MATERIAL_FLAG_MAX]; - bool flags[VS::MATERIAL_FLAG_MAX]; - Variant parameters[VisualServer::FIXED_MATERIAL_PARAM_MAX]; - RID textures[VisualServer::FIXED_MATERIAL_PARAM_MAX]; - - VS::MaterialDepthDrawMode depth_draw_mode; - - Transform uv_transform; - VS::FixedMaterialTexCoordMode texcoord_mode[VisualServer::FIXED_MATERIAL_PARAM_MAX]; - - VS::MaterialBlendMode blend_mode; - - float line_width; - float point_size; - bool has_alpha; - - RID shader; // shader material - uint64_t last_pass; - - Map<StringName,Variant> shader_params; - - - Material() { - - - for(int i=0;i<VS::FIXED_MATERIAL_FLAG_MAX;i++) - flags[i]=false; - - for(int i=0;i<VS::MATERIAL_FLAG_MAX;i++) - flags[i]=false; - flags[VS::MATERIAL_FLAG_VISIBLE]=true; - - parameters[VS::FIXED_MATERIAL_PARAM_DIFFUSE] = Color(0.8, 0.8, 0.8); - parameters[VS::FIXED_MATERIAL_PARAM_SPECULAR_EXP] = 12; - - for (int i=0; i<VisualServer::FIXED_MATERIAL_PARAM_MAX; i++) { - texcoord_mode[i] = VS::FIXED_MATERIAL_TEXCOORD_UV; - }; - depth_draw_mode=VS::MATERIAL_DEPTH_DRAW_OPAQUE_ONLY; - line_width=1; - has_alpha=false; - blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - last_pass = 0; - point_size = 1.0; - - } - }; - mutable RID_Owner<Material> material_owner; - - void _material_check_alpha(Material *p_material); - - - struct Geometry { - - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_POLY, - GEOMETRY_PARTICLES, - GEOMETRY_MULTISURFACE, - }; - - Type type; - RID material; - bool has_alpha; - bool material_owned; - - Geometry() { has_alpha=false; material_owned = false; } - virtual ~Geometry() {}; - }; - - struct GeometryOwner { - - virtual ~GeometryOwner() {} - }; - - class Mesh; - - struct Surface : public Geometry { - - struct ArrayData { - - uint32_t ofs,size,datatype,count; - bool normalize; - bool bind; - - ArrayData() { ofs=0; size=0; count=0; datatype=0; normalize=0; bind=false;} - }; - - Mesh *mesh; - - Array data; - Array morph_data; - ArrayData array[VS::ARRAY_MAX]; - // support for vertex array objects - GLuint array_object_id; - // support for vertex buffer object - GLuint vertex_id; // 0 means, unconfigured - GLuint index_id; // 0 means, unconfigured - // no support for the above, array in localmem. - uint8_t *array_local; - uint8_t *index_array_local; - - bool packed; - - struct MorphTarget { - uint32_t configured_format; - uint8_t *array; - }; - - MorphTarget* morph_targets_local; - int morph_target_count; - AABB aabb; - - int array_len; - int index_array_len; - int max_bone; - - float vertex_scale; - float uv_scale; - float uv2_scale; - - VS::PrimitiveType primitive; - - uint32_t format; - uint32_t configured_format; - - int stride; - int local_stride; - uint32_t morph_format; - - bool active; - - Point2 uv_min; - Point2 uv_max; - - Surface() { - - - array_len=0; - local_stride=0; - morph_format=0; - type=GEOMETRY_SURFACE; - primitive=VS::PRIMITIVE_POINTS; - index_array_len=0; - vertex_scale=1.0; - uv_scale=1.0; - uv2_scale=1.0; - - format=0; - stride=0; - morph_targets_local=0; - morph_target_count=0; - - array_local = index_array_local = 0; - vertex_id = index_id = 0; - - active=false; - packed=false; - } - - ~Surface() { - - } - }; - - - struct Mesh { - - bool active; - Vector<Surface*> surfaces; - int morph_target_count; - VS::MorphTargetMode morph_target_mode; - AABB custom_aabb; - - mutable uint64_t last_pass; - Mesh() { - morph_target_mode=VS::MORPH_MODE_NORMALIZED; - morph_target_count=0; - last_pass=0; - active=false; - } - }; - mutable RID_Owner<Mesh> mesh_owner; - - Error _surface_set_arrays(Surface *p_surface, uint8_t *p_mem,uint8_t *p_index_mem,const Array& p_arrays,bool p_main); - - struct MultiMesh; - - struct MultiMeshSurface : public Geometry { - - Surface *surface; - MultiMeshSurface() { type=GEOMETRY_MULTISURFACE; } - }; - - struct MultiMesh : public GeometryOwner { - - struct Element { - - float matrix[16]; - uint8_t color[4]; - }; - - AABB aabb; - RID mesh; - int visible; - - //IDirect3DVertexBuffer9* instance_buffer; - Vector<Element> elements; - Vector<MultiMeshSurface> cache_surfaces; - mutable uint64_t last_pass; - - MultiMesh() { - - last_pass=0; - visible = -1; - } - }; - - mutable RID_Owner<MultiMesh> multimesh_owner; - - - struct Immediate { - - RID material; - int empty; - }; - - mutable RID_Owner<Immediate> immediate_owner; - - struct Particles : public Geometry { - - ParticleSystemSW data; // software particle system - - Particles() { - type=GEOMETRY_PARTICLES; - - } - }; - - mutable RID_Owner<Particles> particles_owner; - - struct ParticlesInstance : public GeometryOwner { - - RID particles; - - ParticleSystemProcessSW particles_process; - Transform transform; - - ParticlesInstance() { } - }; - - mutable RID_Owner<ParticlesInstance> particles_instance_owner; - ParticleSystemDrawInfoSW particle_draw_info; - - struct Skeleton { - - Vector<Transform> bones; - - }; - - mutable RID_Owner<Skeleton> skeleton_owner; - - - struct Light { - - VS::LightType type; - float vars[VS::LIGHT_PARAM_MAX]; - Color colors[3]; - bool shadow_enabled; - RID projector; - bool volumetric_enabled; - Color volumetric_color; - - - Light() { - - vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]=1; - vars[VS::LIGHT_PARAM_SPOT_ANGLE]=45; - vars[VS::LIGHT_PARAM_ATTENUATION]=1.0; - vars[VS::LIGHT_PARAM_ENERGY]=1.0; - vars[VS::LIGHT_PARAM_RADIUS]=1.0; - vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.05; - - colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1); - colors[VS::LIGHT_COLOR_SPECULAR]=Color(1,1,1); - shadow_enabled=false; - volumetric_enabled=false; - } - }; - - - struct Environment { - - - VS::EnvironmentBG bg_mode; - Variant bg_param[VS::ENV_BG_PARAM_MAX]; - bool fx_enabled[VS::ENV_FX_MAX]; - Variant fx_param[VS::ENV_FX_PARAM_MAX]; - - Environment() { - - bg_mode=VS::ENV_BG_DEFAULT_COLOR; - bg_param[VS::ENV_BG_PARAM_COLOR]=Color(0,0,0); - bg_param[VS::ENV_BG_PARAM_TEXTURE]=RID(); - bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID(); - bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0; - - for(int i=0;i<VS::ENV_FX_MAX;i++) - fx_enabled[i]=false; - - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_RANGE]=10.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_WHITE]=1.0; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_TRESHOLD]=0.95; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_SCALE]=0.2; - fx_param[VS::ENV_FX_PARAM_HDR_MIN_LUMINANCE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_MAX_LUMINANCE]=8.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED]=0.5; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]=1.0; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_BG]=true; - fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0; - - } - - }; - - mutable RID_Owner<Environment> environment_owner; - - struct ShadowBuffer; - - struct LightInstance { - - struct SplitInfo { - - CameraMatrix camera; - Transform transform; - float near; - float far; - }; - - RID light; - Light *base; - Transform transform; - CameraMatrix projection; - - Transform custom_transform; - CameraMatrix custom_projection; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - uint64_t shadow_pass; - uint64_t last_pass; - uint16_t sort_key; - - Vector<ShadowBuffer*> shadow_buffers; - - void clear_shadow_buffers() { - - for (int i=0;i<shadow_buffers.size();i++) { - - ShadowBuffer *sb=shadow_buffers[i]; - ERR_CONTINUE( sb->owner != this ); - - sb->owner=NULL; - } - - shadow_buffers.clear(); - } - - LightInstance() { shadow_pass=0; last_pass=0; sort_key=0; } - - }; - mutable RID_Owner<Light> light_owner; - mutable RID_Owner<LightInstance> light_instance_owner; - - LightInstance *light_instances[MAX_SCENE_LIGHTS]; - LightInstance *directional_lights[4]; -// LightInstance *directional_light_instances[MAX_SCENE_LIGHTS]; - int light_instance_count; - int directional_light_count; - int last_light_id; - - - struct RenderList { - - enum { - MAX_ELEMENTS=4096, - MAX_LIGHTS=4 - }; - - struct Element { - - - float depth; - const InstanceData *instance; - const Skeleton *skeleton; - union { - uint16_t lights[MAX_HW_LIGHTS]; - uint64_t light_key; - }; - - const Geometry *geometry; - const Material *material; - const GeometryOwner *owner; - uint16_t light_count; - bool mirror; - - - }; - - - Element _elements[MAX_ELEMENTS]; - Element *elements[MAX_ELEMENTS]; - int element_count; - - void clear() { - - element_count=0; - } - - struct SortZ { - - _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { - - return A->depth > B->depth; - } - }; - - void sort_z() { - - SortArray<Element*,SortZ> sorter; - sorter.sort(elements,element_count); - } - - - struct SortMat { - - _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { - // TODO move to a single uint64 (one comparison) - if (A->material == B->material) { - - return A->light_key < B->light_key; - } else { - - return (A->material < B->material); - } - } - }; - - void sort_mat() { - - SortArray<Element*,SortMat> sorter; - sorter.sort(elements,element_count); - } - - struct SortMatLight { - - _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { - - if (A->material->flags[VS::MATERIAL_FLAG_UNSHADED] == B->material->flags[VS::MATERIAL_FLAG_UNSHADED]) { - - if (A->material == B->material) { - - if (A->geometry == B->geometry) { - - return A->light_key<B->light_key; - } else - return (A->geometry < B->geometry); - } else { - - return (A->material < B->material); - } - } else { - - return (int(A->material->flags[VS::MATERIAL_FLAG_UNSHADED]) < int(B->material->flags[VS::MATERIAL_FLAG_UNSHADED])); - } - } - }; - - void sort_mat_light() { - - SortArray<Element*,SortMatLight> sorter; - sorter.sort(elements,element_count); - } - - _FORCE_INLINE_ Element* add_element() { - - if (element_count>MAX_ELEMENTS) - return NULL; - elements[element_count]=&_elements[element_count]; - return elements[element_count++]; - } - - RenderList() { - - element_count = 0; - for (int i=0;i<MAX_ELEMENTS;i++) - elements[i]=&_elements[i]; // assign elements - } - }; - - RenderList opaque_render_list; - RenderList alpha_render_list; - - RID default_material; - - struct FX { - - bool bgcolor_active; - Color bgcolor; - - bool skybox_active; - RID skybox_cubemap; - - bool antialias_active; - float antialias_tolerance; - - bool glow_active; - int glow_passes; - float glow_attenuation; - float glow_bloom; - - bool ssao_active; - float ssao_attenuation; - float ssao_radius; - float ssao_max_distance; - float ssao_range_max; - float ssao_range_min; - bool ssao_only; - - bool fog_active; - float fog_near; - float fog_far; - float fog_attenuation; - Color fog_color_near; - Color fog_color_far; - bool fog_bg; - - bool toon_active; - float toon_treshold; - float toon_soft; - - bool edge_active; - Color edge_color; - float edge_size; - - FX(); - - }; - mutable RID_Owner<FX> fx_owner; - - - FX *scene_fx; - CameraMatrix camera_projection; - Transform camera_transform; - Transform camera_transform_inverse; - float camera_z_near; - float camera_z_far; - Size2 camera_vp_size; - Color last_color; - - Plane camera_plane; - - bool keep_copies; - - bool depth_write; - bool depth_test; - int blend_mode; - bool lighting; - - _FORCE_INLINE_ void _add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner); - - void _render_list_forward(RenderList *p_render_list,bool p_reverse_cull=false); - - void _setup_light(LightInstance* p_instance, int p_idx); - void _setup_lights(const uint16_t * p_lights,int p_light_count); - - _FORCE_INLINE_ void _setup_shader_params(const Material *p_material); - void _setup_fixed_material(const Geometry *p_geometry,const Material *p_material); - void _setup_material(const Geometry *p_geometry,const Material *p_material); - - Error _setup_geometry(const Geometry *p_geometry, const Material* p_material,const Skeleton *p_skeleton, const float *p_morphs); - void _render(const Geometry *p_geometry,const Material *p_material, const Skeleton* p_skeleton, const GeometryOwner *p_owner); - - - /***********/ - /* SHADOWS */ - /***********/ - - struct ShadowBuffer { - - int size; - GLuint fbo; - GLuint depth; - LightInstance *owner; - void init(int p_size); - ShadowBuffer() { size=0; depth=0; owner=NULL; } - }; - - Vector<ShadowBuffer> near_shadow_buffers; - Vector<ShadowBuffer> far_shadow_buffers; - - LightInstance *shadow; - int shadow_pass; - void _init_shadow_buffers(); - - float shadow_near_far_split_size_ratio; - bool _allocate_shadow_buffers(LightInstance *p_instance, Vector<ShadowBuffer>& p_buffers); - void _debug_draw_shadow(ShadowBuffer *p_buffer, const Rect2& p_rect); - void _debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,Point2& ofs); - void _debug_shadows(); - void reset_state(); - - /***********/ - /* FBOs */ - /***********/ - - - struct FrameBuffer { - - GLuint fbo; - GLuint color; - GLuint depth; - int width,height; - bool buff16; - bool active; - - struct Blur { - - GLuint fbo; - GLuint color; - } blur[2]; - - } framebuffer; - - void _update_framebuffer(); - void _process_glow_and_bloom(); - - /*********/ - /* FRAME */ - /*********/ - - struct _Rinfo { - - int texture_mem; - int vertex_count; - int object_count; - int mat_change_count; - int shader_change_count; - - } _rinfo; - - GLuint white_tex; - RID canvas_tex; - float canvas_opacity; - VS::MaterialBlendMode canvas_blend; - _FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture); - - - int _setup_geometry_vinfo; - - bool cull_front; - _FORCE_INLINE_ void _set_cull(bool p_front,bool p_reverse_cull=false); - - Size2 window_size; - VS::ViewportRect viewport; - double last_time; - double time_delta; - uint64_t frame; - uint64_t scene_pass; - - //void _draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color* p_colors, const Vector3 *p_uvs,const Plane *p_tangents=NULL,int p_instanced=1); - //void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip=false, bool p_v_flip=false ); - //void _draw_quad(const Rect2& p_rect); - -public: - - /* TEXTURE API */ - - 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 Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT); - virtual 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_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual bool texture_has_alpha(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture,int p_width, int p_height); - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const; - - /* SHADER API */ - - virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL); - - virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode); - virtual VS::ShaderMode shader_get_mode(RID p_shader) const; - - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0); - virtual String shader_get_fragment_code(RID p_shader) const; - virtual String shader_get_vertex_code(RID p_shader) const; - virtual String shader_get_light_code(RID p_shader) const; - - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - /* COMMON MATERIAL API */ - - virtual RID material_create(); - - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_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_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled); - virtual bool material_get_flag(RID p_material,VS::MaterialFlag p_flag) const; - - virtual void material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode); - virtual VS::MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const; - - virtual void material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode); - virtual VS::MaterialBlendMode material_get_blend_mode(RID p_material) const; - - virtual void material_set_line_width(RID p_material,float p_line_width); - virtual float material_get_line_width(RID p_material) const; - - /* FIXED MATERIAL */ - - virtual RID fixed_material_create(); - - virtual void fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled); - virtual bool fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const; - - virtual void fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value); - virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const; - - virtual void fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const; - - virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode); - virtual VS::FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const; - - virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform); - virtual Transform fixed_material_get_uv_transform(RID p_material) const; - - virtual void fixed_material_set_point_size(RID p_material,float p_size); - virtual float fixed_material_get_point_size(RID p_material) const; - - /* MESH API */ - - - virtual RID mesh_create(); - - virtual void mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false); - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat); - - virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); - virtual int mesh_get_morph_target_count(RID p_mesh) const; - - virtual void mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode); - virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false); - 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 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 void mesh_remove_surface(RID p_mesh,int p_index); - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh,RID p_skeleton=RID()) const; - - virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - /* MULTIMESH API */ - - virtual RID multimesh_create(); - - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count); - virtual int multimesh_get_instance_count(RID p_multimesh) const; - - virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb); - virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& 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 AABB multimesh_get_aabb(RID p_multimesh) const;; - - virtual Transform multimesh_instance_get_transform(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; - - /* 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 AABB immediate_get_aabb(RID p_immediate) const; - virtual void immediate_set_material(RID p_immediate,RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; - - - /* PARTICLES API */ - - virtual RID particles_create(); - - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual int particles_get_amount(RID p_particles) const; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_is_emitting(RID p_particles) const; - - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility); - virtual AABB particles_get_visibility_aabb(RID p_particles) const; - - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents); - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const; - - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity); - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points); - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal); - virtual Vector3 particles_get_gravity_normal(RID p_particles) const; - - virtual void particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value); - virtual float particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness); - virtual float particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos); - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const; - - virtual void particles_set_color_phases(RID p_particles, int p_phases); - virtual int particles_get_color_phases(RID p_particles) const; - - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color); - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const; - - virtual void particles_set_attractors(RID p_particles, int p_attractors); - virtual int particles_get_attractors(RID p_particles) const; - - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos); - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const; - - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force); - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const; - - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false); - virtual RID particles_get_material(RID p_particles) const; - - virtual AABB particles_get_aabb(RID p_particles) const; - - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable); - virtual bool particles_has_height_from_velocity(RID p_particles) const; - - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual bool particles_is_using_local_coordinates(RID p_particles) const; - - /* SKELETON API */ - - virtual RID skeleton_create(); - virtual void skeleton_resize(RID p_skeleton,int p_bones); - 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); - - - /* LIGHT API */ - - virtual RID light_create(VS::LightType p_type); - virtual VS::LightType light_get_type(RID p_light) const; - - virtual void light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color); - virtual Color light_get_color(RID p_light,VS::LightColor p_type) const; - - virtual void light_set_shadow(RID p_light,bool p_enabled); - virtual bool light_has_shadow(RID p_light) const; - - virtual void light_set_volumetric(RID p_light,bool p_enabled); - virtual bool light_is_volumetric(RID p_light) const; - - virtual void light_set_projector(RID p_light,RID p_texture); - virtual RID light_get_projector(RID p_light) const; - - virtual void light_set_var(RID p_light, VS::LightParam p_var, float p_value); - virtual float light_get_var(RID p_light, VS::LightParam p_var) const; - - virtual void light_set_operator(RID p_light,VS::LightOp p_op); - virtual VS::LightOp light_get_operator(RID p_light) const; - - virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode); - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const; - - - virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const; - virtual void light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value); - virtual float light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const; - - virtual AABB light_get_aabb(RID p_poly) const; - - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); - - virtual bool light_instance_has_shadow(RID p_light_instance) const; - virtual bool light_instance_assign_shadow(RID p_light_instance); - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const; - virtual int light_instance_get_shadow_passes(RID p_light_instance) const; - virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const; - virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; } - - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance,bool p_far=false) const; - virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - - virtual void shadow_clear_near(); - virtual bool shadow_allocate_near(RID p_light); - virtual bool shadow_allocate_far(RID p_light); - - - /* PARTICLES INSTANCE */ - - virtual RID particles_instance_create(RID p_particles); - virtual void particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform); - - /* VIEWPORT */ - - virtual RID viewport_data_create(); - - 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 bool render_target_renedered_in_frame(RID p_render_target); - - /* RENDER API */ - /* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - virtual void begin_frame(); - - virtual void set_viewport(const VS::ViewportRect& p_viewport); - virtual void set_render_target(RID p_render_target,bool p_transparent_bg=false,bool p_vflip=false); - virtual void clear_viewport(const Color& p_color); - virtual void capture_viewport(Image* r_capture); - - - virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug); - virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass ); - - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection); - - virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls - - - virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data); - virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data); - virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {} - virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data); - - virtual void end_scene(); - virtual void end_shadow_map(); - - virtual void end_frame(); - - /* CANVAS API */ - - virtual void canvas_begin(); - virtual void canvas_disable_blending(); - virtual void canvas_set_opacity(float p_opacity); - virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode); - virtual void canvas_begin_rect(const Matrix32& p_transform); - virtual void canvas_set_clip(bool p_clip, const Rect2& p_rect); - virtual void canvas_end_rect(); - virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width); - virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate); - virtual void canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); - virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width); - virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); - virtual void canvas_set_transform(const Matrix32& p_transform); - - /* FX */ - - virtual RID fx_create(); - virtual void fx_get_effects(RID p_fx,List<String> *p_effects) const; - virtual void fx_set_active(RID p_fx,const String& p_effect, bool p_active); - virtual bool fx_is_active(RID p_fx,const String& p_effect) const; - virtual void fx_get_effect_params(RID p_fx,const String& p_effect,List<PropertyInfo> *p_params) const; - virtual Variant fx_get_effect_param(RID p_fx,const String& p_effect,const String& p_param) const; - virtual void fx_set_effect_param(RID p_fx,const String& p_effect, const String& p_param, const Variant& p_pvalue); - - /* ENVIRONMENT */ - - virtual RID environment_create(); - - virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg); - virtual VS::EnvironmentBG environment_get_background(RID p_env) const; - - virtual void environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value); - virtual Variant environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const; - - virtual void environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled); - virtual bool environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const; - - virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); - virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; - - - /*MISC*/ - - virtual bool is_texture(const RID& p_rid) const; - virtual bool is_material(const RID& p_rid) const; - virtual bool is_mesh(const RID& p_rid) const; - virtual bool is_multimesh(const RID& p_rid) const; - virtual bool is_immediate(const RID& p_rid) const; - virtual bool is_particles(const RID &p_beam) const; - - virtual bool is_light(const RID& p_rid) const; - virtual bool is_light_instance(const RID& p_rid) const; - virtual bool is_particles_instance(const RID& p_rid) const; - virtual bool is_skeleton(const RID& p_rid) const; - virtual bool is_environment(const RID& p_rid) const; - virtual bool is_fx(const RID& p_rid) const; - virtual bool is_shader(const RID& p_rid) const; - - virtual void free(const RID& p_rid); - - virtual void custom_shade_model_set_shader(int p_model, RID p_shader); - virtual RID custom_shade_model_get_shader(int p_model) const; - virtual void custom_shade_model_set_name(int p_model, const String& p_name); - virtual String custom_shade_model_get_name(int p_model) const; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info); - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const; - - - virtual void init(); - virtual void finish(); - - virtual int get_render_info(VS::RenderInfo p_info); - - void reload_vram(); - - virtual bool needs_to_draw_next_frame() const; - - virtual bool has_feature(VS::Features p_feature) const; - - -#ifdef TOOLS_ENABLED - RasterizerGLES1(bool p_keep_copies=true,bool p_use_reload_hooks=false); -#else - RasterizerGLES1(bool p_keep_copies=false,bool p_use_reload_hooks=false); -#endif - virtual ~RasterizerGLES1(); -}; - -#endif -#endif diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index ecf80047b..9375532f0 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -63,6 +63,13 @@ #define _glClearDepth glClearDepthf #endif + +#define _GL_SRGB_EXT 0x8C40 +#define _GL_SRGB_ALPHA_EXT 0x8C42 + +#define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + //#define DEBUG_OPENGL #ifdef DEBUG_OPENGL @@ -132,11 +139,13 @@ static _FORCE_INLINE_ uint16_t make_half_float(float f) { else if (exp <= 0x38000000) { - // store a denorm half-float value or zero + /*// store a denorm half-float value or zero exp = (0x38000000 - exp) >> 23; mantissa >>= (14 + exp); hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa); + */ + hf=0; //denormals do not work for 3D, convert to zero } else { @@ -303,9 +312,23 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c #define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 #define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 #define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 + +#define _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54 +#define _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55 +#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56 +#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57 + + #define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define _EXT_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define _EXT_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define _EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define _EXT_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 + + #define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB #define _EXT_COMPRESSED_RED_RGTC1 0x8DBB #define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC @@ -316,6 +339,22 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c #define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE #define _EXT_ETC1_RGB8_OES 0x8D64 + + +#define _EXT_SLUMINANCE_NV 0x8C46 +#define _EXT_SLUMINANCE_ALPHA_NV 0x8C44 +#define _EXT_SRGB8_NV 0x8C41 +#define _EXT_SLUMINANCE8_NV 0x8C47 +#define _EXT_SLUMINANCE8_ALPHA8_NV 0x8C45 + + +#define _EXT_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C +#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D +#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E +#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F + + + #define _EXT_ATC_RGB_AMD 0x8C92 #define _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 #define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE @@ -323,10 +362,11 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c /* TEXTURE API */ -Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) { +Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) { r_has_alpha_cache=false; r_compressed=false; + r_gl_format=0; Image image=p_image; switch(p_format) { @@ -334,6 +374,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For case Image::FORMAT_GRAYSCALE: { r_gl_components=1; r_gl_format=GL_LUMINANCE; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_NV:GL_LUMINANCE; } break; case Image::FORMAT_INTENSITY: { @@ -342,6 +383,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.convert(Image::FORMAT_RGBA); r_gl_components=4; r_gl_format=GL_RGBA; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; r_has_alpha_cache=true; } break; case Image::FORMAT_GRAYSCALE_ALPHA: { @@ -349,6 +391,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For //image.convert(Image::FORMAT_RGBA); r_gl_components=2; r_gl_format=GL_LUMINANCE_ALPHA; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_ALPHA_NV:GL_LUMINANCE_ALPHA; r_has_alpha_cache=true; } break; @@ -358,6 +401,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.convert(Image::FORMAT_RGB); r_gl_components=3; r_gl_format=GL_RGB; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB; } break; @@ -366,54 +410,119 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.convert(Image::FORMAT_RGBA); r_gl_components=4; - r_gl_format=GL_RGBA; + + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } break; case Image::FORMAT_RGB: { r_gl_components=3; - r_gl_format=GL_RGB; + + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_internal_format=_GL_SRGB_EXT; + r_gl_format=GL_RGB; + } else { + r_gl_internal_format=GL_RGB; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGB; + } } break; case Image::FORMAT_RGBA: { r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + r_gl_format=GL_RGBA; + //r_gl_internal_format=GL_RGBA; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } + r_has_alpha_cache=true; } break; case Image::FORMAT_BC1: { - if (!s3tc_supported) { + if (!s3tc_supported || (!s3tc_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { if (!image.empty()) { image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; r_compressed=true; }; } break; case Image::FORMAT_BC2: { - if (!s3tc_supported) { + if (!s3tc_supported || (!s3tc_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { if (!image.empty()) { image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; + r_has_alpha_cache=true; r_compressed=true; }; @@ -421,18 +530,30 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_BC3: { - if (!s3tc_supported) { + if (!s3tc_supported || (!s3tc_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { if (!image.empty()) { image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; r_has_alpha_cache=true; r_compressed=true; }; @@ -440,18 +561,30 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_BC4: { - if (!s3tc_supported) { + if (!latc_supported) { if (!image.empty()) { image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RED_RGTC1; + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT; r_gl_components=1; //doesn't matter much r_compressed=true; }; @@ -459,36 +592,60 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_BC5: { - if (!s3tc_supported) { + if (!latc_supported ) { if (!image.empty()) { image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RG_RGTC2; + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; r_gl_components=1; //doesn't matter much r_compressed=true; }; } break; case Image::FORMAT_PVRTC2: { - if (!pvr_supported) { + if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { if (!image.empty()) { image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; @@ -497,18 +654,31 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_PVRTC2_ALPHA: { - if (!pvr_supported) { + if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { if (!image.empty()) image.decompress(); r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + r_gl_internal_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; @@ -517,16 +687,28 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_PVRTC4: { - if (!pvr_supported) { + if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { if (!image.empty()) image.decompress(); r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -534,16 +716,28 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_PVRTC4_ALPHA: { - if (!pvr_supported) { + if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { if (!image.empty()) image.decompress(); r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGBA; + } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -551,18 +745,31 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_ETC: { - if (!etc_supported) { + if (!etc_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (!image.empty()) { image.decompress(); } r_gl_components=3; - r_gl_format=GL_RGB; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=GL_RGB; + r_gl_internal_format=_GL_SRGB_EXT; + } else { + r_gl_internal_format=GL_RGB; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_internal_format=GL_RGB; + } + r_gl_internal_format=GL_RGB; } else { - r_gl_format=_EXT_ETC1_RGB8_OES; + r_gl_internal_format=_EXT_ETC1_RGB8_OES; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -576,12 +783,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=3; - r_gl_format=GL_RGB; + r_gl_internal_format=GL_RGB; } else { - r_gl_format=_EXT_ATC_RGB_AMD; + r_gl_internal_format=_EXT_ATC_RGB_AMD; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -595,12 +802,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } else { - r_gl_format=_EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD; + r_gl_internal_format=_EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -614,12 +821,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } else { - r_gl_format=_EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD; + r_gl_internal_format=_EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -630,7 +837,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.convert(Image::FORMAT_RGB); - r_gl_format=GL_RGB; + r_gl_internal_format=GL_RGB; r_gl_components=3; } break; @@ -641,6 +848,10 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } } + if (r_gl_format==0) { + r_gl_format=r_gl_internal_format; + } + return image; } @@ -672,6 +883,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I bool has_alpha_cache; int components; GLenum format; + GLenum internal_format; bool compressed; int po2_width = nearest_power_of_2(p_width); @@ -690,7 +902,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I texture->flags=p_flags; texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; - _get_gl_image_and_format(Image(),texture->format,texture->flags,format,components,has_alpha_cache,compressed); + _get_gl_image_and_format(Image(),texture->format,texture->flags,format,internal_format,components,has_alpha_cache,compressed); bool scale_textures = !compressed && !(p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && (!npo2_textures_available || p_flags&VS::TEXTURE_FLAG_MIPMAPS); @@ -708,6 +920,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I texture->gl_components_cache=components; texture->gl_format_cache=format; + texture->gl_internal_format_cache=internal_format; texture->format_has_alpha=has_alpha_cache; texture->compressed=compressed; texture->has_alpha=false; //by default it doesn't have alpha unless something with alpha is blitteds @@ -722,7 +935,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I if (p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) { //prealloc if video - glTexImage2D(texture->target, 0, format, p_width, p_height, 0, format, GL_UNSIGNED_BYTE,NULL); + glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, GL_UNSIGNED_BYTE,NULL); } texture->active=true; @@ -740,6 +953,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu int components; GLenum format; + GLenum internal_format; bool alpha; bool compressed; @@ -747,7 +961,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu texture->image[p_cube_side]=p_image; } - Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,components,alpha,compressed); + Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,internal_format,components,alpha,compressed); if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) { @@ -757,7 +971,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu - if (img.detect_alpha()==Image::ALPHA_BLEND) { + if ((!texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) { texture->has_alpha=true; } @@ -800,6 +1014,16 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); } + if (use_anisotropic_filter) { + + if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { + + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_level); + } else { + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + } + } + int mipmaps= (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1; @@ -821,7 +1045,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) { glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] ); } else { - glTexImage2D(blit_target, i, format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); + glTexImage2D(blit_target, i, internal_format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); } } @@ -1047,6 +1271,16 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { } + if (use_anisotropic_filter) { + + if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { + + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_level); + } else { + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + } + } + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); else @@ -1177,6 +1411,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { material_shader.free_custom_shader(shader->custom_code_id); } break; + case VS::SHADER_CANVAS_ITEM: { + canvas_shader.free_custom_shader(shader->custom_code_id); + } break; } shader->custom_code_id=0; @@ -1188,6 +1425,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { shader->custom_code_id=material_shader.create_custom_shader(); } break; + case VS::SHADER_CANVAS_ITEM: { + shader->custom_code_id=canvas_shader.create_custom_shader(); + } break; } _shader_make_dirty(shader); @@ -1307,6 +1547,48 @@ void RasterizerGLES2::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_ } +void RasterizerGLES2::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + + if (p_texture.is_valid()) + shader->default_textures[p_name]=p_texture; + else + shader->default_textures.erase(p_name); + + _shader_make_dirty(shader); + +} + +RID RasterizerGLES2::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ + const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,RID()); + + const Map<StringName,RID>::Element *E=shader->default_textures.find(p_name); + if (!E) + return RID(); + return E->get(); +} + +Variant RasterizerGLES2::shader_get_default_param(RID p_shader, const StringName& p_name) { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,Variant()); + + //update shader params if necesary + //make sure the shader is compiled and everything + //so the actual parameters can be properly retrieved! + if (shader->dirty_list.in_list()) { + _update_shader(shader); + } + if (shader->valid && shader->uniforms.has(p_name)) + return shader->uniforms[p_name].default_value; + + return Variant(); +} + /* COMMON MATERIAL API */ @@ -1349,6 +1631,7 @@ void RasterizerGLES2::material_set_param(RID p_material, const StringName& p_par material->shader_version=0; //get default! } else { E->get().value=p_value; + E->get().inuse=true; } } else { @@ -1356,6 +1639,7 @@ void RasterizerGLES2::material_set_param(RID p_material, const StringName& p_par ud.index=-1; ud.value=p_value; ud.istexture=p_value.get_type()==Variant::_RID; /// cache it being texture + ud.inuse=true; material->shader_params[p_param]=ud; //may be got at some point, or erased } @@ -1387,7 +1671,7 @@ Variant RasterizerGLES2::material_get_param(RID p_material, const StringName& p_ } - if (material->shader_params.has(p_param)) + if (material->shader_params.has(p_param) && material->shader_params[p_param].inuse) return material->shader_params[p_param].value; else return Variant(); @@ -1399,6 +1683,7 @@ void RasterizerGLES2::material_set_flag(RID p_material, VS::MaterialFlag p_flag, Material *material = material_owner.get(p_material); ERR_FAIL_COND(!material); ERR_FAIL_INDEX(p_flag,VS::MATERIAL_FLAG_MAX); + material->flags[p_flag]=p_enabled; } @@ -3940,6 +4225,9 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { pixels.resize(viewport.width*viewport.height*4); DVector<uint8_t>::Write w = pixels.write(); glPixelStorei(GL_PACK_ALIGNMENT, 4); + +// uint64_t time = OS::get_singleton()->get_ticks_usec(); + if (current_rt) { #ifdef GLEW_ENABLED glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -3949,10 +4237,24 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { // back? glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGBA,GL_UNSIGNED_BYTE,w.ptr()); } - w=DVector<uint8_t>::Write(); + uint32_t *imgptr = (uint32_t*)w.ptr(); + for(int y=0;y<(viewport.height/2);y++) { + + uint32_t *ptr1 = &imgptr[y*viewport.width]; + uint32_t *ptr2 = &imgptr[(viewport.height-y-1)*viewport.width]; + + for(int x=0;x<viewport.width;x++) { + + uint32_t tmp = ptr1[x]; + ptr1[x]=ptr2[x]; + ptr2[x]=tmp; + } + } + + w=DVector<uint8_t>::Write(); r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels); - r_capture->flip_y(); + //r_capture->flip_y(); #endif @@ -4155,6 +4457,13 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (err) { return; //invalid } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + + Error err = shader_precompiler.compile(p_shader->vertex_code,ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX,vertex_code,vertex_globals,vertex_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } + } //print_line("compiled vertex: "+vertex_code); @@ -4164,9 +4473,16 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { String fragment_code; String fragment_globals; - Error err = shader_precompiler.compile(p_shader->fragment_code,(p_shader->mode==VS::SHADER_MATERIAL?ShaderLanguage::SHADER_MATERIAL_FRAGMENT:ShaderLanguage::SHADER_POST_PROCESS),fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); - if (err) { - return; //invalid + if (p_shader->mode==VS::SHADER_MATERIAL) { + Error err = shader_precompiler.compile(p_shader->fragment_code,ShaderLanguage::SHADER_MATERIAL_FRAGMENT,fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + Error err = shader_precompiler.compile(p_shader->fragment_code,ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT,fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } } @@ -4179,6 +4495,11 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (err) { return; //invalid } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + Error err = shader_precompiler.compile(p_shader->light_code,(ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT),light_code,light_globals,light_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } } fragment_globals+=light_globals; //both fragment anyway @@ -4212,7 +4533,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { enablers.push_back("#define ENABLE_UV_INTERP\n"); if (fragment_flags.use_uv2_interp || vertex_flags.use_uv2_interp) enablers.push_back("#define ENABLE_UV2_INTERP\n"); - if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp) + if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp || fragment_flags.uses_normalmap) enablers.push_back("#define ENABLE_TANGENT_INTERP\n"); if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) enablers.push_back("#define ENABLE_VAR1_INTERP\n"); @@ -4227,6 +4548,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (fragment_flags.uses_discard) { enablers.push_back("#define ENABLE_DISCARD\n"); } + if (fragment_flags.uses_normalmap) { + enablers.push_back("#define ENABLE_NORMALMAP\n"); + } if (light_flags.uses_light) { enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); } @@ -4236,7 +4560,36 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { } material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); - } else { + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + + Vector<const char*> enablers; + + if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { + enablers.push_back("#define USE_TIME\n"); + uses_time=true; + } + if (fragment_flags.uses_normal) { + enablers.push_back("#define NORMAL_USED\n"); + } + if (light_flags.uses_light) { + enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); + } + if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) + enablers.push_back("#define ENABLE_VAR1_INTERP\n"); + if (fragment_flags.use_var2_interp || vertex_flags.use_var2_interp) + enablers.push_back("#define ENABLE_VAR2_INTERP\n"); + if (fragment_flags.uses_texscreen) { + enablers.push_back("#define ENABLE_TEXSCREEN\n"); + } + if (fragment_flags.uses_screen_uv) { + enablers.push_back("#define ENABLE_SCREEN_UV\n"); + } + if (fragment_flags.uses_texpixel_size) { + enablers.push_back("#define USE_TEXPIXEL_SIZE\n"); + } + + canvas_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); + //postprocess_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names); } @@ -4247,7 +4600,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { p_shader->has_texscreen=fragment_flags.uses_texscreen; p_shader->has_screen_uv=fragment_flags.uses_screen_uv; p_shader->can_zpass=!fragment_flags.uses_discard && !vertex_flags.vertex_code_writes_vertex; + p_shader->uses_normal=fragment_flags.uses_normal || light_flags.uses_normal; p_shader->uses_time=uses_time; + p_shader->uses_texpixel_size=fragment_flags.uses_texpixel_size; p_shader->version++; } @@ -4394,7 +4749,8 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES]) e->mirror=!e->mirror; - e->light_type=0xFF; // no lights! + //e->light_type=0xFF; // no lights! + e->light_type=3; //light type 3 is no light? e->light=0xFFFF; if (!shadow && !has_blend_alpha && has_alpha && m->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA) { @@ -4597,31 +4953,46 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ Material::UniformData ud; - bool keep=true; + bool keep=true; //keep material value + bool has_old = old_mparams.has(E->key()); + bool old_inuse=has_old && old_mparams[E->key()].inuse; - if (!old_mparams.has(E->key())) + if (!has_old || !old_inuse) keep=false; else if (old_mparams[E->key()].value.get_type()!=E->value().default_value.get_type()) { - - if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { + //type changed between old and new + /* if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { if (E->value().default_value.get_type()!=Variant::_RID) //hackfor textures keep=false; } else if (!old_mparams[E->key()].value.is_num() || !E->value().default_value.get_type()) + keep=false;*/ + + //value is invalid because type differs and default is not null + if (E->value().default_value.get_type()!=Variant::NIL) keep=false; } + ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); + if (keep) { ud.value=old_mparams[E->key()].value; + //print_line("KEEP: "+String(E->key())); } else { - ud.value=E->value().default_value; + if (ud.istexture && p_material->shader_cache->default_textures.has(E->key())) + ud.value=p_material->shader_cache->default_textures[E->key()]; + else + ud.value=E->value().default_value; + old_inuse=false; //if reverted to default, obviously did not work + //print_line("NEW: "+String(E->key())+" because: hasold-"+itos(old_mparams.has(E->key()))); //if (old_mparams.has(E->key())) // print_line(" told "+Variant::get_type_name(old_mparams[E->key()].value.get_type())+" tnew "+Variant::get_type_name(E->value().default_value.get_type())); } - ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); + ud.index=idx++; + ud.inuse=old_inuse; mparams[E->key()]=ud; } @@ -4656,6 +5027,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF13); material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM); material_shader.set_conditional(MaterialShaderGLES2::USE_LIGHTMAP_ON_UV2,p_material->flags[VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2]); + material_shader.set_conditional(MaterialShaderGLES2::USE_COLOR_ATTRIB_SRGB_TO_LINEAR,p_material->flags[VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB] && current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); if (p_opaque_pass && p_material->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA && p_material->shader_cache && p_material->shader_cache->has_alpha) { @@ -4735,12 +5107,14 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material Texture *t=NULL; if (rid.is_valid()) { + t=texture_owner.get(rid); - if (!t) + if (!t) { E->get().value=RID(); //nullify, invalid texture + rid=RID(); + } } - glActiveTexture(GL_TEXTURE0+texcoord); glUniform1i(loc,texcoord); //TODO - this could happen automatically on compile... if (t) { @@ -4764,8 +5138,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material } + if (p_material->shader_cache->has_texscreen && framebuffer.active) { material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(0,0,float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_TEX,texcoord); glActiveTexture(GL_TEXTURE0+texcoord); glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); @@ -4897,7 +5273,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { if (li->near_shadow_buffer) { - glActiveTexture(GL_TEXTURE7); + glActiveTexture(GL_TEXTURE0+max_texture_units-1); //if (read_depth_supported) { glBindTexture(GL_TEXTURE_2D,li->near_shadow_buffer->depth); @@ -4908,7 +5284,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,7); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,max_texture_units-1); if (shadow_filter==SHADOW_FILTER_ESM) material_shader.set_uniform(MaterialShaderGLES2::ESM_MULTIPLIER,float(li->base->vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER])); @@ -4952,7 +5328,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { } -template<bool USE_NORMAL, bool USE_TANGENT> +template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE> void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms) { uint32_t basesize = 3; @@ -4962,6 +5338,8 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str basesize+=4; uint32_t extra=(p_dst_stride-basesize*4); + const int dstvec_size=3+(USE_NORMAL?3:0)+(USE_TANGENT?4:0); + float dstcopy[dstvec_size]; for(int i=0;i<p_elements;i++) { @@ -4970,7 +5348,11 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str const uint16_t *bi = (const uint16_t*)&p_src_bones[ss]; const float *bw = (const float *)&p_src_weights[ss]; const float *src_vec=(const float *)&p_src_array[ss]; - float *dst_vec=(float*)&p_dst_array[ds]; + float *dst_vec; + if (INPLACE) + dst_vec=dstcopy; + else + dst_vec=(float*)&p_dst_array[ds]; dst_vec[0]=0.0; dst_vec[1]=0.0; @@ -5023,16 +5405,28 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str end: - //copy extra stuff - const uint8_t *esp =(const uint8_t*) &src_vec[basesize]; - uint8_t *edp =(uint8_t*) &dst_vec[basesize]; + if (INPLACE) { + const uint8_t *esp =(const uint8_t*) dstcopy; + uint8_t *edp =(uint8_t*)&p_dst_array[ds]; - for(uint32_t j=0;j<extra;j++) { - edp[j]=esp[j]; - } + for(uint32_t j=0;j<dstvec_size*4;j++) { + + edp[j]=esp[j]; + } + + } else { + //copy extra stuff + const uint8_t *esp =(const uint8_t*) &src_vec[basesize]; + uint8_t *edp =(uint8_t*) &dst_vec[basesize]; + + for(uint32_t j=0;j<extra;j++) { + + edp[j]=esp[j]; + } + } } } @@ -5107,6 +5501,8 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia } + int16_t coeffp = CLAMP(coef*255,0,255); + for(int i=0;i<VS::ARRAY_MAX-1;i++) { @@ -5116,9 +5512,13 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia int ofs = ad.ofs; int src_stride=surf->stride; - int dst_stride=surf->local_stride; + int dst_stride=skeleton_valid?surf->stride:surf->local_stride; int count = surf->array_len; + if (!skeleton_valid && i>=VS::ARRAY_MAX-3) + break; + + switch(i) { case VS::ARRAY_VERTEX: @@ -5134,7 +5534,21 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia dst[0]= src[0]*coef; dst[1]= src[1]*coef; dst[2]= src[2]*coef; - } break; + }; + + } break; + case VS::ARRAY_COLOR: { + + for(int k=0;k<count;k++) { + + const uint8_t *src = (const uint8_t*)&surf->array_local[ofs+k*src_stride]; + uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride]; + + dst[0]= (src[0]*coeffp)>>8; + dst[1]= (src[1]*coeffp)>>8; + dst[2]= (src[2]*coeffp)>>8; + dst[3]= (src[3]*coeffp)>>8; + } } break; case VS::ARRAY_TEX_UV: @@ -5147,16 +5561,32 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia dst[0]= src[0]*coef; dst[1]= src[1]*coef; - } break; + } } break; + case VS::ARRAY_BONES: + case VS::ARRAY_WEIGHTS: { + + for(int k=0;k<count;k++) { + + const float *src = (const float*)&surf->array_local[ofs+k*src_stride]; + float *dst = (float*)&base[ofs+k*dst_stride]; + + dst[0]= src[0]; + dst[1]= src[1]; + dst[2]= src[2]; + dst[3]= src[3]; + } + + } break; + } } for(int j=0;j<surf->morph_target_count;j++) { - for(int i=0;i<VS::ARRAY_MAX-1;i++) { + for(int i=0;i<VS::ARRAY_MAX-3;i++) { const Surface::ArrayData& ad=surf->array[i]; if (ad.size==0) @@ -5164,10 +5594,12 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia int ofs = ad.ofs; - int dst_stride=surf->local_stride; + int src_stride=surf->local_stride; + int dst_stride=skeleton_valid?surf->stride:surf->local_stride; int count = surf->array_len; const uint8_t *morph=surf->morph_targets_local[j].array; float w = p_morphs[j]; + int16_t wfp = CLAMP(w*255,0,255); switch(i) { @@ -5178,13 +5610,26 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia for(int k=0;k<count;k++) { - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; + const float *src_morph = (const float*)&morph[ofs+k*src_stride]; float *dst = (float*)&base[ofs+k*dst_stride]; dst[0]+= src_morph[0]*w; dst[1]+= src_morph[1]*w; dst[2]+= src_morph[2]*w; - } break; + } + + } break; + case VS::ARRAY_COLOR: { + for(int k=0;k<count;k++) { + + const uint8_t *src = (const uint8_t*)&morph[ofs+k*src_stride]; + uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride]; + + dst[0]= (src[0]*wfp)>>8; + dst[1]= (src[1]*wfp)>>8; + dst[2]= (src[2]*wfp)>>8; + dst[3]= (src[3]*wfp)>>8; + } } break; case VS::ARRAY_TEX_UV: @@ -5192,18 +5637,43 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia for(int k=0;k<count;k++) { - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; + const float *src_morph = (const float*)&morph[ofs+k*src_stride]; float *dst = (float*)&base[ofs+k*dst_stride]; dst[0]+= src_morph[0]*w; dst[1]+= src_morph[1]*w; - } break; + } } break; } } } + + + if (skeleton_valid) { + + + + const uint8_t *src_weights=&surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs]; + const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; + const Skeleton::Bone *skeleton = &p_skeleton->bones[0]; + + + if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT) + _skeleton_xform<true,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + else if (surf->format&(VS::ARRAY_FORMAT_NORMAL)) + _skeleton_xform<true,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + else if (surf->format&(VS::ARRAY_FORMAT_TANGENT)) + _skeleton_xform<false,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + else + _skeleton_xform<false,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + + } + + stride=skeleton_valid?surf->stride:surf->local_stride; + + #if 0 { //in-place skeleton tansformation, only used for morphs, slow. @@ -5297,14 +5767,14 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; const Skeleton::Bone *skeleton = &p_skeleton->bones[0]; - if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT) - _skeleton_xform<true,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT) + _skeleton_xform<true,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); else if (surf->format&(VS::ARRAY_FORMAT_NORMAL)) - _skeleton_xform<true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + _skeleton_xform<true,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); else if (surf->format&(VS::ARRAY_FORMAT_TANGENT)) - _skeleton_xform<false,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + _skeleton_xform<false,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); else - _skeleton_xform<false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + _skeleton_xform<false,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); stride=dst_stride; @@ -5434,9 +5904,10 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater float twd=(1.0/mm->tw)*4.0; float thd=1.0/mm->th; float parm[3]={0.0,01.0,(1.0f/mm->tw)}; - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glDisableVertexAttribArray(6); glBindTexture(GL_TEXTURE_2D,mm->tex_id); + material_shader.set_uniform(MaterialShaderGLES2::INSTANCE_MATRICES,GL_TEXTURE0+max_texture_units-2); if (s->index_array_len>0) { @@ -5737,7 +6208,7 @@ void RasterizerGLES2::_setup_skeleton(const Skeleton *p_skeleton) { material_shader.set_conditional(MaterialShaderGLES2::USE_SKELETON,p_skeleton!=NULL); if (p_skeleton && p_skeleton->tex_id) { - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glBindTexture(GL_TEXTURE_2D,p_skeleton->tex_id); } @@ -5786,7 +6257,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool stores_glow = !shadow && (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) && !p_alpha_pass; - + float sampled_light_dp_multiplier=1.0; bool prev_blend=false; glDisable(GL_BLEND); @@ -5805,6 +6276,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool bind_baked_light_octree=false; bool bind_baked_lightmap=false; bool additive=false; + bool bind_dp_sampler=false; if (!shadow) { @@ -5926,6 +6398,22 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false); material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false); + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,false); + + if (e->instance->sampled_light.is_valid()) { + + SampledLight *sl = sampled_light_owner.get(e->instance->sampled_light); + if (sl) { + + baked_light=NULL; //can't mix + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,true); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); + glBindTexture(GL_TEXTURE_2D,sl->texture); //bind the texture + sampled_light_dp_multiplier=sl->multiplier; + bind_dp_sampler=true; + } + } + if (!additive && baked_light) { @@ -5936,9 +6424,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex=texture_owner.get(baked_light->octree_texture); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } + if (baked_light->light_texture.is_valid()) { + Texture *texl=texture_owner.get(baked_light->light_texture); + if (texl) { + glActiveTexture(GL_TEXTURE0+max_texture_units-4); + glBindTexture(texl->target,texl->tex_id); //bind the light texture + } + } } } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { @@ -5961,7 +6456,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex = texture_owner.get(texid); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } @@ -6037,7 +6532,15 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_SIZE, baked_light->octree_lattice_size); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_DIVIDE, baked_light->octree_lattice_divide); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_STEPS, baked_light->octree_steps); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,max_texture_units-3); + if (baked_light->light_texture.is_valid()) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-4); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->light_tex_pixel_size); + } else { + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-3); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->octree_tex_pixel_size); + } material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_MULTIPLIER,baked_light->texture_multiplier); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_PIX_SIZE,baked_light->octree_tex_pixel_size); @@ -6046,11 +6549,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (bind_baked_lightmap && (baked_light!=prev_baked_light || rebind)) { - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, 5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, max_texture_units-3); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP_MULTIPLIER, baked_light->lightmap_multiplier); } + if (bind_dp_sampler) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER_MULTIPLIER,sampled_light_dp_multiplier); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER,max_texture_units-3); + } _set_cull(e->mirror,p_reverse_cull); @@ -6059,13 +6567,13 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::CAMERA_INVERSE_TRANSFORM, p_view_transform_inverse); material_shader.set_uniform(MaterialShaderGLES2::PROJECTION_TRANSFORM, p_projection); if (skeleton && use_hw_skeleton_xform) { - //material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,6); + material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,GL_TEXTURE0+max_texture_units-2); material_shader.set_uniform(MaterialShaderGLES2::SKELTEX_PIXEL_SIZE,skeleton->pixel_size); } if (!shadow) { if (!additive && current_env && current_env->fx_enabled[VS::ENV_FX_AMBIENT_LIGHT]) { - Color ambcolor = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR]; + Color ambcolor = _convert_color(current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR]); float ambnrg = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY]; material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHT,Vector3(ambcolor.r*ambnrg,ambcolor.g*ambnrg,ambcolor.b*ambnrg)); } else { @@ -6793,6 +7301,7 @@ void RasterizerGLES2::end_scene() { _debug_shadows(); } // _debug_luminances(); + _debug_samplers(); } @@ -7193,6 +7702,38 @@ void RasterizerGLES2::_debug_luminances() { } +void RasterizerGLES2::_debug_samplers() { + canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32,false); + canvas_begin(); + glDisable(GL_BLEND); + _set_color_attrib(Color(1,1,1,1)); + canvas_shader.bind(); + + + List<RID> samplers; + sampled_light_owner.get_owned_list(&samplers); + + Size2 debug_size(128,128); + Size2 ofs; + + + for (List<RID>::Element *E=samplers.front();E;E=E->next()) { + + SampledLight *sl=sampled_light_owner.get(E->get()); + + _debug_draw_shadow(sl->texture, Rect2( ofs, debug_size )); + + ofs.x+=debug_size.x/2; + if ( (ofs.x+debug_size.x) > viewport.width ) { + + ofs.x=0; + ofs.y+=debug_size.y; + } + } + + + +} void RasterizerGLES2::_debug_shadows() { canvas_begin(); @@ -7255,10 +7796,11 @@ void RasterizerGLES2::canvas_begin() { canvas_tex=RID(); //material_shader.unbind(); canvas_shader.unbind(); + canvas_shader.set_custom_shader(0); canvas_shader.bind(); canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0); _set_color_attrib(Color(1,1,1)); - Transform canvas_transform; + canvas_transform=Transform(); canvas_transform.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f); float csy = 1.0; if (current_rt && current_rt_vflip) @@ -7272,6 +7814,9 @@ void RasterizerGLES2::canvas_begin() { canvas_opacity=1.0; canvas_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; + canvas_texscreen_used=false; + uses_texpixel_size=false; + canvas_last_shader=RID(); } @@ -7354,7 +7899,7 @@ void RasterizerGLES2::canvas_end_rect() { RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_texture) { - if (p_texture==canvas_tex) { + if (p_texture==canvas_tex && !rebind_texpixel_size) { if (canvas_tex.is_valid()) { Texture*texture=texture_owner.get(p_texture); return texture; @@ -7362,14 +7907,16 @@ RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_tex return NULL; } - + rebind_texpixel_size=false; if (p_texture.is_valid()) { + Texture*texture=texture_owner.get(p_texture); if (!texture) { canvas_tex=RID(); glBindTexture(GL_TEXTURE_2D,white_tex); + return NULL; } @@ -7378,6 +7925,9 @@ RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_tex glBindTexture(GL_TEXTURE_2D,texture->tex_id); canvas_tex=p_texture; + if (uses_texpixel_size) { + canvas_shader.set_uniform(CanvasShaderGLES2::TEXPIXEL_SIZE,Size2(1.0/texture->width,1.0/texture->height)); + } return texture; @@ -7720,8 +8270,18 @@ void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indic } if (p_indices) { - +#ifdef GLEW_ENABLED glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); +#else + static const int _max_draw_poly_indices = 16*1024; // change this size if needed!!! + ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); + static uint16_t _draw_poly_indices[_max_draw_poly_indices]; + for (int i=0; i<p_vertex_count; i++) { + _draw_poly_indices[i] = p_indices[i]; + }; + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, _draw_poly_indices ); +#endif + //glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); } else { glDrawArrays(GL_TRIANGLES,0,p_vertex_count); } @@ -7738,6 +8298,327 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) { //canvas_transform = Variant(p_transform); } + +void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { + + + CanvasItem *current_clip=NULL; + + canvas_opacity=1.0; + while(p_item_list) { + + CanvasItem *ci=p_item_list; + + if (ci->vp_render) { + if (draw_viewport_func) { + draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect); + } + memdelete(ci->vp_render); + ci->vp_render=NULL; + canvas_last_shader=RID(); + } + + if (current_clip!=ci->final_clip_owner) { + + current_clip=ci->final_clip_owner; + + //setup clip + if (current_clip) { + + glEnable(GL_SCISSOR_TEST); + glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + } else { + + glDisable(GL_SCISSOR_TEST); + } + } + + + //begin rect + CanvasItem *shader_owner = ci->shader_owner?ci->shader_owner:ci; + + if (shader_owner->shader!=canvas_last_shader) { + + Shader *shader = NULL; + if (shader_owner->shader.is_valid()) { + shader = this->shader_owner.get(shader_owner->shader); + if (shader && !shader->valid) { + shader=NULL; + } + } + + if (shader) { + canvas_shader.set_custom_shader(shader->custom_code_id); + if (canvas_shader.bind()) + rebind_texpixel_size=true; + + if (shader_owner->shader_version!=shader->version) { + //todo optimize uniforms + shader_owner->shader_version=shader->version; + } + //this can be optimized.. + int tex_id=1; + int idx=0; + for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { + + + Map<StringName,Variant>::Element *F=shader_owner->shader_param.find(E->key()); + Variant &v=F?F->get():E->get().default_value; + if (v.get_type()==Variant::_RID || v.get_type()==Variant::OBJECT) { + int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. + + glActiveTexture(GL_TEXTURE0+tex_id); + RID tex = v; + Texture *t=texture_owner.get(tex); + if (!t) + glBindTexture(GL_TEXTURE_2D,white_tex); + else + glBindTexture(t->target,t->tex_id); + + glUniform1i(loc,tex_id); + tex_id++; + + } else { + canvas_shader.set_custom_uniform(idx,v); + } + + idx++; + } + + + if (shader->has_texscreen && framebuffer.active) { + + int x = viewport.x; + int y = window_size.height-(viewport.height+viewport.y); + + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,tex_id); + glActiveTexture(GL_TEXTURE0+tex_id); + glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + if (framebuffer.scale==1 && !canvas_texscreen_used) { +#ifdef GLEW_ENABLED + glReadBuffer(GL_COLOR_ATTACHMENT0); +#endif + glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); + if (current_clip) { + print_line(" a clip "); + } + + canvas_texscreen_used=true; + } + tex_id++; + + } + + if (tex_id>1) { + glActiveTexture(GL_TEXTURE0); + } + if (shader->has_screen_uv) { + canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height)); + } + + if (shader->uses_time) { + canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0)); + draw_next_frame=true; + } + //if uses TIME - draw_next_frame=true + + uses_texpixel_size=shader->uses_texpixel_size; + + } else { + canvas_shader.set_custom_shader(0); + canvas_shader.bind(); + uses_texpixel_size=false; + + } + + + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); + canvas_last_shader=shader_owner->shader; + } + + canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform); + canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + + + bool reclip=false; + + if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) { + + switch(ci->blend_mode) { + + case VS::MATERIAL_BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + } break; + case VS::MATERIAL_BLEND_MODE_ADD: { + + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + + } break; + case VS::MATERIAL_BLEND_MODE_SUB: { + + glBlendEquation(GL_FUNC_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case VS::MATERIAL_BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_DST_COLOR,GL_ZERO); + } break; + case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + } break; + + } + + canvas_blend_mode=ci->blend_mode; + } + + int cc=ci->commands.size(); + CanvasItem::Command **commands = ci->commands.ptr(); + + canvas_opacity = ci->final_opacity; + + for(int i=0;i<cc;i++) { + + CanvasItem::Command *c=commands[i]; + + switch(c->type) { + case CanvasItem::Command::TYPE_LINE: { + + CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c); + canvas_draw_line(line->from,line->to,line->color,line->width); + } break; + case CanvasItem::Command::TYPE_RECT: { + + CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c); +// canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); +#if 0 + int flags=0; + + if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { + flags|=Rasterizer::CANVAS_RECT_REGION; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { + flags|=Rasterizer::CANVAS_RECT_TILE; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { + + flags|=Rasterizer::CANVAS_RECT_FLIP_H; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { + + flags|=Rasterizer::CANVAS_RECT_FLIP_V; + } +#else + + int flags=rect->flags; +#endif + canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate); + + } break; + case CanvasItem::Command::TYPE_STYLE: { + + CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c); + canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); + + } break; + case CanvasItem::Command::TYPE_PRIMITIVE: { + + CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c); + canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width); + } break; + case CanvasItem::Command::TYPE_POLYGON: { + + CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c); + canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); + + } break; + + case CanvasItem::Command::TYPE_POLYGON_PTR: { + + CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c); + canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false); + } break; + case CanvasItem::Command::TYPE_CIRCLE: { + + CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c); + static const int numpoints=32; + Vector2 points[numpoints+1]; + points[numpoints]=circle->pos; + int indices[numpoints*3]; + + for(int i=0;i<numpoints;i++) { + + points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius; + indices[i*3+0]=i; + indices[i*3+1]=(i+1)%numpoints; + indices[i*3+2]=numpoints; + } + canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); + //canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); + } break; + case CanvasItem::Command::TYPE_TRANSFORM: { + + CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c); + canvas_set_transform(transform->xform); + } break; + case CanvasItem::Command::TYPE_BLEND_MODE: { + + CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c); + canvas_set_blend_mode(bm->blend_mode); + + } break; + case CanvasItem::Command::TYPE_CLIP_IGNORE: { + + CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c); + if (current_clip) { + + if (ci->ignore!=reclip) { + if (ci->ignore) { + + glDisable(GL_SCISSOR_TEST); + reclip=true; + } else { + + glEnable(GL_SCISSOR_TEST); + glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + reclip=false; + } + } + } + + + + } break; + } + } + + + if (reclip) { + + glEnable(GL_SCISSOR_TEST); + glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + } + + + + p_item_list=p_item_list->next; + } + + if (current_clip) { + glDisable(GL_SCISSOR_TEST); + } + +} + /* ENVIRONMENT */ RID RasterizerGLES2::environment_create() { @@ -7810,6 +8691,78 @@ Variant RasterizerGLES2::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + + +RID RasterizerGLES2::sampled_light_dp_create(int p_width,int p_height) { + + SampledLight *slight = memnew(SampledLight); + slight->w=p_width; + slight->h=p_height; + slight->multiplier=1.0; + slight->is_float=float_linear_supported; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1,&slight->texture); + glBindTexture(GL_TEXTURE_2D, slight->texture); +// for debug, but glitchy +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Remove artifact on the edges of the shadowmap + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + if (slight->is_float) { +#ifdef GLEW_ENABLED + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#endif + } else { + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + } + + return sampled_light_owner.make_rid(slight); +} + +void RasterizerGLES2::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + SampledLight *slight = sampled_light_owner.get(p_sampled_light); + ERR_FAIL_COND(!slight); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, slight->texture); + + if (slight->is_float) { + +#ifdef GLEW_ENABLED + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#else + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#endif + + } else { + //convert to bytes + uint8_t *tex8 = (uint8_t*)alloca(slight->w*slight->h*4); + const float* src=(const float*)p_data; + + for(int i=0;i<slight->w*slight->h*4;i++) { + + tex8[i]=Math::fast_ftoi(CLAMP(src[i]*255.0,0.0,255.0)); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_UNSIGNED_BYTE,p_data); + } + + slight->multiplier=p_multiplier; + +} + /*MISC*/ bool RasterizerGLES2::is_texture(const RID& p_rid) const { @@ -8029,6 +8982,13 @@ void RasterizerGLES2::free(const RID& p_rid) { memdelete(render_target->texture_ptr); render_target_owner.free(p_rid); memdelete( render_target ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + glDeleteTextures(1,&sampled_light->texture); + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); }; } @@ -8617,6 +9577,16 @@ void RasterizerGLES2::init() { use_texture_instancing=false; use_attribute_instancing=true; full_float_fb_supported=true; + srgb_supported=true; + latc_supported=true; + s3tc_srgb_supported=true; + use_anisotropic_filter=true; + float_linear_supported=true; + float_supported=true; + use_rgba_shadowmaps=false; + + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level); + anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0))); #ifdef OSX_ENABLED use_rgba_shadowmaps=true; use_fp16_fb=false; @@ -8636,17 +9606,33 @@ void RasterizerGLES2::init() { use_rgba_shadowmaps=true; //no other way, go back to rgba } pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc"); + pvr_srgb_supported=extensions.has("GL_EXT_pvrtc_sRGB"); etc_supported=extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); use_depth24 = extensions.has("GL_OES_depth24"); s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); use_half_float = extensions.has("GL_OES_vertex_half_float"); atitc_supported=extensions.has("GL_AMD_compressed_ATC_texture"); + + srgb_supported=extensions.has("GL_EXT_sRGB"); + s3tc_srgb_supported = s3tc_supported && extensions.has("GL_EXT_texture_compression_s3tc"); + latc_supported = extensions.has("GL_EXT_texture_compression_latc"); + anisotropic_level=1.0; + use_anisotropic_filter=extensions.has("GL_EXT_texture_filter_anisotropic"); + if (use_anisotropic_filter) { + glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level); + anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0))); + } + + print_line("S3TC: "+itos(s3tc_supported)+" ATITC: "+itos(atitc_supported)); GLint vtf; glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,&vtf); - use_hw_skeleton_xform=vtf>0 && extensions.has("GL_OES_texture_float"); + float_supported = extensions.has("GL_OES_texture_float"); + use_hw_skeleton_xform=vtf>0 && float_supported; + float_linear_supported = extensions.has("GL_OES_texture_float_linear"); + //if (extensions.has("GL_QCOM_tiled_rendering")) // use_hw_skeleton_xform=false; GLint mva; @@ -8684,7 +9670,7 @@ void RasterizerGLES2::init() { - + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units); //read_depth_supported=false; { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index a9fa7994e..0f77d18de 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -73,7 +73,10 @@ class RasterizerGLES2 : public Rasterizer { uint8_t *skinned_buffer; int skinned_buffer_size; bool pvr_supported; + bool pvr_srgb_supported; bool s3tc_supported; + bool s3tc_srgb_supported; + bool latc_supported; bool etc_supported; bool atitc_supported; bool npo2_textures_available; @@ -82,6 +85,10 @@ class RasterizerGLES2 : public Rasterizer { bool full_float_fb_supported; bool use_shadow_mapping; bool use_fp16_fb; + bool srgb_supported; + bool float_supported; + bool float_linear_supported; + ShadowFilterTechnique shadow_filter; bool use_shadow_esm; @@ -91,13 +98,15 @@ class RasterizerGLES2 : public Rasterizer { bool use_texture_instancing; bool use_attribute_instancing; bool use_rgba_shadowmaps; + bool use_anisotropic_filter; + float anisotropic_level; bool use_half_float; Vector<float> skel_default; - Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed); + Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed); class RenderTarget; @@ -110,6 +119,7 @@ class RasterizerGLES2 : public Rasterizer { GLenum target; GLenum gl_format_cache; + GLenum gl_internal_format_cache; int gl_components_cache; int data_size; //original data size, useful for retrieving back bool has_alpha; @@ -181,10 +191,13 @@ class RasterizerGLES2 : public Rasterizer { bool writes_vertex; bool uses_discard; bool uses_time; + bool uses_normal; + bool uses_texpixel_size; Map<StringName,ShaderLanguage::Uniform> uniforms; StringName first_texture; + Map<StringName,RID> default_textures; SelfList<Shader> dirty_list; @@ -203,6 +216,7 @@ class RasterizerGLES2 : public Rasterizer { writes_vertex=false; uses_discard=false; uses_time=false; + uses_normal=false; } @@ -230,8 +244,9 @@ class RasterizerGLES2 : public Rasterizer { struct UniformData { + bool inuse; bool istexture; - Variant value; + Variant value; int index; }; @@ -601,7 +616,7 @@ class RasterizerGLES2 : public Rasterizer { mutable SelfList<Skeleton>::List _skeleton_dirty_list; - template<bool USE_NORMAL, bool USE_TANGENT> + template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE> void _skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms); struct Light { @@ -697,6 +712,18 @@ class RasterizerGLES2 : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + + struct SampledLight { + + int w,h; + GLuint texture; + float multiplier; + bool is_float; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + + struct ViewportData { //1x1 fbo+texture for storing previous HDR value @@ -794,6 +821,7 @@ class RasterizerGLES2 : public Rasterizer { RID shadow_material; Material *shadow_mat_ptr; + int max_texture_units; GLuint base_framebuffer; GLuint gui_quad_buffer; @@ -1064,6 +1092,8 @@ class RasterizerGLES2 : public Rasterizer { void _debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,Point2& ofs); void _debug_shadows(); void _debug_luminances(); + void _debug_samplers(); + /***********/ @@ -1142,6 +1172,13 @@ class RasterizerGLES2 : public Rasterizer { GLuint white_tex; RID canvas_tex; float canvas_opacity; + bool uses_texpixel_size; + bool rebind_texpixel_size; + Transform canvas_transform; + RID canvas_last_shader; + bool canvas_texscreen_used; + + _FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture); VS::MaterialBlendMode canvas_blend_mode; @@ -1172,7 +1209,7 @@ class RasterizerGLES2 : public Rasterizer { RID overdraw_material; mutable MaterialShaderGLES2 material_shader; - CanvasShaderGLES2 canvas_shader; + mutable CanvasShaderGLES2 canvas_shader; BlurShaderGLES2 blur_shader; CopyShaderGLES2 copy_shader; @@ -1230,6 +1267,10 @@ public: 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; + + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name); /* COMMON MATERIAL API */ @@ -1507,6 +1548,8 @@ public: virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); virtual void canvas_set_transform(const Matrix32& p_transform); + virtual void canvas_render_items(CanvasItem *p_item_list); + /* ENVIRONMENT */ @@ -1524,6 +1567,9 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier); /*MISC*/ diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index ada9efa4b..f1ddcf800 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -131,6 +131,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a SL::BlockNode *bnode=(SL::BlockNode*)p_node; //variables + code+="{"ENDL; for(Map<StringName,SL::DataType>::Element *E=bnode->variables.front();E;E=E->next()) { code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";"ENDL; @@ -141,10 +142,12 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";"ENDL; } + code+="}"ENDL; } break; case SL::Node::TYPE_VARIABLE: { SL::VariableNode *vnode=(SL::VariableNode*)p_node; + if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) { if (vnode->name==vname_vertex && p_assign_left) { @@ -171,11 +174,17 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } + + + if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) { if (vnode->name==vname_discard) { uses_discard=true; } + if (vnode->name==vname_normalmap) { + uses_normalmap=true; + } if (vnode->name==vname_screen_uv) { uses_screen_uv=true; } @@ -209,6 +218,47 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } } + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX) { + + if (vnode->name==vname_var1_interp) { + flags->use_var1_interp=true; + } + if (vnode->name==vname_var2_interp) { + flags->use_var2_interp=true; + } + + } + + + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT) { + + + if (vnode->name==vname_texpixel_size) { + uses_texpixel_size=true; + } + if (vnode->name==vname_normal) { + uses_normal=true; + } + + if (vnode->name==vname_screen_uv) { + uses_screen_uv=true; + } + + if (vnode->name==vname_var1_interp) { + flags->use_var1_interp=true; + } + if (vnode->name==vname_var2_interp) { + flags->use_var2_interp=true; + } + } + + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT) { + + if (vnode->name==vname_light) { + uses_light=true; + } + + } if (vnode->name==vname_time) { uses_time=true; @@ -354,7 +404,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } else if (callfunc=="texscreen") { //create the call to sample the screen, and clamp it uses_texscreen=true; - code="(texture2D( texscreen_tex, min(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_mult))).rgb"; + code="(texture2D( texscreen_tex, clamp(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_clamp.xy,texscreen_screen_clamp.zw))).rgb"; //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; break; } else if (callfunc=="texpos") { @@ -546,6 +596,9 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT uses_screen_uv=false; uses_light=false; uses_time=false; + uses_normalmap=false; + uses_normal=false; + uses_texpixel_size=false; vertex_code_writes_vertex=false; uniforms=r_uniforms; flags=&r_flags; @@ -555,6 +608,8 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.use_tangent_interp=false; r_flags.use_var1_interp=false; r_flags.use_var2_interp=false; + r_flags.uses_normalmap=false; + r_flags.uses_normal=false; String error; int errline,errcol; @@ -576,8 +631,12 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.uses_screen_uv=uses_screen_uv; r_flags.uses_light=uses_light; r_flags.uses_time=uses_time; + r_flags.uses_normalmap=uses_normalmap; + r_flags.uses_normal=uses_normalmap; + r_flags.uses_texpixel_size=uses_texpixel_size; r_code_line=code; r_globals_line=global_code; + return OK; } @@ -631,6 +690,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { replace_table["cross" ]="cross"; replace_table["normalize"]= "normalize"; replace_table["reflect"]= "reflect"; + replace_table["refract"]= "refract"; replace_table["tex"]= "tex"; replace_table["texa"]= "texa"; replace_table["tex2"]= "tex2"; @@ -669,7 +729,10 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { //mode_replace_table[1]["POSITION"]="IN_POSITION"; mode_replace_table[1]["NORMAL"]="normal"; mode_replace_table[1]["TANGENT"]="tangent"; + mode_replace_table[1]["POSITION"]="gl_Position"; mode_replace_table[1]["BINORMAL"]="binormal"; + mode_replace_table[1]["NORMALMAP"]="normalmap"; + mode_replace_table[1]["NORMALMAP_DEPTH"]="normaldepth"; mode_replace_table[1]["VAR1"]="var1_interp"; mode_replace_table[1]["VAR2"]="var2_interp"; mode_replace_table[1]["UV"]="uv"; @@ -709,6 +772,42 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[2]["POINT_COORD"]="gl_PointCoord"; mode_replace_table[2]["TIME"]="time"; + mode_replace_table[3]["SRC_VERTEX"]="src_vtx"; + mode_replace_table[3]["VERTEX"]="outvec.xy"; + mode_replace_table[3]["UV"]="uv_interp"; + mode_replace_table[3]["COLOR"]="color_interp"; + mode_replace_table[3]["VAR1"]="var1_interp"; + mode_replace_table[3]["VAR2"]="var2_interp"; + mode_replace_table[3]["POINT_SIZE"]="gl_PointSize"; + mode_replace_table[3]["WORLD_MATRIX"]="modelview_matrix"; + mode_replace_table[3]["PROJECTION_MATRIX"]="projection_matrix"; + mode_replace_table[3]["EXTRA_MATRIX"]="extra_matrix"; + mode_replace_table[3]["TIME"]="time"; + + mode_replace_table[4]["POSITION"]="gl_Position"; + mode_replace_table[4]["NORMAL"]="normal"; + mode_replace_table[4]["UV"]="uv_interp"; + mode_replace_table[4]["SRC_COLOR"]="color_interp"; + mode_replace_table[4]["COLOR"]="color"; + mode_replace_table[4]["TEXTURE"]="texture"; + mode_replace_table[4]["TEXTURE_PIXEL_SIZE"]="texpixel_size"; + mode_replace_table[4]["VAR1"]="var1_interp"; + mode_replace_table[4]["VAR2"]="var2_interp"; + mode_replace_table[4]["SCREEN_UV"]="screen_uv"; + mode_replace_table[4]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[4]["TIME"]="time"; + + mode_replace_table[5]["SRC_COLOR"]="color"; + mode_replace_table[5]["COLOR"]="color"; + mode_replace_table[5]["NORMAL"]="normal"; + mode_replace_table[5]["LIGHT_DIR"]="light_dir"; + mode_replace_table[5]["LIGHT_DISTANCE"]="light_distance"; + mode_replace_table[5]["LIGHT"]="light"; + mode_replace_table[5]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[5]["TIME"]="time"; + + + //mode_replace_table[2]["SCREEN_POS"]="SCREEN_POS"; //mode_replace_table[2]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE"; @@ -728,5 +827,8 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_vertex="VERTEX"; vname_light="LIGHT"; vname_time="TIME"; + vname_normalmap="NORMALMAP"; + vname_normal="NORMAL"; + vname_texpixel_size="TEXTURE_PIXEL_SIZE"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 3dfdd81c0..a10fa6dfe 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -50,6 +50,9 @@ private: bool uses_discard; bool uses_time; bool uses_screen_uv; + bool uses_normalmap; + bool uses_normal; + bool uses_texpixel_size; bool vertex_code_writes_vertex; Flags *flags; @@ -66,6 +69,9 @@ private: StringName vname_vertex; StringName vname_light; StringName vname_time; + StringName vname_normalmap; + StringName vname_normal; + StringName vname_texpixel_size; Map<StringName,ShaderLanguage::Uniform> *uniforms; @@ -77,7 +83,7 @@ private: String replace_string(const StringName& p_string); - Map<StringName,StringName> mode_replace_table[3]; + Map<StringName,StringName> mode_replace_table[9]; Map<StringName,StringName> replace_table; public: @@ -87,6 +93,7 @@ public: bool uses_alpha; bool uses_texscreen; bool uses_texpos; + bool uses_normalmap; bool vertex_code_writes_vertex; bool uses_discard; bool uses_screen_uv; @@ -98,6 +105,8 @@ public: bool use_var2_interp; bool uses_light; bool uses_time; + bool uses_normal; + bool uses_texpixel_size; }; Error compile(const String& p_code, ShaderLanguage::ShaderType p_type, String& r_code_line, String& r_globals_line, Flags& r_flags, Map<StringName,ShaderLanguage::Uniform> *r_uniforms=NULL); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index f36741d58..464cb9e18 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -18,19 +18,56 @@ attribute highp vec2 uv_attrib; // attrib:4 varying vec2 uv_interp; varying vec4 color_interp; +#if defined(USE_TIME) +uniform float time; +#endif + + +#ifdef USE_LIGHTING + +uniform highp mat4 light_matrix; +varying vec4 light_tex_pos; + +#endif + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + //uniform bool snap_pixels; +VERTEX_SHADER_GLOBALS + void main() { color_interp = color_attrib; uv_interp = uv_attrib; highp vec4 outvec = vec4(vertex, 1.0); +{ + vec2 src_vtx=outvec.xy; +VERTEX_SHADER_CODE + +} outvec = extra_matrix * outvec; outvec = modelview_matrix * outvec; #ifdef USE_PIXEL_SNAP - outvec.xy=floor(outvec.xy+0.5); + outvec.xy=floor(outvec.xy+0.5); #endif + + +#ifdef USE_LIGHTING + + light_tex_pos.xy = light_matrix * outvec; + light_tex_pos.zw=outvec.xy - light_matrix[4].xy; //likely wrong + +#endif + + gl_Position = projection_matrix * outvec; } @@ -54,17 +91,112 @@ varying vec4 color_interp; #endif +#if defined(ENABLE_SCREEN_UV) + +uniform vec2 screen_uv_mult; + +#endif + +#if defined(ENABLE_TEXSCREEN) + +uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; +uniform sampler2D texscreen_tex; + +#endif + + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + +#if defined(USE_TIME) +uniform float time; +#endif + + +#ifdef USE_LIGHTING + +uniform sampler2D light_texture; +varying vec4 light_tex_pos; + +#ifdef USE_SHADOWS + +uniform sampler2D shadow_texture; +uniform float shadow_attenuation; + +#endif + +#endif + +#if defined(USE_TEXPIXEL_SIZE) +uniform vec2 texpixel_size; +#endif + + +FRAGMENT_SHADER_GLOBALS + + void main() { vec4 color = color_interp; - +#if defined(NORMAL_USED) + vec3 normal = vec3(0,0,1); +#endif + color *= texture2D( texture, uv_interp ); +#if defined(ENABLE_SCREEN_UV) + vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; +#endif +{ +FRAGMENT_SHADER_CODE +} #ifdef DEBUG_ENCODED_32 highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ); color = vec4(vec3(enc32),1.0); #endif +#ifdef USE_LIGHTING + + float att=1.0; + + vec3 light = texture2D(light_texture,light_tex_pos).rgb; +#ifdef USE_SHADOWS + //this might not be that great on mobile? + float light_dist = length(light_texture.zw); + float light_angle = atan2(light_texture.x,light_texture.z) + 1.0 * 0.5; + float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0)); + if (light_dist>shadow_dist) { + light*=shadow_attenuation; + } +//use shadows +#endif + +#if defined(USE_LIGHT_SHADER_CODE) +//light is written by the light shader +{ + vec2 light_dir = normalize(light_tex_pos.zw); + float light_distance = length(light_tex_pos.zw); +LIGHT_SHADER_CODE +} +#else + +#if defined(NORMAL_USED) + vec2 light_normal = normalize(light_tex_pos.zw); + light = color.rgb * light * max(dot(light_normal,normal),0); +#endif + + color.rgb=light; +//light shader code +#endif + +//use lighting +#endif // color.rgb*=color.a; gl_FragColor = color; diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index d8fb03f3a..ae7185a1d 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -46,6 +46,15 @@ precision mediump int; #endif + +float sRGB_gamma_correct(float c){ + float a = 0.055; + if(c < 0.0031308) + return 12.92*c; + else + return (1.0+a)*pow(c, 1.0/2.4) - a; +} + #define LUM_RANGE 4.0 @@ -407,15 +416,26 @@ void main() { #ifdef USE_SRGB +#if 0 + //this was fast, but was commented out because it looked kind of shitty, might it be fixable? + { //i have my doubts about how fast this is + color.rgb = min(color.rgb,vec3(1.0)); //clamp just in case vec3 S1 = sqrt(color.rgb); vec3 S2 = sqrt(S1); vec3 S3 = sqrt(S2); color.rgb = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.225411470 * color.rgb; } +#else + + color.r=sRGB_gamma_correct(color.r); + color.g=sRGB_gamma_correct(color.g); + color.b=sRGB_gamma_correct(color.b); + #endif +#endif #ifdef USE_HDR_COPY diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index ad8a364ac..38fb03ab5 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -60,7 +60,7 @@ uniform float normal_mult; #ifdef USE_SKELETON attribute vec4 bone_indices; // attrib:6 attribute vec4 bone_weights; // attrib:7 -uniform highp sampler2D skeleton_matrices; // texunit:6 +uniform highp sampler2D skeleton_matrices; uniform highp float skeltex_pixel_size; #endif @@ -76,7 +76,7 @@ attribute highp vec4 instance_row3; // attrib:11 #ifdef USE_TEXTURE_INSTANCING attribute highp vec3 instance_uv; // attrib:6 -uniform highp sampler2D instance_matrices; // texunit:6 +uniform highp sampler2D instance_matrices; #endif @@ -292,11 +292,21 @@ void main() { normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz); #if defined(ENABLE_COLOR_INTERP) +#ifdef USE_COLOR_ATTRIB_SRGB_TO_LINEAR + + color_interp = vec4( + color_attrib.r<0.04045 ? color_attrib.r * (1.0 / 12.92) : pow((color_attrib.r + 0.055) * (1.0 / (1 + 0.055)), 2.4), + color_attrib.g<0.04045 ? color_attrib.g * (1.0 / 12.92) : pow((color_attrib.g + 0.055) * (1.0 / (1 + 0.055)), 2.4), + color_attrib.b<0.04045 ? color_attrib.b * (1.0 / 12.92) : pow((color_attrib.b + 0.055) * (1.0 / (1 + 0.055)), 2.4), + color_attrib.a + ); +#else color_interp = color_attrib; #endif +#endif #if defined(ENABLE_TANGENT_INTERP) - tangent_interp=normalize(tangent_in); + tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz); binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf ); #endif @@ -585,8 +595,10 @@ uniform float time; varying highp vec3 ambient_octree_coords; uniform highp float ambient_octree_lattice_size; uniform highp vec2 ambient_octree_pix_size; +uniform highp vec2 ambient_octree_light_pix_size; uniform highp float ambient_octree_lattice_divide; uniform highp sampler2D ambient_octree_tex; +uniform highp sampler2D ambient_octree_light_tex; uniform float ambient_octree_multiplier; uniform int ambient_octree_steps; @@ -599,6 +611,12 @@ uniform float ambient_lightmap_multiplier; #endif +#ifdef ENABLE_AMBIENT_DP_SAMPLER + +uniform highp sampler2D ambient_dp_sampler; +uniform float ambient_dp_sampler_multiplier; + +#endif FRAGMENT_SHADER_GLOBALS @@ -761,6 +779,7 @@ uniform highp mat4 camera_inverse_transform; #if defined(ENABLE_TEXSCREEN) uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; uniform sampler2D texscreen_tex; #endif @@ -809,6 +828,12 @@ void main() { vec4 color = color_interp; #endif +#if defined(ENABLE_NORMALMAP) + + vec3 normalmap = vec3(0.0); +#endif + + float normaldepth=1.0; @@ -823,6 +848,12 @@ FRAGMENT_SHADER_CODE } +#if defined(ENABLE_NORMALMAP) + + normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side; + +#endif + #if defined(ENABLE_DISCARD) if (discard_) { //easy to eliminate dead code @@ -896,12 +927,12 @@ FRAGMENT_SHADER_CODE } //sample color - octant_uv=(octant_uv+0.5)*ambient_octree_pix_size; + octant_uv=(octant_uv+0.5)*ambient_octree_light_pix_size; highp vec3 sub=(mod(ambient_octree_coords,ld)/ld); - octant_uv.xy+=sub.xy*ambient_octree_pix_size.xy; - vec3 col_up=texture2D(ambient_octree_tex,octant_uv).rgb; - octant_uv.y+=ambient_octree_pix_size.y*2.0; - vec3 col_down=texture2D(ambient_octree_tex,octant_uv).rgb; + octant_uv.xy+=sub.xy*ambient_octree_light_pix_size.xy; + vec3 col_up=texture2D(ambient_octree_light_tex,octant_uv).rgb; + octant_uv.y+=ambient_octree_light_pix_size.y*2.0; + vec3 col_down=texture2D(ambient_octree_light_tex,octant_uv).rgb; ambientmap_color=mix(col_up,col_down,sub.z)*ambient_octree_multiplier; ambientmap_color*=diffuse.rgb; @@ -912,6 +943,26 @@ FRAGMENT_SHADER_CODE +#ifdef ENABLE_AMBIENT_DP_SAMPLER + + vec3 ambientmap_color = vec3(0.0,0.0,0.0); + + { + + vec3 dp_normal = normalize((vec4(normal,0) * camera_inverse_transform).xyz); + vec2 ambient_uv = (dp_normal.xy / (1.0+abs(dp_normal.z)))*0.5+0.5; //dual paraboloid + ambient_uv.y*=0.5; + if (dp_normal.z<0) { + + ambient_uv.y=(0.5-ambient_uv.y)+0.5; + + } + + ambientmap_color = texture2D(ambient_dp_sampler,ambient_uv ).rgb * ambient_dp_sampler_multiplier; + ambientmap_color*=diffuse.rgb; + } + +#endif @@ -1164,7 +1215,7 @@ LIGHT_SHADER_CODE # if !defined(LIGHT_TYPE_DIRECTIONAL) && !defined(LIGHT_TYPE_OMNI) && !defined (LIGHT_TYPE_SPOT) //none #ifndef SHADELESS - diffuse.rgb=vec3(0.0,0.0,0.0); + diffuse.rgb=ambient_light *diffuse.rgb; #endif # endif @@ -1180,7 +1231,7 @@ LIGHT_SHADER_CODE vec3 ambient = const_light_mult*ambient_light*diffuse.rgb; # if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) - ambient*=diffuse_interp.a; //attenuation affects ambient too +// ambient*=diffuse_interp.a; //attenuation affects ambient too # endif @@ -1202,7 +1253,7 @@ LIGHT_SHADER_CODE #endif -#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) +#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) || defined(ENABLE_AMBIENT_DP_SAMPLER) diffuse.rgb+=ambientmap_color; #endif diff --git a/drivers/mpc/audio_stream_mpc.cpp b/drivers/mpc/audio_stream_mpc.cpp index e1f9aacf5..cd8125c9a 100644 --- a/drivers/mpc/audio_stream_mpc.cpp +++ b/drivers/mpc/audio_stream_mpc.cpp @@ -8,6 +8,7 @@ Error AudioStreamMPC::_open_file() { f=NULL; } Error err; + //printf("mpc open file %ls\n", file.c_str()); f=FileAccess::open(file,FileAccess::READ,&err); if (err) { @@ -16,9 +17,10 @@ Error AudioStreamMPC::_open_file() { return err; } - f->seek_end(0); - streamlen=f->get_pos(); - f->seek(0); + //printf("file size is %i\n", f->get_len()); + //f->seek_end(0); + streamlen=f->get_len(); + //f->seek(0); if (streamlen<=0) { memdelete(f); f=NULL; @@ -275,7 +277,7 @@ void AudioStreamMPC::stop() { } bool AudioStreamMPC::is_playing() const { - return active; + return active || (get_total() - get_todo() -1 > 0); } void AudioStreamMPC::set_paused(bool p_paused) { diff --git a/drivers/ogg/SCsub b/drivers/ogg/SCsub index 5cdc3ea1c..dd5989006 100644 --- a/drivers/ogg/SCsub +++ b/drivers/ogg/SCsub @@ -6,5 +6,6 @@ ogg_sources = [ "ogg/framing.c", ] -env.drivers_sources+=ogg_sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources+=ogg_sources diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index 316397ed8..6fc20f36f 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -102,6 +102,9 @@ Error ImageLoaderPNG::_load_image(void *rf_up,png_rw_ptr p_func,Image *p_image) png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); + png_textp t; + //https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp + //png_get_text(png,info,) /* printf("Image width:%i\n", width); printf("Image Height:%i\n", height); diff --git a/drivers/png/pngpriv.h b/drivers/png/pngpriv.h index 67e486c57..56532f4ee 100644 --- a/drivers/png/pngpriv.h +++ b/drivers/png/pngpriv.h @@ -341,7 +341,11 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ # define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strlen lstrlenA +# ifdef WINRT_ENABLED +# define png_strlen strlen +# else +# define png_strlen lstrlenA +# endif # define png_memcmp memcmp # define png_memcpy CopyMemory # define png_memset memset diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index a898f6e61..462051b21 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -30,6 +30,8 @@ #include "scene/resources/texture.h" #include "drivers/png/png.h" #include "os/file_access.h" +#include "globals.h" +#include "core/image.h" static void _write_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) { @@ -45,12 +47,56 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t ERR_EXPLAIN("Can't save empty texture as PNG"); ERR_FAIL_COND_V(!texture->get_width() || !texture->get_height(),ERR_INVALID_PARAMETER); + Image img = texture->get_data(); - if (img.get_format() > Image::FORMAT_INDEXED_ALPHA) - img.decompress(); + Error err = save_image(p_path, img); + + if (err == OK) { + + bool global_filter = Globals::get_singleton()->get("image_loader/filter"); + bool global_mipmaps = Globals::get_singleton()->get("image_loader/gen_mipmaps"); + bool global_repeat = Globals::get_singleton()->get("image_loader/repeat"); + + String text; + + if (global_filter!=bool(texture->get_flags()&Texture::FLAG_FILTER)) { + text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"filter=true\n":"filter=false\n"; + } + if (global_mipmaps!=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)) { + text+=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)?"gen_mipmaps=true\n":"gen_mipmaps=false\n"; + } + if (global_repeat!=bool(texture->get_flags()&Texture::FLAG_REPEAT)) { + text+=bool(texture->get_flags()&Texture::FLAG_REPEAT)?"repeat=true\n":"repeat=false\n"; + } + if (bool(texture->get_flags()&Texture::FLAG_ANISOTROPIC_FILTER)) { + text+="anisotropic=true\n"; + } + if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) { + text+="tolinear=true\n"; + } + + if (text!="" || FileAccess::exists(p_path+".flags")) { - ERR_FAIL_COND_V(img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER); + FileAccess* f = FileAccess::open(p_path+".flags",FileAccess::WRITE); + if (f) { + + f->store_string(text); + memdelete(f); + } + } + } + + + return err; +}; + +Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) { + + if (p_img.get_format() > Image::FORMAT_INDEXED_ALPHA) + p_img.decompress(); + + ERR_FAIL_COND_V(p_img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER); png_structp png_ptr; png_infop info_ptr; @@ -88,7 +134,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t int cs=0; - switch(img.get_format()) { + switch(p_img.get_format()) { case Image::FORMAT_GRAYSCALE: { @@ -112,14 +158,14 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } break; default: { - if (img.detect_alpha()) { + if (p_img.detect_alpha()) { - img.convert(Image::FORMAT_RGBA); + p_img.convert(Image::FORMAT_RGBA); pngf=PNG_COLOR_TYPE_RGB_ALPHA; cs=4; } else { - img.convert(Image::FORMAT_RGB); + p_img.convert(Image::FORMAT_RGB); pngf=PNG_COLOR_TYPE_RGB; cs=3; } @@ -127,8 +173,8 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } } - int w = img.get_width(); - int h = img.get_height(); + int w = p_img.get_width(); + int h = p_img.get_height(); png_set_IHDR(png_ptr, info_ptr, w,h, 8, pngf, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); @@ -143,7 +189,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } - DVector<uint8_t>::Read r = img.get_data().read(); + DVector<uint8_t>::Read r = p_img.get_data().read(); row_pointers = (png_bytep*)memalloc(sizeof(png_bytep)*h); for(int i=0;i<h;i++) { @@ -164,7 +210,6 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t png_write_end(png_ptr, NULL); memdelete(f); - /* cleanup heap allocation */ return OK; @@ -181,3 +226,8 @@ void ResourceSaverPNG::get_recognized_extensions(const RES& p_resource,List<Stri } } + +ResourceSaverPNG::ResourceSaverPNG() { + + Image::save_png_func = &save_image; +}; diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index 7da50150e..116d425d2 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -6,9 +6,13 @@ class ResourceSaverPNG : public ResourceFormatSaver { public: + static Error save_image(const String &p_path, Image& p_img); + virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); virtual bool recognize(const RES& p_resource) const; virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const; + + ResourceSaverPNG(); }; diff --git a/drivers/gles1/SCsub b/drivers/pulseaudio/SCsub index 6a3e474ea..9fbb467ba 100644 --- a/drivers/gles1/SCsub +++ b/drivers/pulseaudio/SCsub @@ -1,5 +1,5 @@ Import('env') -Export('env'); env.add_source_files(env.drivers_sources,"*.cpp") +Export('env') diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp new file mode 100644 index 000000000..dfe9ddc55 --- /dev/null +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -0,0 +1,194 @@ +/*************************************************************************/ +/* audio_driver_alsa.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "audio_driver_pulseaudio.h" + +#ifdef PULSEAUDIO_ENABLED + +#include <pulse/error.h> + +#include "globals.h" + +Error AudioDriverPulseAudio::init() { + + active = false; + thread_exited = false; + exit_thread = false; + pcm_open = false; + samples_in = NULL; + samples_out = NULL; + + mix_rate = 44100; + output_format = OUTPUT_STEREO; + channels = 2; + + pa_sample_spec spec; + spec.format = PA_SAMPLE_S16LE; + spec.channels = channels; + spec.rate = mix_rate; + + int error_code; + pulse = pa_simple_new(NULL, // default server + "Godot", // application name + PA_STREAM_PLAYBACK, + NULL, // default device + "Sound", // stream description + &spec, + NULL, // use default channel map + NULL, // use default buffering attributes + &error_code + ); + + if (pulse == NULL) { + + fprintf(stderr, "PulseAudio ERR: %s\n", pa_strerror(error_code));\ + ERR_FAIL_COND_V(pulse == NULL, ERR_CANT_OPEN); + } + + int latency = GLOBAL_DEF("audio/output_latency", 25); + buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + + samples_in = memnew_arr(int32_t, buffer_size * channels); + samples_out = memnew_arr(int16_t, buffer_size * channels); + + mutex = Mutex::create(); + thread = Thread::create(AudioDriverPulseAudio::thread_func, this); + + return OK; +} + +void AudioDriverPulseAudio::thread_func(void* p_udata) { + + AudioDriverPulseAudio* ad = (AudioDriverPulseAudio*)p_udata; + + while (!ad->exit_thread) { + + if (!ad->active) { + + for (unsigned int i=0; i < ad->buffer_size * ad->channels; i++) { + + ad->samples_out[i] = 0; + } + + } else { + + ad->lock(); + + ad->audio_server_process(ad->buffer_size, ad->samples_in); + + ad->unlock(); + + for (unsigned int i=0; i < ad->buffer_size * ad->channels;i ++) { + + ad->samples_out[i] = ad->samples_in[i] >> 16; + } + } + + // pa_simple_write always consumes the entire buffer + + int error_code; + int byte_size = ad->buffer_size * sizeof(int16_t) * ad->channels; + if (pa_simple_write(ad->pulse, ad->samples_out, byte_size, &error_code) < 0) { + + // can't recover here + fprintf(stderr, "PulseAudio failed and can't recover: %s\n", pa_strerror(error_code)); + ad->active = false; + ad->exit_thread = true; + break; + } + } + + ad->thread_exited = true; +} + +void AudioDriverPulseAudio::start() { + + active = true; +} + +int AudioDriverPulseAudio::get_mix_rate() const { + + return mix_rate; +} + +AudioDriverSW::OutputFormat AudioDriverPulseAudio::get_output_format() const { + + return output_format; +} + +void AudioDriverPulseAudio::lock() { + + if (!thread || !mutex) + return; + mutex->lock(); +} + +void AudioDriverPulseAudio::unlock() { + + if (!thread || !mutex) + return; + mutex->unlock(); +} + +void AudioDriverPulseAudio::finish() { + + if (!thread) + return; + + exit_thread = true; + Thread::wait_to_finish(thread); + + if (pulse) + pa_simple_free(pulse); + + if (samples_in) { + memdelete_arr(samples_in); + memdelete_arr(samples_out); + }; + + memdelete(thread); + if (mutex) { + memdelete(mutex); + mutex = NULL; + } + + thread = NULL; +} + +AudioDriverPulseAudio::AudioDriverPulseAudio() { + + mutex = NULL; + thread = NULL; + pulse = NULL; +} + +AudioDriverPulseAudio::~AudioDriverPulseAudio() { + +} + +#endif diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h new file mode 100644 index 000000000..e82e0c24b --- /dev/null +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* audio_driver_pulseaudio.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "servers/audio/audio_server_sw.h" + +#ifdef PULSEAUDIO_ENABLED + +#include "core/os/thread.h" +#include "core/os/mutex.h" + +#include <pulse/simple.h> + +class AudioDriverPulseAudio : public AudioDriverSW { + + Thread* thread; + Mutex* mutex; + + pa_simple* pulse; + + int32_t* samples_in; + int16_t* samples_out; + + static void thread_func(void* p_udata); + + unsigned int mix_rate; + OutputFormat output_format; + + unsigned int buffer_size; + int channels; + + bool active; + bool thread_exited; + mutable bool exit_thread; + bool pcm_open; + +public: + + const char* get_name() const { + return "PulseAudio"; + }; + + virtual Error init(); + virtual void start(); + virtual int get_mix_rate() const; + virtual OutputFormat get_output_format() const; + virtual void lock(); + virtual void unlock(); + virtual void finish(); + + AudioDriverPulseAudio(); + ~AudioDriverPulseAudio(); +}; + +#endif diff --git a/drivers/squish/image_compress_squish.cpp b/drivers/squish/image_compress_squish.cpp index 1d71f51db..2c520bd1e 100644 --- a/drivers/squish/image_compress_squish.cpp +++ b/drivers/squish/image_compress_squish.cpp @@ -18,18 +18,19 @@ void image_compress_squish(Image *p_image) { if (p_image->get_format()>=Image::FORMAT_BC1) return; //do not compress, already compressed - - Image::AlphaMode alpha = p_image->detect_alpha(); - Image::Format target_format; int shift=0; int squish_comp=squish::kColourRangeFit; - switch(alpha) { + Image::Format target_format; - case Image::ALPHA_NONE: target_format = Image::FORMAT_BC1; shift=1; squish_comp|=squish::kDxt1; break; - case Image::ALPHA_BIT: target_format = Image::FORMAT_BC2; squish_comp|=squish::kDxt3; break; - case Image::ALPHA_BLEND: target_format = Image::FORMAT_BC3; squish_comp|=squish::kDxt5; break; - } + if (p_image->get_format()==Image::FORMAT_GRAYSCALE_ALPHA) { + //compressed normalmap + target_format = Image::FORMAT_BC3; squish_comp|=squish::kDxt5;; + } else if (p_image->detect_alpha()!=Image::ALPHA_NONE) { + target_format = Image::FORMAT_BC2; squish_comp|=squish::kDxt3;; + } else { + target_format = Image::FORMAT_BC1; shift=1; squish_comp|=squish::kDxt1;; + } p_image->convert(Image::FORMAT_RGBA); //always expects rgba diff --git a/drivers/theora/SCsub b/drivers/theora/SCsub index d3e583827..ecabce6c9 100644 --- a/drivers/theora/SCsub +++ b/drivers/theora/SCsub @@ -32,6 +32,7 @@ sources = [ "theora/video_stream_theora.cpp", ] -env.drivers_sources += sources +if env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources diff --git a/drivers/theoraplayer/SCsub b/drivers/theoraplayer/SCsub index 023b2c928..09fb13d8e 100644 --- a/drivers/theoraplayer/SCsub +++ b/drivers/theoraplayer/SCsub @@ -59,27 +59,47 @@ src/YUV/C/yuv420_grey_c.c src/YUV/C/yuv420_yuv_c.c src/YUV/C/yuv420_rgb_c.c src/TheoraVideoFrame.cpp -video_stream_theoraplayer.cpp """) +env_theora = env.Clone() + if env["platform"] == "iphone": sources.append("src/AVFoundation/TheoraVideoClip_AVFoundation.mm") env.Append(LINKFLAGS=['-framework', 'CoreVideo', '-framework', 'CoreMedia', '-framework', 'AVFoundation']) + if env["target"] == "release": + env_theora.Append(CPPFLAGS=["-D_IOS", "-D__ARM_NEON__", "-fstrict-aliasing", "-fmessage-length=210", "-fdiagnostics-show-note-include-stack", "-fmacro-backtrace-limit=0", "-fcolor-diagnostics", "-Wno-trigraphs", "-fpascal-strings", "-fvisibility=hidden", "-fvisibility-inlines-hidden"]) -env_theora = env.Clone() - -env_theora.Append(CPPFLAGS=["-D_YUV_C", "-D__THEORA", "-D_LIB"]) +env_theora.Append(CPPFLAGS=["-D_LIB", "-D__THEORA"]) # removed -D_YUV_C +env_theora.Append(CPPFLAGS=["-D_YUV_LIBYUV"]) +#env_theora.Append(CPPFLAGS=["-D_YUV_C"]) if env["platform"] == "iphone": env_theora.Append(CPPFLAGS=["-D__AVFOUNDATION"]) +else: + pass + #env_theora.Append(CPPFLAGS=["-D__FFMPEG"]) if env["platform"] == "android": env_theora.Append(CPPFLAGS=["-D_ANDROID"]) +if env["platform"] == "winrt": + env_theora.Append(CPPFLAGS=["-D_WINRT"]) + env_theora.Append(CPPPATH=["#drivers/theoraplayer/include/theoraplayer", "#drivers/theoraplayer/src/YUV", "#drivers/theoraplayer/src/YUV/libyuv/include", "#drivers/theoraplayer/src/Theora", "#drivers/theoraplayer/src/AVFoundation"]) objs = [] -env_theora.add_source_files(objs, sources) + +env_theora.add_source_files(objs, ["video_stream_theoraplayer.cpp"]) + +if env['use_theoraplayer_binary'] == "yes": + if env["platform"] == "iphone": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/ios']) + env.Append(LIBS=['theoraplayer', 'ogg', 'theora', 'tremor']) + if env["platform"] == "windows": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/windows']) + env.Append(LINKFLAGS=['libtheoraplayer_static.lib', 'libogg.lib', 'libtheora.lib', 'libvorbis.lib']) +else: + env_theora.add_source_files(objs, sources) env.drivers_sources += objs diff --git a/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h b/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h index b2987c01c..fe71cf856 100644 --- a/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h +++ b/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h @@ -87,6 +87,7 @@ protected: std::string mName; int mWidth, mHeight, mStride; int mNumFrames; + int audio_track; int mSubFrameWidth, mSubFrameHeight, mSubFrameOffsetX, mSubFrameOffsetY; float mAudioGain; //! multiplier for audio samples. between 0 and 1 @@ -233,6 +234,7 @@ public: bool getAutoRestart() { return mAutoRestart; } + void set_audio_track(int p_track) { audio_track=p_track; } /** TODO: user priority. Useful only when more than one video is being decoded diff --git a/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h b/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h index 3ff9b217c..d94c51b4d 100644 --- a/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h +++ b/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h @@ -67,8 +67,8 @@ public: //! search registered clips by name TheoraVideoClip* getVideoClipByName(std::string name); - TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0); - TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0); + TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_track=0); + TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_audio_track=0); void update(float timeDelta); diff --git a/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm b/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm index 8c3d2cc3b..1b5cf0ab1 100644 --- a/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm +++ b/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm @@ -271,7 +271,10 @@ void TheoraVideoClip_AVFoundation::load(TheoraDataSource* source) AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; NSArray* audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; - AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:0] : NULL; + if (audio_track >= audioTracks.count) + audio_track = 0; + AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:audio_track] : NULL; + printf("*********** using audio track %i\n", audio_track); #ifdef _AVFOUNDATION_BGRX bool yuv_output = (mOutputMode != TH_BGRX && mOutputMode != TH_RGBA); diff --git a/drivers/theoraplayer/src/TheoraVideoClip.cpp b/drivers/theoraplayer/src/TheoraVideoClip.cpp index 3ee4b8337..16897ee80 100644 --- a/drivers/theoraplayer/src/TheoraVideoClip.cpp +++ b/drivers/theoraplayer/src/TheoraVideoClip.cpp @@ -51,6 +51,8 @@ TheoraVideoClip::TheoraVideoClip(TheoraDataSource* data_source, mWaitingForCache(false), mOutputMode(TH_UNDEFINED) { + + audio_track=0; mAudioMutex = NULL; mThreadAccessMutex = new TheoraMutex(); mTimer = mDefaultTimer = new TheoraTimer(); @@ -75,7 +77,7 @@ TheoraVideoClip::~TheoraVideoClip() if (mAudioInterface) { mAudioMutex->lock(); // ensure a thread isn't using this mutex - memdelete(mAudioInterface); // notify audio interface it's time to call it a day + delete mAudioInterface; // notify audio interface it's time to call it a day mAudioMutex ->unlock(); delete mAudioMutex; } @@ -247,6 +249,7 @@ int TheoraVideoClip::discardOutdatedFrames(float absTime) if (nPop > 0) { +#define _DEBUG #ifdef _DEBUG std::string log = getName() + ": dropped frame "; diff --git a/drivers/theoraplayer/src/TheoraVideoManager.cpp b/drivers/theoraplayer/src/TheoraVideoManager.cpp index 87696d12a..53b211374 100644 --- a/drivers/theoraplayer/src/TheoraVideoManager.cpp +++ b/drivers/theoraplayer/src/TheoraVideoManager.cpp @@ -35,6 +35,8 @@ extern "C" void initYUVConversionModule(); } +#include "core/os/memory.h" + //#define _DECODING_BENCHMARK //uncomment to test average decoding time on a given device @@ -184,16 +186,18 @@ TheoraAudioInterfaceFactory* TheoraVideoManager::getAudioInterfaceFactory() TheoraVideoClip* TheoraVideoManager::createVideoClip(std::string filename, TheoraOutputMode output_mode, int numPrecachedOverride, - bool usePower2Stride) + bool usePower2Stride, + int p_track) { - TheoraDataSource* src=new TheoraFileDataSource(filename); - return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride); + TheoraDataSource* src=memnew(TheoraFileDataSource(filename)); + return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride, p_track); } TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_source, TheoraOutputMode output_mode, int numPrecachedOverride, - bool usePower2Stride) + bool usePower2Stride, + int p_audio_track) { mWorkMutex->lock(); @@ -226,6 +230,8 @@ TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_sour #ifdef __FFMPEG clip = new TheoraVideoClip_FFmpeg(data_source, output_mode, nPrecached, usePower2Stride); #endif + + clip->set_audio_track(p_audio_track); clip->load(data_source); clip->decodeNextFrame(); // ensure the first frame is always preloaded and have the main thread do it to prevent potential thread starvatio diff --git a/drivers/theoraplayer/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp index 12ef5de88..9f4a44ae9 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.cpp +++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp @@ -37,6 +37,11 @@ #include "include/theoraplayer/TheoraException.h" #include "core/ring_buffer.h" +#include "core/os/thread_safe.h" + +#include "core/globals.h" + +static TheoraVideoManager* mgr = NULL; class TPDataFA : public TheoraDataSource { @@ -86,12 +91,18 @@ public: return fa->get_pos(); }; - TPDataFA(String p_path) { + TPDataFA(const String& p_path) { fa = FileAccess::open(p_path, FileAccess::READ); data_name = "File: " + p_path; }; + TPDataFA(FileAccess* p_fa, const String& p_path) { + + fa = p_fa; + data_name = "File: " + p_path; + }; + ~TPDataFA() { if (fa) @@ -101,6 +112,8 @@ public: class AudioStreamInput : public AudioStreamResampled { + _THREAD_SAFE_CLASS_; + int channels; int freq; @@ -108,20 +121,35 @@ class AudioStreamInput : public AudioStreamResampled { mutable RingBuffer<float> rb; int rb_power; int total_wrote; + bool playing; + bool paused; public: virtual void play() { + + _THREAD_SAFE_METHOD_ _setup(channels, freq, 256); stream_rid=AudioServer::get_singleton()->audio_stream_create(get_audio_stream()); AudioServer::get_singleton()->stream_set_active(stream_rid,true); AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,1); + playing = true; + paused = false; }; - virtual void stop() {}; + virtual void stop() { + + _THREAD_SAFE_METHOD_ + + AudioServer::get_singleton()->stream_set_active(stream_rid,false); + //_clear_stream(); + playing=false; + _clear(); + }; + virtual bool is_playing() const { return true; }; - virtual void set_paused(bool p_paused) {}; - virtual bool is_paused(bool p_paused) const { return false; }; + virtual void set_paused(bool p_paused) { paused = p_paused; }; + virtual bool is_paused(bool p_paused) const { return paused; }; virtual void set_loop(bool p_enable) {}; virtual bool has_loop() const { return false; }; @@ -135,32 +163,39 @@ public: virtual float get_pos() const { return 0; }; virtual void seek_pos(float p_time) {}; - virtual UpdateMode get_update_mode() const { return UPDATE_IDLE; }; + virtual UpdateMode get_update_mode() const { return UPDATE_THREAD; }; virtual bool _can_mix() const { return true; }; void input(float* p_data, int p_samples) { + + _THREAD_SAFE_METHOD_; + //printf("input %i samples from %p\n", p_samples, p_data); if (rb.space_left() < p_samples) { rb_power += 1; rb.resize(rb_power); } rb.write(p_data, p_samples); + + update(); //update too here for less latency }; void update() { + _THREAD_SAFE_METHOD_; int todo = get_todo(); int16_t* buffer = get_write_buffer(); - int samples = rb.data_left(); - const int to_write = MIN(todo, samples); + int frames = rb.data_left()/channels; + const int to_write = MIN(todo, frames); - for (int i=0; i<to_write; i++) { + for (int i=0; i<to_write*channels; i++) { - uint16_t sample = uint16_t(rb.read() * 32767); + int v = rb.read() * 32767; + int16_t sample = CLAMP(v,-32768,32767); buffer[i] = sample; }; - write(to_write/channels); + write(to_write); total_wrote += to_write; }; @@ -175,12 +210,19 @@ public: AudioStreamInput(int p_channels, int p_freq) { + playing = false; + paused = true; channels = p_channels; freq = p_freq; total_wrote = 0; - rb_power = 12; + rb_power = 22; rb.resize(rb_power); }; + + ~AudioStreamInput() { + + stop(); + }; }; class TPAudioGodot : public TheoraAudioInterface, TheoraTimer { @@ -200,7 +242,7 @@ public: TPAudioGodot(TheoraVideoClip* owner, int nChannels, int p_freq) : TheoraAudioInterface(owner, nChannels, p_freq), TheoraTimer() { - printf("***************** audio interface constructor\n"); + printf("***************** audio interface constructor freq %i\n", p_freq); channels = nChannels; freq = p_freq; stream = Ref<AudioStreamInput>(memnew(AudioStreamInput(nChannels, p_freq))); @@ -209,14 +251,22 @@ public: owner->setTimer(this); }; + void stop() { + + stream->stop(); + }; + void update(float time_increase) { - mTime = (float)(stream->get_total_wrote() / channels) / freq; + float prev_time = mTime; + //mTime = (float)(stream->get_total_wrote()) / freq; + //mTime = MAX(0,mTime-AudioServer::get_singleton()->get_output_delay()); //mTime = (float)sample_count / channels / freq; - //mTime += time_increase; + mTime += time_increase; + if (mTime - prev_time > .02) printf("time increase %f secs\n", mTime - prev_time); //float duration=mClip->getDuration(); //if (mTime > duration) mTime=duration; - //printf("time at timer is %f, samples %i\n", mTime, sample_count); + //printf("time at timer is %f, %f, samples %i\n", mTime, time_increase, sample_count); } }; @@ -226,7 +276,7 @@ public: TheoraAudioInterface* createInstance(TheoraVideoClip* owner, int nChannels, int freq) { printf("************** creating audio output\n"); - TheoraAudioInterface* ta = memnew(TPAudioGodot(owner, nChannels, freq)); + TheoraAudioInterface* ta = new TPAudioGodot(owner, nChannels, freq); return ta; }; }; @@ -236,13 +286,16 @@ static TPAudioGodotFactory* audio_factory = NULL; void VideoStreamTheoraplayer::stop() { playing = false; - if (clip) + if (clip) { + clip->stop(); clip->seek(0); + }; + started = true; }; void VideoStreamTheoraplayer::play() { - - playing = true; + if (clip) + playing = true; }; bool VideoStreamTheoraplayer::is_playing() const { @@ -252,7 +305,13 @@ bool VideoStreamTheoraplayer::is_playing() const { void VideoStreamTheoraplayer::set_paused(bool p_paused) { - playing = false; + paused = p_paused; + if (paused) { + clip->pause(); + } else { + if (clip && playing && !started) + clip->play(); + } }; bool VideoStreamTheoraplayer::is_paused(bool p_paused) const { @@ -300,22 +359,37 @@ int VideoStreamTheoraplayer::get_pending_frame_count() const { if (!clip) return 0; - if (!frame.empty()) - return 1; + TheoraVideoFrame* f = clip->getNextFrame(); + return f ? 1 : 0; +}; + + +void VideoStreamTheoraplayer::pop_frame(Ref<ImageTexture> p_tex) { + + if (!clip) + return; TheoraVideoFrame* f = clip->getNextFrame(); - if (!f) - return 0; + if (!f) { + return; + }; + +#ifdef GLES2_ENABLED +// RasterizerGLES2* r = RasterizerGLES2::get_singleton(); +// r->_texture_set_data(p_tex, f->mBpp == 3 ? Image::Format_RGB : Image::Format_RGBA, f->mBpp, w, h, f->getBuffer()); + +#endif float w=clip->getWidth(),h=clip->getHeight(); - int imgsize = w * h * f->mBpp; + int imgsize = w * h * f->mBpp; int size = f->getStride() * f->getHeight() * f->mBpp; - DVector<uint8_t> data; data.resize(imgsize); - DVector<uint8_t>::Write wr = data.write(); - uint8_t* ptr = wr.ptr(); - copymem(ptr, f->getBuffer(), imgsize); + { + DVector<uint8_t>::Write wr = data.write(); + uint8_t* ptr = wr.ptr(); + memcpy(ptr, f->getBuffer(), imgsize); + } /* for (int i=0; i<h; i++) { int dstofs = i * w * f->mBpp; @@ -323,24 +397,32 @@ int VideoStreamTheoraplayer::get_pending_frame_count() const { copymem(ptr + dstofs, f->getBuffer() + dstofs, w * f->mBpp); }; */ - frame = Image(); + Image frame = Image(); frame.create(w, h, 0, f->mBpp == 3 ? Image::FORMAT_RGB : Image::FORMAT_RGBA, data); clip->popFrame(); - return 1; + if (p_tex->get_width() == 0) { + p_tex->create(frame.get_width(),frame.get_height(),frame.get_format(),Texture::FLAG_VIDEO_SURFACE|Texture::FLAG_FILTER); + p_tex->set_data(frame); + } else { + + p_tex->set_data(frame); + }; }; +/* Image VideoStreamTheoraplayer::pop_frame() { Image ret = frame; frame = Image(); return ret; }; +*/ Image VideoStreamTheoraplayer::peek_frame() const { - return frame; + return Image(); }; void VideoStreamTheoraplayer::update(float p_time) { @@ -348,6 +430,12 @@ void VideoStreamTheoraplayer::update(float p_time) { if (!mgr) return; + if (!clip) + return; + + if (!playing || paused) + return; + //printf("video update!\n"); if (started) { if (clip->getNumReadyFrames() < 2) { @@ -364,26 +452,44 @@ void VideoStreamTheoraplayer::update(float p_time) { mgr->update(p_time); }; + +void VideoStreamTheoraplayer::set_audio_track(int p_idx) { + audio_track=p_idx; + if (clip) + clip->set_audio_track(audio_track); +} + void VideoStreamTheoraplayer::set_file(const String& p_file) { + FileAccess* f = FileAccess::open(p_file, FileAccess::READ); + if (!f || !f->is_open()) + return; + if (!audio_factory) { audio_factory = memnew(TPAudioGodotFactory); }; - mgr = memnew(TheoraVideoManager); - mgr->setAudioInterfaceFactory(audio_factory); + if (mgr == NULL) { + mgr = memnew(TheoraVideoManager); + mgr->setAudioInterfaceFactory(audio_factory); + }; + + int track = GLOBAL_DEF("theora/audio_track", 0); // hack if (p_file.find(".mp4") != -1) { std::string file = p_file.replace("res://", "").utf8().get_data(); - clip = mgr->createVideoClip(file); + clip = mgr->createVideoClip(file, TH_RGBX, 2, false, track); + //clip->set_audio_track(audio_track); + memdelete(f); } else { - TheoraDataSource* ds = memnew(TPDataFA(p_file)); + TheoraDataSource* ds = memnew(TPDataFA(f, p_file)); try { clip = mgr->createVideoClip(ds); + clip->set_audio_track(audio_track); } catch (_TheoraGenericException e) { printf("exception ocurred! %s\n", e.repr().c_str()); clip = NULL; @@ -396,19 +502,26 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) { VideoStreamTheoraplayer::~VideoStreamTheoraplayer() { - if (mgr) { - memdelete(mgr); + stop(); + //if (mgr) { // this should be a singleton or static or something + // memdelete(mgr); + //}; + //mgr = NULL; + if (clip) { + mgr->destroyVideoClip(clip); + clip = NULL; }; - mgr = NULL; }; VideoStreamTheoraplayer::VideoStreamTheoraplayer() { - mgr = NULL; + //mgr = NULL; clip = NULL; started = false; playing = false; + paused = false; loop = false; + audio_track=0; }; diff --git a/drivers/theoraplayer/video_stream_theoraplayer.h b/drivers/theoraplayer/video_stream_theoraplayer.h index 063bf3895..d43c12609 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.h +++ b/drivers/theoraplayer/video_stream_theoraplayer.h @@ -3,6 +3,7 @@ #include "scene/resources/video_stream.h" #include "io/resource_loader.h" +#include "scene/resources/texture.h" class TheoraVideoManager; class TheoraVideoClip; @@ -11,12 +12,14 @@ class VideoStreamTheoraplayer : public VideoStream { OBJ_TYPE(VideoStreamTheoraplayer,VideoStream); - mutable Image frame; - TheoraVideoManager* mgr; + mutable DVector<uint8_t> data; TheoraVideoClip* clip; bool started; bool playing; bool loop; + bool paused; + + int audio_track; public: @@ -37,12 +40,13 @@ public: virtual float get_length() const; virtual int get_pending_frame_count() const; - virtual Image pop_frame(); + virtual void pop_frame(Ref<ImageTexture> p_tex); virtual Image peek_frame() const; void update(float p_time); void set_file(const String& p_file); + void set_audio_track(int p_idx); ~VideoStreamTheoraplayer(); VideoStreamTheoraplayer(); diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index c22174345..841160f94 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "ip_unix.h" -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) && !defined(WINRT_ENABLED) #ifdef WINDOWS_ENABLED diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp index fa1266b2d..4711f4f09 100644 --- a/drivers/unix/memory_pool_static_malloc.cpp +++ b/drivers/unix/memory_pool_static_malloc.cpp @@ -40,10 +40,9 @@ * so BE CAREFUL! */ - void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) { - #if DFAULT_ALIGNMENT == 1 + #if DEFAULT_ALIGNMENT == 1 return _alloc(p_bytes, p_description); @@ -123,7 +122,7 @@ void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) { void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) { - #if DFAULT_ALIGNMENT == 1 + #if DEFAULT_ALIGNMENT == 1 return _realloc(p_memory,p_bytes); #else @@ -172,7 +171,6 @@ void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) { bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr); bool is_list = ( ringlist == ringptr ); - RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr)); ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed @@ -213,7 +211,7 @@ void MemoryPoolStaticMalloc::free(void *p_ptr) { ERR_FAIL_COND( !MemoryPoolStatic::get_singleton()); - #if DFAULT_ALIGNMENT == 1 + #if DEFAULT_ALIGNMENT == 1 _free(p_ptr); #else diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index ef4cf644f..2de975e5d 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -42,6 +42,7 @@ #include "dir_access_unix.h" #include "tcp_server_posix.h" #include "stream_peer_tcp_posix.h" +#include "packet_peer_udp_posix.h" #include <stdarg.h> @@ -115,6 +116,7 @@ void OS_Unix::initialize_core() { #ifndef NO_NETWORK TCPServerPosix::make_default(); StreamPeerTCPPosix::make_default(); + PacketPeerUDPPosix::make_default(); IP_Unix::make_default(); #endif mempool_static = new MemoryPoolStaticMalloc; @@ -330,6 +332,12 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo Error OS_Unix::kill(const ProcessID& p_pid) { int ret = ::kill(p_pid,SIGKILL); + if (!ret) { + //avoid zombie process + int st; + ::waitpid(p_pid,&st,0); + + } return ret?ERR_INVALID_PARAMETER:OK; } diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp new file mode 100644 index 000000000..26a0b2922 --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -0,0 +1,194 @@ +#include "packet_peer_udp_posix.h" + +#ifdef UNIX_ENABLED + + +#include <errno.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <stdio.h> + +#ifndef NO_FCNTL +#include <sys/fcntl.h> +#else +#include <sys/ioctl.h> +#endif + +#ifdef JAVASCRIPT_ENABLED +#include <arpa/inet.h> +#endif + + +int PacketPeerUDPPosix::get_available_packet_count() const { + + Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false); + if (err!=OK) + return 0; + + return queue_count; +} + +Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{ + + Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false); + if (err!=OK) + return err; + if (queue_count==0) + return ERR_UNAVAILABLE; + + uint32_t size; + rb.read((uint8_t*)&packet_ip.host,4,true); + rb.read((uint8_t*)&packet_port,4,true); + rb.read((uint8_t*)&size,4,true); + rb.read(packet_buffer,size,true); + --queue_count; + *r_buffer=packet_buffer; + r_buffer_size=size; + return OK; + +} +Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ + + int sock = _get_socket(); + ERR_FAIL_COND_V( sock == -1, FAILED ); + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(peer_port); + addr.sin_addr = *((struct in_addr*)&peer_addr.host); + + errno = 0; + int err; + + while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + + if (errno != EAGAIN) { + return FAILED; + } + } + + return OK; +} + +int PacketPeerUDPPosix::get_max_packet_size() const{ + + return 512; // uhm maybe not +} + +Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){ + + close(); + int sock = _get_socket(); + if (sock == -1 ) + return ERR_CANT_CREATE; + sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(p_port); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + close(); + return ERR_UNAVAILABLE; + } + printf("UDP Connection listening on port %i bufsize %i \n", p_port,p_recv_buffer_size); + rb.resize(nearest_shift(p_recv_buffer_size)); + return OK; +} + +void PacketPeerUDPPosix::close(){ + + if (sockfd != -1) + ::close(sockfd); + sockfd=-1; + rb.resize(8); + queue_count=0; +} + + +Error PacketPeerUDPPosix::wait() { + + return _poll(true); +} + +Error PacketPeerUDPPosix::_poll(bool p_wait) { + + struct sockaddr_in from = {0}; + socklen_t len = sizeof(struct sockaddr_in); + int ret; + while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { + rb.write((uint8_t*)&from.sin_addr, 4); + uint32_t port = ntohs(from.sin_port); + rb.write((uint8_t*)&port, 4); + rb.write((uint8_t*)&ret, 4); + rb.write(recv_buffer, ret); + len = sizeof(struct sockaddr_in); + ++queue_count; + }; + + if (ret == 0 || (ret == -1 && errno != EAGAIN) ) { + close(); + return FAILED; + }; + + return OK; +} +bool PacketPeerUDPPosix::is_listening() const{ + + return sockfd!=-1; +} + +IP_Address PacketPeerUDPPosix::get_packet_address() const { + + return packet_ip; +} + +int PacketPeerUDPPosix::get_packet_port() const{ + + return packet_port; +} + +int PacketPeerUDPPosix::_get_socket() { + + if (sockfd != -1) + return sockfd; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + ERR_FAIL_COND_V( sockfd == -1, -1 ); + //fcntl(sockfd, F_SETFL, O_NONBLOCK); + + return sockfd; +} + + +void PacketPeerUDPPosix::set_send_address(const IP_Address& p_address,int p_port) { + + peer_addr=p_address; + peer_port=p_port; +} + +PacketPeerUDP* PacketPeerUDPPosix::_create() { + + return memnew(PacketPeerUDPPosix); +}; + +void PacketPeerUDPPosix::make_default() { + + PacketPeerUDP::_create = PacketPeerUDPPosix::_create; +}; + + +PacketPeerUDPPosix::PacketPeerUDPPosix() { + + sockfd=-1; + packet_port=0; + queue_count=0; + peer_port=0; +} + +PacketPeerUDPPosix::~PacketPeerUDPPosix() { + + close(); +} +#endif diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h new file mode 100644 index 000000000..b14568eb5 --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.h @@ -0,0 +1,57 @@ +#ifndef PACKET_PEER_UDP_POSIX_H +#define PACKET_PEER_UDP_POSIX_H + +#ifdef UNIX_ENABLED + +#include "io/packet_peer_udp.h" +#include "ring_buffer.h" + +class PacketPeerUDPPosix : public PacketPeerUDP { + + + enum { + PACKET_BUFFER_SIZE=65536 + }; + + mutable RingBuffer<uint8_t> rb; + uint8_t recv_buffer[PACKET_BUFFER_SIZE]; + mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; + IP_Address packet_ip; + int packet_port; + mutable int queue_count; + int sockfd; + + IP_Address peer_addr; + int peer_port; + + _FORCE_INLINE_ int _get_socket(); + + static PacketPeerUDP* _create(); + virtual Error _poll(bool p_block); + +public: + + virtual int get_available_packet_count() const; + virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const; + virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size); + + virtual int get_max_packet_size() const; + + virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual void close(); + virtual Error wait(); + virtual bool is_listening() const; + + virtual IP_Address get_packet_address() const; + virtual int get_packet_port() const; + + virtual void set_send_address(const IP_Address& p_address,int p_port); + + static void make_default(); + + PacketPeerUDPPosix(); + ~PacketPeerUDPPosix(); +}; + +#endif // PACKET_PEER_UDP_POSIX_H +#endif diff --git a/drivers/vorbis/SCsub b/drivers/vorbis/SCsub index 1c7cccc42..2c137629a 100644 --- a/drivers/vorbis/SCsub +++ b/drivers/vorbis/SCsub @@ -3,6 +3,9 @@ Import('env') sources = [ "vorbis/audio_stream_ogg_vorbis.cpp", +] + +sources_lib = [ "vorbis/analysis.c", #"vorbis/barkmel.c", "vorbis/bitrate.c", @@ -32,3 +35,6 @@ sources = [ env.drivers_sources += sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources_lib + diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index d9b7b1d16..996f75d16 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -215,7 +215,7 @@ AudioStreamOGGVorbis::UpdateMode AudioStreamOGGVorbis::get_update_mode() const { bool AudioStreamOGGVorbis::is_playing() const { - return playing; + return playing || (get_total() - get_todo() -1 > 0); } float AudioStreamOGGVorbis::get_pos() const { diff --git a/drivers/vorbis/os.h b/drivers/vorbis/os.h index 276b4decc..3df1d194e 100644 --- a/drivers/vorbis/os.h +++ b/drivers/vorbis/os.h @@ -120,7 +120,7 @@ static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise, /* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the * 64 bit compiler */ -#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) +#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) && !defined(WINDOWSPHONE_ENABLED) # define VORBIS_FPU_CONTROL typedef ogg_int16_t vorbis_fpu_control; diff --git a/drivers/webp/dsp/dsp.h b/drivers/webp/dsp/dsp.h index 9ff53174d..afe30413c 100644 --- a/drivers/webp/dsp/dsp.h +++ b/drivers/webp/dsp/dsp.h @@ -33,7 +33,7 @@ extern "C" { #define WEBP_ANDROID_NEON // Android targets that might support NEON #endif -#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED) +#if ( (defined(__ARM_NEON__) && !defined(__aarch64__)) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED) #define WEBP_USE_NEON #endif diff --git a/drivers/webp/utils/bit_reader.h b/drivers/webp/utils/bit_reader.h index d80b49714..43cd948fd 100644 --- a/drivers/webp/utils/bit_reader.h +++ b/drivers/webp/utils/bit_reader.h @@ -1,3 +1,4 @@ +// // Copyright 2010 Google Inc. All Rights Reserved. // // This code is licensed under the same terms as WebM: diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index aefec59ce..d1e976610 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -106,6 +106,7 @@ String DirAccessWindows::get_next() { return name; } else { +#ifndef WINRT_ENABLED _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); String name=p->f.cFileName; @@ -117,7 +118,8 @@ String DirAccessWindows::get_next() { } return name; - +#endif + return ""; } } @@ -189,10 +191,10 @@ Error DirAccessWindows::change_dir(String p_dir) { current_dir=real_current_dir_name; // TODO, utf8 parser current_dir=current_dir.replace("\\","/"); - } else { + } //else { SetCurrentDirectoryW(prev_dir.c_str()); - } + //} return worked?OK:ERR_INVALID_PARAMETER; } else { @@ -210,10 +212,10 @@ Error DirAccessWindows::change_dir(String p_dir) { current_dir=real_current_dir_name; // TODO, utf8 parser current_dir=current_dir.replace("\\","/"); - } else { + }// else { SetCurrentDirectoryA(prev_dir.ascii().get_data()); - } + //} return worked?OK:ERR_INVALID_PARAMETER; @@ -352,22 +354,23 @@ bool DirAccessWindows::dir_exists(String p_dir) { DWORD fileAttr; fileAttr = GetFileAttributesExW(p_dir.c_str(), GetFileExInfoStandard, &fileInfo); - if (0xFFFFFFFF == fileAttr) + if (0 == fileAttr) return false; return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); } else { +#ifndef WINRT_ENABLED DWORD fileAttr; fileAttr = GetFileAttributesExA(p_dir.ascii().get_data(), GetFileExInfoStandard, &fileInfo); - if (0xFFFFFFFF == fileAttr) + if (0 == fileAttr) return false; return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); +#endif } - return false; } diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 3cd065841..a6073cbb2 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -54,7 +54,6 @@ void FileAccessWindows::check_errors() const { Error FileAccessWindows::_open(const String& p_filename, int p_mode_flags) { String filename=fix_path(p_filename); - if (f) close(); |
