diff options
Diffstat (limited to 'drivers')
75 files changed, 5099 insertions, 7504 deletions
diff --git a/drivers/SCsub b/drivers/SCsub index bfd35344ea..a1a2191cbc 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -7,9 +7,9 @@ Export('env') SConscript('unix/SCsub');
SConscript('alsa/SCsub');
+SConscript('pulseaudio/SCsub');
SConscript('windows/SCsub');
SConscript('gles2/SCsub');
-SConscript('gles1/SCsub');
SConscript('gl_context/SCsub');
SConscript('openssl/SCsub');
diff --git a/drivers/builtin_openssl2/openssl/md5.h b/drivers/builtin_openssl2/openssl/md5.h index 8f392f0ec6..765be94335 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 c5f0830ae6..8b9871463f 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/etc1/SCsub b/drivers/etc1/SCsub index 152dc3f4d0..251c3ffb86 100644 --- a/drivers/etc1/SCsub +++ b/drivers/etc1/SCsub @@ -6,7 +6,8 @@ etc_sources = [ "etc1/rg_etc1.cpp" ] -env.drivers_sources+=etc_sources +if (env["etc1"] != "no"): + env.drivers_sources+=etc_sources #env.add_source_files(env.drivers_sources, etc_sources) diff --git a/drivers/etc1/rg_etc1.cpp b/drivers/etc1/rg_etc1.cpp index cad9af8830..fd109f003c 100644 --- a/drivers/etc1/rg_etc1.cpp +++ b/drivers/etc1/rg_etc1.cpp @@ -24,6 +24,9 @@ namespace rg_etc1
{
+ inline long labs(long val) {
+ return val < 0 ? -val : val;
+ }
inline int intabs(int val) {
@@ -1913,7 +1916,7 @@ done: for (uint packed_c = 0; packed_c < limit; packed_c++)
{
int v = etc1_decode_value(diff, inten, selector, packed_c);
- uint err = intabs(v - color);
+ uint err = labs(v - static_cast<int>(color));
//printf("err: %d - %u = %u\n",v,color,err);
if (err < best_error)
{
@@ -2367,7 +2370,7 @@ found_perfect_match: int dr = best_results[1].m_block_color_unscaled.r - best_results[0].m_block_color_unscaled.r;
int dg = best_results[1].m_block_color_unscaled.g - best_results[0].m_block_color_unscaled.g;
int db = best_results[1].m_block_color_unscaled.b - best_results[0].m_block_color_unscaled.b;
- RG_ETC1_ASSERT(best_use_color4 || (rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax));
+ RG_ETC1_ASSERT(best_use_color4 || ((rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax)));
if (best_use_color4)
{
diff --git a/drivers/gl_context/context_gl.cpp b/drivers/gl_context/context_gl.cpp index 77a94f9333..82195cc6f6 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 4c3d863e87..392f8341ae 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 02de063bda..0000000000 --- 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 cca953eed0..0000000000 --- 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 d596aad4b9..4f486897d1 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -91,6 +91,10 @@ static RasterizerGLES2* _singleton = NULL; +#ifdef GLES_NO_CLIENT_ARRAYS +static float GlobalVertexBuffer[MAX_POLYGON_VERTICES * 8] = {0}; +#endif + static const GLenum prim_type[]={GL_POINTS,GL_LINES,GL_TRIANGLES,GL_TRIANGLE_FAN}; _FORCE_INLINE_ static void _set_color_attrib(const Color& p_color) { @@ -139,11 +143,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 { @@ -360,17 +366,19 @@ 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) { case Image::FORMAT_GRAYSCALE: { r_gl_components=1; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_NV:GL_LUMINANCE; + 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: { @@ -378,14 +386,16 @@ 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=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + 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: { //image.convert(Image::FORMAT_RGBA); r_gl_components=2; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_ALPHA_NV:GL_LUMINANCE_ALPHA; + 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; @@ -394,7 +404,8 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.convert(Image::FORMAT_RGB); r_gl_components=3; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB; + 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; @@ -407,14 +418,15 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; @@ -426,14 +438,15 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_EXT; - } else { + 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_format=GL_RGB; + r_gl_internal_format=GL_RGB; } } break; case Image::FORMAT_RGBA: { @@ -442,14 +455,16 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { + 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; @@ -465,21 +480,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_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_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; }; @@ -495,20 +511,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_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_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; @@ -526,20 +543,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_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_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; }; @@ -556,20 +574,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT; + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT; r_gl_components=1; //doesn't matter much r_compressed=true; }; @@ -586,19 +605,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; r_gl_components=1; //doesn't matter much r_compressed=true; }; @@ -614,21 +634,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_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_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; @@ -645,22 +666,23 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_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_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; @@ -677,19 +699,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_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_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; } @@ -705,19 +728,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { 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_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_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_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; } @@ -734,21 +758,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_EXT; - } else { 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_format=GL_RGB; + r_gl_internal_format=GL_RGB; } - r_gl_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; } @@ -762,12 +787,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; } @@ -781,12 +806,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; } @@ -800,12 +825,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; } @@ -816,7 +841,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; @@ -827,6 +852,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; } @@ -858,6 +887,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); @@ -876,7 +906,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); @@ -894,6 +924,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 @@ -908,7 +939,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; @@ -926,6 +957,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; @@ -933,7 +965,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()) { @@ -943,7 +975,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; } @@ -961,8 +993,14 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu 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 - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + else { + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + } else { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + + } + } if (texture->flags&VS::TEXTURE_FLAG_FILTER) { @@ -999,32 +1037,33 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu 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 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); + int mm_w,mm_h; + img.get_mipmap_offset_size_and_dimensions(i,ofs,size,mm_w,mm_h); if (texture->compressed) { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] ); + glCompressedTexImage2D( blit_target, i, format,mm_w,mm_h,0,size,&read[ofs] ); } else { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) { - glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] ); + glTexSubImage2D( blit_target, i, 0,0,mm_w, mm_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, mm_w, mm_h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); } } tsize+=size; - w = MAX(1,w>>1); - h = MAX(1,h>>1); + //w = MAX(Image::,w>>1); + //h = MAX(1,h>>1); } @@ -1255,8 +1294,14 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { 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 - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + else{ + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + } else { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + + } + } if (texture->flags&VS::TEXTURE_FLAG_FILTER) { @@ -1383,6 +1428,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; @@ -1394,6 +1442,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); @@ -1513,6 +1564,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 */ @@ -1555,6 +1648,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 { @@ -1562,6 +1656,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 } @@ -1593,7 +1688,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(); @@ -2447,7 +2542,7 @@ Error RasterizerGLES2::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem,ui void RasterizerGLES2::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(); + ERR_FAIL(); } Array RasterizerGLES2::mesh_get_surface_arrays(RID p_mesh,int p_surface) const { @@ -3960,8 +4055,16 @@ void RasterizerGLES2::render_target_set_size(RID p_render_target,int p_width,int glGenTextures(1, &rt->color); glBindTexture(GL_TEXTURE_2D, rt->color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 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); + + if (rt->texture_ptr->flags&VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); @@ -4030,6 +4133,10 @@ void RasterizerGLES2::begin_frame() { shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter"))); #endif + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF5,shadow_filter==SHADOW_FILTER_PCF5); + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF13,shadow_filter==SHADOW_FILTER_PCF13); + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM); + window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height ); double time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec @@ -4147,6 +4254,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); @@ -4156,10 +4266,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 @@ -4169,7 +4293,7 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { void RasterizerGLES2::clear_viewport(const Color& p_color) { - if (current_rt) { + if (current_rt || using_canvas_bg) { glScissor( 0, 0, viewport.width, viewport.height ); } else { @@ -4177,7 +4301,7 @@ void RasterizerGLES2::clear_viewport(const Color& p_color) { } glEnable(GL_SCISSOR_TEST); - glClearColor(p_color.r,p_color.g,p_color.b,1.0); + 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); }; @@ -4362,6 +4486,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); @@ -4371,9 +4502,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 + } } @@ -4386,6 +4524,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 @@ -4446,7 +4589,42 @@ 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"); + } + if (light_flags.uses_shadow_color) { + enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n"); + } + + if (vertex_flags.uses_worldvec) { + enablers.push_back("#define USE_WORLD_VEC\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); } @@ -4457,7 +4635,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++; } @@ -4604,7 +4784,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) { @@ -4807,31 +4988,58 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ Material::UniformData ud; - bool keep=true; + bool keep=true; //keep material value + + Map<StringName,Material::UniformData>::Element *OLD=old_mparams.find(E->key()); + bool has_old = OLD; + bool old_inuse=has_old && old_mparams[E->key()].inuse; + + ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); - 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()) { + } + else if (OLD->get().value.get_type()!=E->value().default_value.get_type()) { + + if (OLD->get().value.get_type()==Variant::INT && E->get().type==ShaderLanguage::TYPE_FLOAT) { + //handle common mistake using shaders (feeding ints instead of float) + OLD->get().value=float(OLD->get().value); + keep=true; + } else if (!ud.istexture && E->value().default_value.get_type()!=Variant::NIL) { - if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { + keep=false; + } + //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; + keep=false;*/ + + //value is invalid because type differs and default is not null + ; } + 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; } @@ -4935,8 +5143,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material int texcoord=0; for (Map<StringName,Material::UniformData>::Element *E=p_material->shader_params.front();E;E=E->next()) { + if (E->get().index<0) continue; +// print_line(String(E->key())+": "+E->get().value); if (E->get().istexture) { //clearly a texture.. RID rid = E->get().value; @@ -4946,12 +5156,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) { @@ -4975,8 +5187,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); @@ -5108,7 +5322,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); @@ -5119,7 +5333,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])); @@ -5312,13 +5526,15 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia base = surf->array_local; glBindBuffer(GL_ARRAY_BUFFER, 0); bool can_copy_to_local=surf->local_stride * surf->array_len <= skinned_buffer_size; + if (p_morphs && surf->stride * surf->array_len > skinned_buffer_size) + can_copy_to_local=false; + + if (!can_copy_to_local) skeleton_valid=false; - /* compute morphs */ - if (p_morphs && surf->morph_target_count && can_copy_to_local) { @@ -5739,9 +5955,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) { @@ -6042,7 +6259,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); } @@ -6091,7 +6308,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); @@ -6110,6 +6327,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) { @@ -6204,7 +6422,12 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans case VS::MATERIAL_BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } break; case VS::MATERIAL_BLEND_MODE_ADD: { @@ -6215,12 +6438,17 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans } break; case VS::MATERIAL_BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_SUBTRACT); + glBlendEquation(GL_FUNC_REVERSE_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); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } break; @@ -6231,6 +6459,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) { @@ -6241,9 +6485,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) { @@ -6266,7 +6517,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 } @@ -6342,7 +6593,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); @@ -6351,11 +6610,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); @@ -6364,7 +6628,7 @@ 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) { @@ -6451,7 +6715,12 @@ void RasterizerGLES2::_copy_to_texscreen() { #endif glDisable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glBindBuffer(GL_ARRAY_BUFFER,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); @@ -6683,7 +6952,7 @@ void RasterizerGLES2::_draw_tex_bg() { RID texture; - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { texture=current_env->bg_param[VS::ENV_BG_PARAM_TEXTURE]; } else { texture=current_env->bg_param[VS::ENV_BG_PARAM_CUBEMAP]; @@ -6700,25 +6969,20 @@ void RasterizerGLES2::_draw_tex_bg() { copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY,true); - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,false); } else { copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,true); } - if (current_env->bg_mode==VS::ENV_BG_CUBEMAP_RGBE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { - copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,true); - } else { - copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false); - } copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true); copy_shader.bind(); - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0); } else { glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE_CUBE),0); @@ -6745,7 +7009,7 @@ void RasterizerGLES2::_draw_tex_bg() { Vector3( 0, 0, 0) }; - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { //regular texture //adjust aspect @@ -6815,7 +7079,7 @@ void RasterizerGLES2::end_scene() { if (framebuffer.active) { //detect when to use the framebuffer object - if (texscreen_used || framebuffer.scale!=1) { + if (using_canvas_bg || texscreen_used || framebuffer.scale!=1) { use_fb=true; } else if (current_env) { use_fb=false; @@ -6867,6 +7131,7 @@ void RasterizerGLES2::end_scene() { switch(current_env->bg_mode) { + case VS::ENV_BG_CANVAS: case VS::ENV_BG_KEEP: { //copy from framebuffer if framebuffer glClear(GL_DEPTH_BUFFER_BIT); @@ -6879,7 +7144,7 @@ void RasterizerGLES2::end_scene() { bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR]; else bgcolor = Globals::get_singleton()->get("render/default_clear_color"); - bgcolor = _convert_color(bgcolor); + bgcolor = _convert_color(bgcolor); float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0; glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a); _glClearDepth(1.0); @@ -6887,9 +7152,7 @@ void RasterizerGLES2::end_scene() { } break; case VS::ENV_BG_TEXTURE: - case VS::ENV_BG_CUBEMAP: - case VS::ENV_BG_TEXTURE_RGBE: - case VS::ENV_BG_CUBEMAP_RGBE: { + case VS::ENV_BG_CUBEMAP: { glClear(GL_DEPTH_BUFFER_BIT); @@ -6925,7 +7188,12 @@ void RasterizerGLES2::end_scene() { current_depth_mask=true; texscreen_copied=false; glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } glDisable(GL_BLEND); current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; @@ -6942,7 +7210,12 @@ void RasterizerGLES2::end_scene() { } glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } glDisable(GL_BLEND); current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,false); @@ -7098,7 +7371,12 @@ void RasterizerGLES2::end_scene() { _debug_shadows(); } // _debug_luminances(); +// _debug_samplers(); + if (using_canvas_bg) { + using_canvas_bg=false; + glColorMask(1,1,1,1); //don't touch alpha + } } void RasterizerGLES2::end_shadow_map() { @@ -7498,6 +7776,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(); @@ -7535,8 +7845,26 @@ void RasterizerGLES2::flush_frame() { /* CANVAS API */ +void RasterizerGLES2::begin_canvas_bg() { + + if (framebuffer.active) { + using_canvas_bg=true; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); + glViewport( 0,0,viewport.width , viewport.height ); + } else { + using_canvas_bg=false; + } + +} + void RasterizerGLES2::canvas_begin() { + + if (using_canvas_bg) { + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); + glColorMask(1,1,1,0); //don't touch alpha + } + glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); @@ -7546,7 +7874,12 @@ void RasterizerGLES2::canvas_begin() { #endif glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glLineWidth(1.0); glBindBuffer(GL_ARRAY_BUFFER,0); @@ -7560,10 +7893,13 @@ void RasterizerGLES2::canvas_begin() { canvas_tex=RID(); //material_shader.unbind(); canvas_shader.unbind(); + canvas_shader.set_custom_shader(0); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false); canvas_shader.bind(); canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0); + canvas_use_modulate=false; _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) @@ -7576,7 +7912,10 @@ 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_material=NULL; } @@ -7598,7 +7937,12 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { case VS::MATERIAL_BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } break; case VS::MATERIAL_BLEND_MODE_ADD: { @@ -7609,7 +7953,7 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { } break; case VS::MATERIAL_BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_SUBTRACT); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_SRC_ALPHA,GL_ONE); } break; case VS::MATERIAL_BLEND_MODE_MUL: { @@ -7659,7 +8003,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; @@ -7667,14 +8011,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; } @@ -7683,6 +8029,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; @@ -7831,7 +8180,7 @@ void RasterizerGLES2::_draw_gui_primitive2(int p_points, const Vector2 *p_vertic _rinfo.ci_draw_commands++; } -void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip, bool p_v_flip ) { +void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip, bool p_v_flip, bool p_transpose ) { Vector2 texcoords[4]= { Vector2( p_src_region.pos.x/p_tex_size.width, @@ -7847,6 +8196,9 @@ void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_sr (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height) }; + if (p_transpose) { + SWAP( texcoords[1], texcoords[3] ); + } if (p_h_flip) { SWAP( texcoords[0], texcoords[1] ); SWAP( texcoords[2], texcoords[3] ); @@ -7894,11 +8246,11 @@ void RasterizerGLES2::canvas_draw_rect(const Rect2& p_rect, int p_flags, const R 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); + _draw_textured_quad(p_rect,region,region.size,p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V,p_flags&CANVAS_RECT_TRANSPOSE); } 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 ); + _draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V,p_flags&CANVAS_RECT_TRANSPOSE); } } else { @@ -7993,20 +8345,22 @@ void RasterizerGLES2::canvas_draw_primitive(const Vector<Point2>& p_points, cons void RasterizerGLES2::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; + bool do_colors=false; + Color m; + if (p_singlecolor) { + m = *p_colors; + m.a*=canvas_opacity; + _set_color_attrib(m); + } else if (!p_colors) { + m = Color(1, 1, 1, canvas_opacity); + _set_color_attrib(m); + } else + do_colors=true; - if (p_singlecolor) { - Color m = *p_colors; - m.a*=canvas_opacity; - _set_color_attrib(m); - } else if (!p_colors) { - _set_color_attrib( Color(1,1,1,canvas_opacity)); - } else - do_colors=true; + Texture *texture = _bind_canvas_texture(p_texture); - Texture *texture = _bind_canvas_texture(p_texture); - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); +#ifndef GLES_NO_CLIENT_ARRAYS + glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(Vector2), p_vertices ); if (do_colors) { @@ -8025,12 +8379,89 @@ 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 } else { glDrawArrays(GL_TRIANGLES,0,p_vertex_count); } + +#else //WebGL specific impl. + glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer); + float *b = GlobalVertexBuffer; + int ofs = 0; + if(p_vertex_count > MAX_POLYGON_VERTICES){ + print_line("Too many vertices to render"); + return; + } + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_vertices[i].x; + b[ofs++]=p_vertices[i].y; + } + + if (p_colors && do_colors) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer( VS::ARRAY_COLOR, 4 ,GL_FLOAT, false, sizeof(float)*4, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_colors[i].r; + b[ofs++]=p_colors[i].g; + b[ofs++]=p_colors[i].b; + b[ofs++]=p_colors[i].a; + } + + } else { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + } + + + if (p_uvs) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer( VS::ARRAY_TEX_UV, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_uvs[i].x; + b[ofs++]=p_uvs[i].y; + } + + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glBufferSubData(GL_ARRAY_BUFFER,0,ofs*4,&b[0]); + + //bind the indices buffer. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); + + 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]; + //OS::get_singleton()->print("ind: %d ", p_indices[i]); + }; + + //copy the data to GPU. + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, p_vertex_count * sizeof(uint16_t), &_draw_poly_indices[0]); + + //draw the triangles. + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#endif + _rinfo.ci_draw_commands++; }; @@ -8043,6 +8474,1091 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) { //canvas_transform = Variant(p_transform); } +RID RasterizerGLES2::canvas_light_occluder_create() { + + CanvasOccluder *co = memnew( CanvasOccluder ); + co->index_id=0; + co->vertex_id=0; + co->len=0; + + return canvas_occluder_owner.make_rid(co); +} + +void RasterizerGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) { + + CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!co); + + co->lines=p_lines; + + if (p_lines.size()!=co->len) { + + if (co->index_id) + glDeleteBuffers(1,&co->index_id); + if (co->vertex_id) + glDeleteBuffers(1,&co->vertex_id); + + co->index_id=0; + co->vertex_id=0; + co->len=0; + + } + + if (p_lines.size()) { + + + + DVector<float> geometry; + DVector<uint16_t> indices; + int lc = p_lines.size(); + + geometry.resize(lc*6); + indices.resize(lc*3); + + DVector<float>::Write vw=geometry.write(); + DVector<uint16_t>::Write iw=indices.write(); + + + DVector<Vector2>::Read lr=p_lines.read(); + + const int POLY_HEIGHT = 16384; + + for(int i=0;i<lc/2;i++) { + + vw[i*12+0]=lr[i*2+0].x; + vw[i*12+1]=lr[i*2+0].y; + vw[i*12+2]=POLY_HEIGHT; + + vw[i*12+3]=lr[i*2+1].x; + vw[i*12+4]=lr[i*2+1].y; + vw[i*12+5]=POLY_HEIGHT; + + vw[i*12+6]=lr[i*2+1].x; + vw[i*12+7]=lr[i*2+1].y; + vw[i*12+8]=-POLY_HEIGHT; + + vw[i*12+9]=lr[i*2+0].x; + vw[i*12+10]=lr[i*2+0].y; + vw[i*12+11]=-POLY_HEIGHT; + + iw[i*6+0]=i*4+0; + iw[i*6+1]=i*4+1; + iw[i*6+2]=i*4+2; + + iw[i*6+3]=i*4+2; + iw[i*6+4]=i*4+3; + iw[i*6+5]=i*4+0; + + } + + //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush + + + if (!co->vertex_id) { + glGenBuffers(1,&co->vertex_id); + glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id); + glBufferData(GL_ARRAY_BUFFER,lc*6*sizeof(real_t),vw.ptr(),GL_STATIC_DRAW); + } else { + + glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id); + glBufferSubData(GL_ARRAY_BUFFER,0,lc*6*sizeof(real_t),vw.ptr()); + + } + + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + if (!co->index_id) { + + glGenBuffers(1,&co->index_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,lc*3*sizeof(uint16_t),iw.ptr(),GL_STATIC_DRAW); + } else { + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,lc*3*sizeof(uint16_t),iw.ptr()); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind + + co->len=lc; + + } + + + +} + +RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) { + + CanvasLightShadow *cls = memnew( CanvasLightShadow ); + if (p_width>max_texture_size) + p_width=max_texture_size; + + cls->size=p_width; + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &cls->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + // Create a render buffer + glGenRenderbuffers(1, &cls->rbo); + glBindRenderbuffer(GL_RENDERBUFFER, cls->rbo); + + // Create a texture for storing the depth + glGenTextures(1, &cls->depth); + glBindTexture(GL_TEXTURE_2D, cls->depth); + 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); + + cls->height=16; + + //print_line("ERROR? "+itos(glGetError())); + if ( read_depth_supported ) { + + // We'll use a depth texture to store the depths in the shadow map + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cls->size, cls->height, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + +#ifdef GLEW_ENABLED + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#endif + + // Attach the depth texture to FBO depth attachment point + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, cls->depth, 0); + +#ifdef GLEW_ENABLED + glDrawBuffer(GL_NONE); +#endif + + } else { + // We'll use a RGBA texture into which we pack the depth info + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + // Attach the RGBA texture to FBO color attachment point + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, cls->depth, 0); + cls->rgba=cls->depth; + + // Allocate 16-bit depth buffer + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height); + + // Attach the render buffer as depth buffer - will be ignored + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, cls->rbo); + + + } + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + //printf("errnum: %x\n",status); +#ifdef GLEW_ENABLED + if (read_depth_supported) { + //glDrawBuffer(GL_BACK); + } +#endif + glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); + DEBUG_TEST_ERROR("2D Shadow Buffer Init"); + ERR_FAIL_COND_V( status != GL_FRAMEBUFFER_COMPLETE, RID() ); + +#ifdef GLEW_ENABLED + if (read_depth_supported) { + //glDrawBuffer(GL_BACK); + } +#endif + + return canvas_light_shadow_owner.make_rid(cls); +} + +void RasterizerGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_buffer); + ERR_FAIL_COND(!cls); + + + glDisable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + if (!use_rgba_shadowmaps) + glColorMask(0, 0, 0, 0); + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + canvas_shadow_shader.bind(); + + const int vp_height = 10; + + glViewport(0, 0, cls->size,cls->height); + _glClearDepth(1.0f); + glClearColor(1,1,1,1); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + VS::CanvasOccluderPolygonCullMode cull=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + + + for(int i=0;i<4;i++) { + + //make sure it remains orthogonal, makes easy to read angle later + + Transform light; + light.origin[0]=p_light_xform[2][0]; + light.origin[1]=p_light_xform[2][1]; + light.basis[0][0]=p_light_xform[0][0]; + light.basis[0][1]=p_light_xform[1][0]; + light.basis[1][0]=p_light_xform[0][1]; + light.basis[1][1]=p_light_xform[1][1]; + + //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); + + /// p_near=1; + CameraMatrix projection; + { + real_t fov = 90; + real_t near = p_near; + real_t far = p_far; + real_t aspect = 1.0; + + real_t ymax = near * Math::tan( Math::deg2rad( fov * 0.5 ) ); + real_t ymin = - ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; + + projection.set_frustum( xmin, xmax, ymin, ymax, near, far ); + } + + Vector3 cam_target=Matrix3(Vector3(0,0,Math_PI*2*(i/4.0))).xform(Vector3(0,1,0)); + projection = projection * CameraMatrix(Transform().looking_at(cam_target,Vector3(0,0,-1)).affine_inverse()); + + //print_line("near: "+rtos(p_near)); + //print_line("far: "+rtos(p_far)); + //projection.set_perspective(60,size/float(vp_height),p_near,p_far); + + // CameraMatrix light_mat = projection * CameraMatrix(camera); + + canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX,projection); + canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX,light); + + if (i==0) + *p_xform_cache=projection; + + glViewport(0, (cls->height/4)*i, cls->size,cls->height/4); + + CanvasLightOccluderInstance *instance=p_occluders; + + while(instance) { + + CanvasOccluder *cc = canvas_occluder_owner.get(instance->polygon_buffer); + if (!cc || cc->len==0 || !(p_light_mask&instance->light_mask)) { + + instance=instance->next; + continue; + } + + canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX,instance->xform_cache); + if (cull!=instance->cull_cache) { + + cull=instance->cull_cache; + switch(cull) { + case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { + + glDisable(GL_CULL_FACE); + + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + } break; + } + } +/* + if (i==0) { + for(int i=0;i<cc->lines.size();i++) { + Vector2 p = instance->xform_cache.xform(cc->lines.get(i)); + Plane pp(Vector3(p.x,p.y,0),1); + pp.normal = light.xform(pp.normal); + pp = projection.xform4(pp); + print_line(itos(i)+": "+pp.normal/pp.d); + //pp=light_mat.xform4(pp); + //print_line(itos(i)+": "+pp.normal/pp.d); + } + } +*/ + glBindBuffer(GL_ARRAY_BUFFER,cc->vertex_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,cc->index_id); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); + glDrawElements(GL_TRIANGLES,cc->len*3,GL_UNSIGNED_SHORT,0); + + + instance=instance->next; + } + + + } + + glDisableVertexAttribArray(VS::ARRAY_VERTEX); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + + if (shadow_filter==SHADOW_FILTER_ESM) { + //blur the buffer +#if 0 + //this is ignord, it did not make any difference.. + if (read_depth_supported) { + glDepthFunc(GL_ALWAYS); + } else { + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + } + glDisable(GL_CULL_FACE); + glViewport(0, 0, cls->size,cls->height); + + int passes=1; + CanvasLightShadow *blur = canvas_light_shadow_owner.get(canvas_shadow_blur); + + copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,true); + copy_shader.bind(); + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,1); + copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1); + glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0); + + for(int i=0;i<passes;i++) { + + glBindFramebuffer(GL_FRAMEBUFFER, blur->fbo); + glActiveTexture(GL_TEXTURE0); + + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,cls->depth); + else + glBindTexture(GL_TEXTURE_2D,cls->rgba); + + + { + Vector2 src_sb_uv[4]={ + Vector2( 0, 1), + Vector2( 1, 1), + Vector2( 1, 0), + Vector2( 0, 0) + }; + static const Vector2 dst_pos[4]={ + Vector2(-1, 1), + Vector2( 1, 1), + Vector2( 1,-1), + Vector2(-1,-1) + }; + + + + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/cls->size); + _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv); + } + + glActiveTexture(GL_TEXTURE0); + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,blur->depth); + else + glBindTexture(GL_TEXTURE_2D,blur->rgba); + + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + { + float hlimit = float(cls->size) / blur->size; + //hlimit*=2.0; + Vector2 src_sb_uv[4]={ + Vector2( 0, 1), + Vector2( hlimit, 1), + Vector2( hlimit, 0), + Vector2( 0, 0) + }; + static const Vector2 dst_pos[4]={ + Vector2(-1, 1), + Vector2( 1, 1), + Vector2( 1,-1), + Vector2(-1,-1) + }; + + + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/blur->size); + _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv); + } + + } + copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false); + glDepthFunc(GL_LEQUAL); +#endif + } + + glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer); + glColorMask(1, 1, 1, 1); + + + +} + + +void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) { + + CanvasLight* light=p_lights_with_shadow; + + canvas_begin(); //reset + + int h = 10; + int w = viewport.width; + int ofs = h; + + //print_line(" debug lights "); + while(light) { + + // print_line("debug light"); + if (light->shadow_buffer.is_valid()) { + + // print_line("sb is valid"); + CanvasLightShadow * sb = canvas_light_shadow_owner.get(light->shadow_buffer); + if (sb) { + glActiveTexture(GL_TEXTURE0); + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,sb->depth); + else + glBindTexture(GL_TEXTURE_2D,sb->rgba); + _draw_textured_quad(Rect2(h,ofs,w-h*2,h),Rect2(0,0,sb->size,10),Size2(sb->size,10),false,false); + ofs+=h*2; + + } + } + + light=light->shadows_next_ptr; + } + +} + +void RasterizerGLES2::_canvas_normal_set_flip(const Vector2& p_flip) { + + if (p_flip==normal_flip) + return; + normal_flip=p_flip; + canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,normal_flip); +} + + +template<bool use_normalmap> +void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip) { + + int cc=p_item->commands.size(); + CanvasItem::Command **commands = p_item->commands.ptr(); + + + 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 + if (use_normalmap) + _canvas_normal_set_flip(Vector2((flags&CANVAS_RECT_FLIP_H)?-1:1,(flags&CANVAS_RECT_FLIP_V)?-1:1)); + 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); + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); + + } break; + case CanvasItem::Command::TYPE_PRIMITIVE: { + + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + 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: { + + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + 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: { + + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + 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; + } + } + +} + +void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* shader) { + + if (canvas_shader.bind()) + rebind_texpixel_size=true; + + if (material->shader_version!=shader->version) { + //todo optimize uniforms + material->shader_version=shader->version; + } + + 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,max_texture_units-1); + glActiveTexture(GL_TEXTURE0+max_texture_units-1); + 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; + } + + 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)); + } + + + uses_texpixel_size=shader->uses_texpixel_size; + +} + +void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* shader) { + + //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=material->shader_param.find(E->key()); + + if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) { + + RID rid; + if (F) { + rid=F->get(); + } + + if (!rid.is_valid()) { + + Map<StringName,RID>::Element *DT=shader->default_textures.find(E->key()); + if (DT) { + rid=DT->get(); + } + } + + if (rid.is_valid()) { + + int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. + + glActiveTexture(GL_TEXTURE0+tex_id); + Texture *t=texture_owner.get(rid); + if (!t) + glBindTexture(GL_TEXTURE_2D,white_tex); + else + glBindTexture(t->target,t->tex_id); + + glUniform1i(loc,tex_id); + tex_id++; + } + } else { + Variant &v=F?F->get():E->get().default_value; + canvas_shader.set_custom_uniform(idx,v); + } + + idx++; + } + + if (tex_id>1) { + glActiveTexture(GL_TEXTURE0); + } + + 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 + + +} + +void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) { + + + CanvasItem *current_clip=NULL; + Shader *shader_cache=NULL; + + bool rebind_shader=true; + + canvas_opacity=1.0; + canvas_use_modulate=p_modulate!=Color(1,1,1,1); + canvas_modulate=p_modulate; + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false); + + + bool reset_modulate=false; + bool prev_distance_field=false; + + 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_material=NULL; + canvas_use_modulate=p_modulate!=Color(1,1,1,1); + canvas_modulate=p_modulate; + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false); + prev_distance_field=false; + rebind_shader=true; + reset_modulate=true; + + + } + + if (prev_distance_field!=ci->distance_field) { + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,ci->distance_field); + prev_distance_field=ci->distance_field; + rebind_shader=true; + } + + + 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); + } + } + + if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) { + + Rect2 rect; + int x,y,w,h; + + if (ci->copy_back_buffer->full) { + + x = viewport.x; + y = window_size.height-(viewport.height+viewport.y); + w = viewport.width; + h = viewport.height; + } else { + x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x; + y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y); + w = ci->copy_back_buffer->screen_rect.size.x; + h = ci->copy_back_buffer->screen_rect.size.y; + } + glActiveTexture(GL_TEXTURE0+max_texture_units-1); + glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + +#ifdef GLEW_ENABLED + glReadBuffer(GL_COLOR_ATTACHMENT0); +#endif + glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,w,h); +// if (current_clip) { +// // print_line(" a clip "); +// } + + canvas_texscreen_used=true; + glActiveTexture(GL_TEXTURE0); + } + + + + + //begin rect + CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci; + CanvasItemMaterial *material = material_owner->material; + + if (material!=canvas_last_material || rebind_shader) { + + Shader *shader = NULL; + if (material && material->shader.is_valid()) { + shader = shader_owner.get(material->shader); + if (shader && !shader->valid) { + shader=NULL; + } + } + + shader_cache=shader; + + if (shader) { + canvas_shader.set_custom_shader(shader->custom_code_id); + _canvas_item_setup_shader_params(material,shader); + } else { + shader_cache=NULL; + canvas_shader.set_custom_shader(0); + canvas_shader.bind(); + uses_texpixel_size=false; + + } + + + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); + if (canvas_use_modulate) + reset_modulate=true; + canvas_last_material=material; + rebind_shader=false; + } + + if (material && shader_cache) { + + _canvas_item_setup_shader_uniforms(material,shader_cache); + } + + bool unshaded = material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED; + + if (unshaded) { + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1)); + reset_modulate=true; + } else if (reset_modulate) { + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate); + reset_modulate=false; + } + + + + 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); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } 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_REVERSE_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; + } + + canvas_opacity = ci->final_opacity; + + + if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT))) + _canvas_item_render_commands<false>(ci,current_clip,reclip); + + if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) { + + CanvasLight *light = p_light; + bool light_used=false; + VS::CanvasLightMode mode=VS::CANVAS_LIGHT_MODE_ADD; + + + while(light) { + + if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) { + + //intersects this light + + if (!light_used || mode!=light->mode) { + + mode=light->mode; + + switch(mode) { + + case VS::CANVAS_LIGHT_MODE_ADD: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + + } break; + case VS::CANVAS_LIGHT_MODE_SUB: { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case VS::CANVAS_LIGHT_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + } break; + } + + } + + if (!light_used) { + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,true); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false); + light_used=true; + normal_flip=Vector2(1,1); + + } + + bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask&light->item_shadow_mask; + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,has_shadow); + + bool light_rebind = canvas_shader.bind(); + + if (light_rebind) { + + if (material && shader_cache) { + _canvas_item_setup_shader_params(material,shader_cache); + _canvas_item_setup_shader_uniforms(material,shader_cache); + } + + canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform); + canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); + if (canvas_use_modulate) + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate); + canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,Vector2(1,1)); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE,1.0/light->shadow_buffer_size); + + + } + + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX,light->light_shader_xform); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,Color(light->color.r*light->energy,light->color.g*light->energy,light->color.b*light->energy,light->color.a)); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse()); + + if (has_shadow) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(light->shadow_buffer); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,cls->depth); + else + glBindTexture(GL_TEXTURE_2D,cls->rgba); + + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); + + } + + + glActiveTexture(GL_TEXTURE0+max_texture_units-2); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2); + Texture *t = texture_owner.get(light->texture); + if (!t) { + glBindTexture(GL_TEXTURE_2D,white_tex); + } else { + + glBindTexture(t->target,t->tex_id); + } + + glActiveTexture(GL_TEXTURE0); + _canvas_item_render_commands<true>(ci,current_clip,reclip); //redraw using light + + } + + light=light->next_ptr; + } + + if (light_used) { + + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,false); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,false); + + canvas_shader.bind(); + + if (material && shader_cache) { + _canvas_item_setup_shader_params(material,shader_cache); + _canvas_item_setup_shader_uniforms(material,shader_cache); + } + + canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform); + canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + if (canvas_use_modulate) + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate); + + glBlendEquation(GL_FUNC_ADD); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + } + + + } + + 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() { @@ -8115,6 +9631,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 { @@ -8164,6 +9752,11 @@ bool RasterizerGLES2::is_environment(const RID& p_rid) const { } bool RasterizerGLES2::is_shader(const RID& p_rid) const { + return shader_owner.owns(p_rid); +} + +bool RasterizerGLES2::is_canvas_light_occluder(const RID& p_rid) const { + return false; } @@ -8334,7 +9927,37 @@ 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 ); + } else if (canvas_occluder_owner.owns(p_rid)) { + + + CanvasOccluder *co = canvas_occluder_owner.get(p_rid); + if (co->index_id) + glDeleteBuffers(1,&co->index_id); + if (co->vertex_id) + glDeleteBuffers(1,&co->vertex_id); + canvas_occluder_owner.free(p_rid); + memdelete(co); + + } else if (canvas_light_shadow_owner.owns(p_rid)) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid); + glDeleteFramebuffers(1,&cls->fbo); + glDeleteRenderbuffers(1,&cls->rbo); + glDeleteTextures(1,&cls->depth); + //if (!read_depth_supported) { + // glDeleteTextures(1,&cls->rgba); + //} + + canvas_light_shadow_owner.free(p_rid); + memdelete(cls); }; } @@ -8450,7 +10073,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) { //printf("errnum: %x\n",status); #ifdef GLEW_ENABLED if (p_use_depth) { - glDrawBuffer(GL_BACK); + //glDrawBuffer(GL_BACK); } #endif glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -8459,7 +10082,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) { #ifdef GLEW_ENABLED if (p_use_depth) { - glDrawBuffer(GL_BACK); + //glDrawBuffer(GL_BACK); } #endif @@ -8837,6 +10460,62 @@ void RasterizerGLES2::_update_blur_buffer() { } #endif + + +bool RasterizerGLES2::_test_depth_shadow_buffer() { + + + int size=16; + + GLuint fbo; + GLuint rbo; + GLuint depth; + + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Create a render buffer + glGenRenderbuffers(1, &rbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + + // Create a texture for storing the depth + glGenTextures(1, &depth); + glBindTexture(GL_TEXTURE_2D, depth); + 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); + + + + // We'll use a depth texture to store the depths in the shadow map + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + +#ifdef GLEW_ENABLED + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#endif + + // Attach the depth texture to FBO depth attachment point + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, depth, 0); + + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + glDeleteFramebuffers(1,&fbo); + glDeleteRenderbuffers(1,&rbo); + glDeleteTextures(1,&depth); + + return status == GL_FRAMEBUFFER_COMPLETE; + +} + void RasterizerGLES2::init() { #ifdef GLEW_ENABLED @@ -8869,10 +10548,12 @@ void RasterizerGLES2::init() { material_shader.init(); canvas_shader.init(); copy_shader.init(); + canvas_shadow_shader.init(); #ifdef GLEW_ENABLED material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL,true); canvas_shader.set_conditional(CanvasShaderGLES2::USE_GLES_OVER_GL,true); + canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_GLES_OVER_GL,true); copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL,true); #endif @@ -8894,9 +10575,6 @@ void RasterizerGLES2::init() { //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++) { @@ -8910,7 +10588,7 @@ void RasterizerGLES2::init() { #ifdef GLEW_ENABLED - read_depth_supported=true; + pvr_supported=false; etc_supported=false; use_depth24 =true; @@ -8926,6 +10604,13 @@ void RasterizerGLES2::init() { latc_supported=true; s3tc_srgb_supported=true; use_anisotropic_filter=true; + float_linear_supported=true; + float_supported=true; + + read_depth_supported=_test_depth_shadow_buffer(); + use_rgba_shadowmaps=!read_depth_supported; + //print_line("read depth support? "+itos(read_depth_supported)); + 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 @@ -8970,7 +10655,10 @@ void RasterizerGLES2::init() { 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; @@ -9008,9 +10696,12 @@ void RasterizerGLES2::init() { - + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units); + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_texture_size); //read_depth_supported=false; + canvas_shadow_blur = canvas_light_shadow_buffer_create(max_texture_size); + { //shadowmaps OS::VideoMode vm=OS::get_singleton()->get_video_mode(); @@ -9032,6 +10723,7 @@ void RasterizerGLES2::init() { //material_shader material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps); + canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps); } @@ -9040,6 +10732,7 @@ void RasterizerGLES2::init() { shadow_mat_ptr = material_owner.get(shadow_material); overdraw_material = create_overdraw_debug_material(); copy_shader.set_conditional(CopyShaderGLES2::USE_8BIT_HDR,!use_fp16_fb); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DEPTH_SHADOWS,read_depth_supported); canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false)); @@ -9053,19 +10746,29 @@ void RasterizerGLES2::init() { glGenBuffers(1,&gui_quad_buffer); glBindBuffer(GL_ARRAY_BUFFER,gui_quad_buffer); - glBufferData(GL_ARRAY_BUFFER,128,NULL,GL_DYNAMIC_DRAW); +#ifdef GLES_NO_CLIENT_ARRAYS //WebGL specific implementation. + glBufferData(GL_ARRAY_BUFFER, 8 * MAX_POLYGON_VERTICES,NULL,GL_DYNAMIC_DRAW); +#else + glBufferData(GL_ARRAY_BUFFER,128,NULL,GL_DYNAMIC_DRAW); +#endif glBindBuffer(GL_ARRAY_BUFFER,0); //unbind +#ifdef GLES_NO_CLIENT_ARRAYS //webgl indices buffer + glGenBuffers(1, &indices_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 16*1024, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// unbind +#endif + using_canvas_bg=false; _update_framebuffer(); DEBUG_TEST_ERROR("Initializing"); } void RasterizerGLES2::finish() { - - memdelete_arr(skinned_buffer); + free(canvas_shadow_blur); } int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) { @@ -9345,10 +11048,29 @@ RasterizerGLES2* RasterizerGLES2::get_singleton() { return _singleton; }; +int RasterizerGLES2::RenderList::max_elements=RenderList::DEFAULT_MAX_ELEMENTS; + RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,bool p_default_fragment_lighting,bool p_use_reload_hooks) { _singleton = this; + RenderList::max_elements=GLOBAL_DEF("rasterizer/max_render_elements",(int)RenderList::DEFAULT_MAX_ELEMENTS); + if (RenderList::max_elements>64000) + RenderList::max_elements=64000; + if (RenderList::max_elements<1024) + RenderList::max_elements=1024; + + opaque_render_list.init(); + alpha_render_list.init(); + + skinned_buffer_size = GLOBAL_DEF("rasterizer/skeleton_buffer_size_kb",DEFAULT_SKINNED_BUFFER_SIZE); + if (skinned_buffer_size<256) + skinned_buffer_size=256; + if (skinned_buffer_size>16384) + skinned_buffer_size=16384; + skinned_buffer_size*=1024; + skinned_buffer = memnew_arr( uint8_t, skinned_buffer_size ); + keep_copies=p_keep_ram_copy; use_reload_hooks=p_use_reload_hooks; pack_arrays=p_compress_arrays; @@ -9392,6 +11114,7 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo RasterizerGLES2::~RasterizerGLES2() { + memdelete_arr(skinned_buffer); }; diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index dc2e22d240..a694571452 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -31,6 +31,8 @@ #include "servers/visual/rasterizer.h" +#define MAX_POLYGON_VERTICES 4096 //used for WebGL canvas_draw_polygon call. + #ifdef GLES2_ENABLED #include "image.h" @@ -51,6 +53,7 @@ #include "drivers/gles2/shaders/material.glsl.h" #include "drivers/gles2/shaders/canvas.glsl.h" +#include "drivers/gles2/shaders/canvas_shadow.glsl.h" #include "drivers/gles2/shaders/blur.glsl.h" #include "drivers/gles2/shaders/copy.glsl.h" #include "drivers/gles2/shader_compiler_gles2.h" @@ -65,7 +68,7 @@ class RasterizerGLES2 : public Rasterizer { MAX_SCENE_LIGHTS=2048, LIGHT_SPOT_BIT=0x80, - DEFAULT_SKINNED_BUFFER_SIZE = 2048 * 1024, // 10k vertices + DEFAULT_SKINNED_BUFFER_SIZE = 2048, // 10k vertices MAX_HW_LIGHTS = 1, }; @@ -86,6 +89,8 @@ class RasterizerGLES2 : public Rasterizer { bool use_shadow_mapping; bool use_fp16_fb; bool srgb_supported; + bool float_supported; + bool float_linear_supported; ShadowFilterTechnique shadow_filter; @@ -104,7 +109,7 @@ class RasterizerGLES2 : public Rasterizer { 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; @@ -117,6 +122,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; @@ -188,10 +194,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; @@ -210,6 +219,7 @@ class RasterizerGLES2 : public Rasterizer { writes_vertex=false; uses_discard=false; uses_time=false; + uses_normal=false; } @@ -237,8 +247,9 @@ class RasterizerGLES2 : public Rasterizer { struct UniformData { + bool inuse; bool istexture; - Variant value; + Variant value; int index; }; @@ -668,6 +679,7 @@ class RasterizerGLES2 : public Rasterizer { bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0; bg_param[VS::ENV_BG_PARAM_SCALE]=1.0; bg_param[VS::ENV_BG_PARAM_GLOW]=0.0; + bg_param[VS::ENV_BG_PARAM_CANVAS_MAX_LAYER]=0; for(int i=0;i<VS::ENV_FX_MAX;i++) fx_enabled[i]=false; @@ -704,6 +716,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 @@ -796,25 +820,31 @@ class RasterizerGLES2 : public Rasterizer { bool current_depth_mask; VS::MaterialBlendMode current_blend_mode; bool use_fast_texture_filter; + int max_texture_size; bool fragment_lighting; RID shadow_material; Material *shadow_mat_ptr; + int max_texture_units; GLuint base_framebuffer; GLuint gui_quad_buffer; + GLuint indices_buffer; + struct RenderList { enum { - MAX_ELEMENTS=4096, + DEFAULT_MAX_ELEMENTS=4096, MAX_LIGHTS=4, SORT_FLAG_SKELETON=1, SORT_FLAG_INSTANCING=2, }; + static int max_elements; + struct Element { @@ -847,8 +877,8 @@ class RasterizerGLES2 : public Rasterizer { }; - Element _elements[MAX_ELEMENTS]; - Element *elements[MAX_ELEMENTS]; + Element *_elements; + Element **elements; int element_count; void clear() { @@ -983,17 +1013,28 @@ class RasterizerGLES2 : public Rasterizer { } _FORCE_INLINE_ Element* add_element() { - if (element_count>MAX_ELEMENTS) + if (element_count>=max_elements) return NULL; elements[element_count]=&_elements[element_count]; return elements[element_count++]; } - RenderList() { + void init() { element_count = 0; - for (int i=0;i<MAX_ELEMENTS;i++) + elements=memnew_arr(Element*,max_elements); + _elements=memnew_arr(Element,max_elements); + for (int i=0;i<max_elements;i++) elements[i]=&_elements[i]; // assign elements + + } + + RenderList() { + + } + ~RenderList() { + memdelete_arr(elements); + memdelete_arr(_elements); } }; @@ -1071,6 +1112,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(); + /***********/ @@ -1090,6 +1133,7 @@ class RasterizerGLES2 : public Rasterizer { bool active; int blur_size; + struct Blur { GLuint fbo; @@ -1122,6 +1166,7 @@ class RasterizerGLES2 : public Rasterizer { void _process_glow_and_bloom(); //void _update_blur_buffer(); + /*********/ /* FRAME */ /*********/ @@ -1140,6 +1185,45 @@ class RasterizerGLES2 : public Rasterizer { } _rinfo; + /*******************/ + /* CANVAS OCCLUDER */ + /*******************/ + + + struct CanvasOccluder { + + GLuint vertex_id; // 0 means, unconfigured + GLuint index_id; // 0 means, unconfigured + DVector<Vector2> lines; + int len; + }; + + RID_Owner<CanvasOccluder> canvas_occluder_owner; + + /***********************/ + /* CANVAS LIGHT SHADOW */ + /***********************/ + + + struct CanvasLightShadow { + + int size; + int height; + GLuint fbo; + GLuint rbo; + GLuint depth; + GLuint rgba; //for older devices + + GLuint blur; + + }; + + RID_Owner<CanvasLightShadow> canvas_light_shadow_owner; + + RID canvas_shadow_blur; + + /* ETC */ + RenderTarget *current_rt; bool current_rt_transparent; bool current_rt_vflip; @@ -1149,6 +1233,17 @@ class RasterizerGLES2 : public Rasterizer { GLuint white_tex; RID canvas_tex; float canvas_opacity; + Color canvas_modulate; + bool canvas_use_modulate; + bool uses_texpixel_size; + bool rebind_texpixel_size; + Transform canvas_transform; + CanvasItemMaterial *canvas_last_material; + bool canvas_texscreen_used; + Vector2 normal_flip; + _FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip); + + _FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture); VS::MaterialBlendMode canvas_blend_mode; @@ -1167,6 +1262,7 @@ class RasterizerGLES2 : public Rasterizer { void _process_hdr(); void _draw_tex_bg(); + bool using_canvas_bg; Size2 window_size; VS::ViewportRect viewport; double last_time; @@ -1178,21 +1274,24 @@ class RasterizerGLES2 : public Rasterizer { VS::ScenarioDebugMode current_debug; RID overdraw_material; + mutable MaterialShaderGLES2 material_shader; - CanvasShaderGLES2 canvas_shader; + mutable CanvasShaderGLES2 canvas_shader; BlurShaderGLES2 blur_shader; CopyShaderGLES2 copy_shader; + mutable CanvasShadowShaderGLES2 canvas_shadow_shader; mutable ShaderCompilerGLES2 shader_precompiler; 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); _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color* p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_gui_primitive2(int p_points, const Vector2 *p_vertices, const Color* p_colors, const Vector2 *p_uvs, const Vector2 *p_uvs2); - 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_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, bool p_transpose=false ); void _draw_quad(const Rect2& p_rect); void _copy_screen_quad(); void _copy_to_texscreen(); + bool _test_depth_shadow_buffer(); Vector3 chunk_vertex; Vector3 chunk_normal; @@ -1203,6 +1302,10 @@ class RasterizerGLES2 : public Rasterizer { GLuint tc0_id_cache; GLuint tc0_idx; + template<bool use_normalmap> + _FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip); + _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* p_shader); + _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* p_shader); public: /* TEXTURE API */ @@ -1237,6 +1340,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 */ @@ -1499,6 +1606,8 @@ public: /* CANVAS API */ + virtual void begin_canvas_bg(); + virtual void canvas_begin(); virtual void canvas_disable_blending(); @@ -1514,6 +1623,19 @@ 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,int p_z,const Color& p_modulate,CanvasLight *p_light); + virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow); + + /* CANVAS LIGHT SHADOW */ + + //buffer + virtual RID canvas_light_shadow_buffer_create(int p_width); + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache); + + //occluder + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines); + /* ENVIRONMENT */ @@ -1531,6 +1653,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*/ @@ -1548,6 +1673,8 @@ public: virtual bool is_environment(const RID& p_rid) const; virtual bool is_shader(const RID& p_rid) const; + virtual bool is_canvas_light_occluder(const RID& p_rid) const; + virtual void free(const RID& p_rid); virtual void init(); diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 50b63e1aa0..69bd269948 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -61,6 +61,7 @@ static String _typestr(SL::DataType p_type) { case SL::TYPE_VEC2: return "vec2"; case SL::TYPE_VEC3: return "vec3"; case SL::TYPE_VEC4: return "vec4"; + case SL::TYPE_MAT2: return "mat2"; case SL::TYPE_MAT3: return "mat3"; case SL::TYPE_MAT4: return "mat4"; case SL::TYPE_TEXTURE: return "sampler2D"; @@ -131,6 +132,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 +143,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,6 +175,9 @@ 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) { @@ -212,6 +219,58 @@ 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 (vnode->name==vname_world_vec) { + uses_worldvec=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_normal) { + uses_normal=true; + } + + if (vnode->name==vname_shadow) { + uses_shadow_color=true; + } + + } if (vnode->name==vname_time) { uses_time=true; @@ -229,6 +288,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a case SL::TYPE_VEC2: { Vector2 v = cnode->value; code="vec2("+_mknum(v.x)+", "+_mknum(v.y)+")"; } break; case SL::TYPE_VEC3: { Vector3 v = cnode->value; code="vec3("+_mknum(v.x)+", "+_mknum(v.y)+", "+_mknum(v.z)+")"; } break; case SL::TYPE_VEC4: { Plane v = cnode->value; code="vec4("+_mknum(v.normal.x)+", "+_mknum(v.normal.y)+", "+_mknum(v.normal.z)+", "+_mknum(v.d)+")"; } break; + case SL::TYPE_MAT2: { Matrix32 x = cnode->value; code="mat2( vec2("+_mknum(x[0][0])+", "+_mknum(x[0][1])+"), vec2("+_mknum(x[1][0])+", "+_mknum(x[1][1])+"))"; } break; case SL::TYPE_MAT3: { Matrix3 x = cnode->value; code="mat3( vec3("+_mknum(x.get_axis(0).x)+", "+_mknum(x.get_axis(0).y)+", "+_mknum(x.get_axis(0).z)+"), vec3("+_mknum(x.get_axis(1).x)+", "+_mknum(x.get_axis(1).y)+", "+_mknum(x.get_axis(1).z)+"), vec3("+_mknum(x.get_axis(2).x)+", "+_mknum(x.get_axis(2).y)+", "+_mknum(x.get_axis(2).z)+"))"; } break; case SL::TYPE_MAT4: { Transform x = cnode->value; code="mat4( vec4("+_mknum(x.basis.get_axis(0).x)+", "+_mknum(x.basis.get_axis(0).y)+", "+_mknum(x.basis.get_axis(0).z)+",0.0), vec4("+_mknum(x.basis.get_axis(1).x)+", "+_mknum(x.basis.get_axis(1).y)+", "+_mknum(x.basis.get_axis(1).z)+",0.0), vec4("+_mknum(x.basis.get_axis(2).x)+", "+_mknum(x.basis.get_axis(2).y)+", "+_mknum(x.basis.get_axis(2).z)+",0.0), vec4("+_mknum(x.origin.x)+", "+_mknum(x.origin.y)+", "+_mknum(x.origin.z)+",1.0))"; } break; default: code="<error: "+Variant::get_type_name(cnode->value.get_type())+" ("+itos(cnode->datatype)+">"; @@ -260,13 +320,13 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); - code=mul_l+"=(vec4("+mul_l+",1.0,1.0)*("+mul_r+")).xy"; + code=mul_l+"=(vec4("+mul_l+",0.0,1.0)*("+mul_r+")).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); - code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",1.0,1.0)).xy"; + code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",0.0,1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT3) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); @@ -296,11 +356,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { - code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",1.0,1.0)).xyz"; + code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",0.0,1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT4) { - code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",1.0,1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xyz"; + code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",0.0,1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT3 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { @@ -357,7 +417,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") { @@ -421,6 +481,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a m="[2]"; else if (mnode->name=="w") m="[3]"; + } else if (mnode->basetype==SL::TYPE_MAT2) { + if (mnode->name=="x") + m="[0]"; + else if (mnode->name=="y") + m="[1]"; } else if (mnode->basetype==SL::TYPE_MAT3) { if (mnode->name=="x") @@ -550,7 +615,11 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT uses_light=false; uses_time=false; uses_normalmap=false; + uses_normal=false; + uses_texpixel_size=false; + uses_worldvec=false; vertex_code_writes_vertex=false; + uses_shadow_color=false; uniforms=r_uniforms; flags=&r_flags; r_flags.use_color_interp=false; @@ -560,6 +629,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT 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; @@ -582,6 +652,10 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.uses_light=uses_light; r_flags.uses_time=uses_time; r_flags.uses_normalmap=uses_normalmap; + r_flags.uses_normal=uses_normal; + r_flags.uses_texpixel_size=uses_texpixel_size; + r_flags.uses_worldvec=uses_worldvec; + r_flags.uses_shadow_color=uses_shadow_color; r_code_line=code; r_globals_line=global_code; @@ -595,6 +669,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { replace_table["vec2" ]= "vec2"; replace_table["vec3" ]= "vec3"; replace_table["vec4" ]= "vec4"; + replace_table["mat2" ]= "mat2"; replace_table["mat3" ]= "mat3"; replace_table["mat4" ]= "mat4"; replace_table["texture" ]= "sampler2D"; @@ -638,6 +713,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"; @@ -676,6 +752,7 @@ 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"; @@ -718,6 +795,52 @@ 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]["WORLD_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]["POSITION"]="gl_Position"; + mode_replace_table[5]["NORMAL"]="normal"; + mode_replace_table[5]["UV"]="uv_interp"; + mode_replace_table[5]["COLOR"]="color"; + mode_replace_table[5]["TEXTURE"]="texture"; + mode_replace_table[5]["TEXTURE_PIXEL_SIZE"]="texpixel_size"; + mode_replace_table[5]["VAR1"]="var1_interp"; + mode_replace_table[5]["VAR2"]="var2_interp"; + mode_replace_table[5]["LIGHT_VEC"]="light_vec"; + mode_replace_table[5]["LIGHT_HEIGHT"]="light_height"; + mode_replace_table[5]["LIGHT_COLOR"]="light"; + mode_replace_table[5]["LIGHT_UV"]="light_uv"; + mode_replace_table[5]["LIGHT"]="light_out"; + mode_replace_table[5]["SHADOW"]="shadow_color"; + mode_replace_table[5]["SCREEN_UV"]="screen_uv"; + 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"; @@ -738,5 +861,9 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_light="LIGHT"; vname_time="TIME"; vname_normalmap="NORMALMAP"; + vname_normal="NORMAL"; + vname_texpixel_size="TEXTURE_PIXEL_SIZE"; + vname_world_vec="WORLD_VERTEX"; + vname_shadow="SHADOW"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 5012414c8b..87016fd968 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -51,7 +51,11 @@ private: bool uses_time; bool uses_screen_uv; bool uses_normalmap; + bool uses_normal; + bool uses_texpixel_size; + bool uses_worldvec; bool vertex_code_writes_vertex; + bool uses_shadow_color; Flags *flags; StringName vname_discard; @@ -68,6 +72,10 @@ private: StringName vname_light; StringName vname_time; StringName vname_normalmap; + StringName vname_normal; + StringName vname_texpixel_size; + StringName vname_world_vec; + StringName vname_shadow; Map<StringName,ShaderLanguage::Uniform> *uniforms; @@ -79,7 +87,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: @@ -101,6 +109,10 @@ public: bool use_var2_interp; bool uses_light; bool uses_time; + bool uses_normal; + bool uses_texpixel_size; + bool uses_worldvec; + bool uses_shadow_color; }; 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/SCsub b/drivers/gles2/shaders/SCsub index c665cf9036..9679223b16 100644 --- a/drivers/gles2/shaders/SCsub +++ b/drivers/gles2/shaders/SCsub @@ -3,6 +3,7 @@ Import('env') if env['BUILDERS'].has_key('GLSL120GLES'): env.GLSL120GLES('material.glsl'); env.GLSL120GLES('canvas.glsl'); + env.GLSL120GLES('canvas_shadow.glsl'); env.GLSL120GLES('blur.glsl'); env.GLSL120GLES('copy.glsl'); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index f36741d586..c4f0847870 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -18,20 +18,81 @@ 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; +uniform highp mat4 light_local_matrix; +uniform vec2 light_pos; +varying vec4 light_uv_interp; + +#if defined(NORMAL_USED) +varying vec4 local_rot; +uniform vec2 normal_flip; +#endif + +#ifdef USE_SHADOWS +varying highp vec2 pos; +#endif + +#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); - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; + highp vec4 outvec = vec4(vertex, 1.0); +{ + vec2 src_vtx=outvec.xy; +VERTEX_SHADER_CODE + +} +#if !defined(USE_WORLD_VEC) + outvec = extra_matrix * outvec; + outvec = modelview_matrix * outvec; +#endif + + + #ifdef USE_PIXEL_SNAP - outvec.xy=floor(outvec.xy+0.5); + outvec.xy=floor(outvec.xy+0.5); #endif + + gl_Position = projection_matrix * outvec; + +#ifdef USE_LIGHTING + + light_uv_interp.xy = (light_matrix * outvec).xy; + light_uv_interp.zw =(light_local_matrix * outvec).xy; +#ifdef USE_SHADOWS + pos=outvec.xy; +#endif + +#if defined(NORMAL_USED) + local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy )*normal_flip.x; + local_rot.zw=normalize( (modelview_matrix * ( extra_matrix * vec4(0.0,1.0,0.0,0.0) )).xy )*normal_flip.y; +#endif + +#endif + } [fragment] @@ -54,17 +115,268 @@ 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_MODULATE + +uniform vec4 modulate; + +#endif + +#ifdef USE_LIGHTING + +uniform sampler2D light_texture; +uniform vec4 light_color; +uniform float light_height; +varying vec4 light_uv_interp; + +#if defined(NORMAL_USED) +varying vec4 local_rot; +#endif + +#ifdef USE_SHADOWS + +uniform highp sampler2D shadow_texture; +uniform float shadow_attenuation; + +uniform highp mat4 shadow_matrix; +varying highp vec2 pos; +uniform float shadowpixel_size; + +#ifdef SHADOW_ESM +uniform float shadow_esm_multiplier; +#endif + +#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,0.0,1.0); +#endif + +#ifdef USE_DISTANCE_FIELD + const float smoothing = 1.0/32.0; + float distance = texture2D(texture, uv_interp).a; + color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance); +#else color *= texture2D( texture, uv_interp ); +#endif + + +#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_MODULATE + + color*=modulate; +#endif + + +#ifdef USE_LIGHTING + + vec2 light_vec = light_uv_interp.zw;; //for shadow and normal mapping + +#if defined(NORMAL_USED) + normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy; +#endif + + float att=1.0; + + vec2 light_uv = light_uv_interp.xy; + vec4 light = texture2D(light_texture,light_uv) * light_color; +#if defined(USE_LIGHT_SHADOW_COLOR) + vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); +#endif + +#if defined(USE_LIGHT_SHADER_CODE) +//light is written by the light shader +{ + vec4 light_out=light*color; +LIGHT_SHADER_CODE + color=light_out; +} + +#else + +#if defined(NORMAL_USED) + vec3 light_normal = normalize(vec3(light_vec,-light_height)); + light*=max(dot(-light_normal,normal),0.0); +#endif + + color*=light; +/* +#ifdef USE_NORMAL + color.xy=local_rot.xy;//normal.xy; + color.zw=vec2(0.0,1.0); +#endif +*/ + +//light shader code +#endif + + if (any(lessThan(light_uv_interp.xy,vec2(0.0,0.0))) || any(greaterThanEqual(light_uv_interp.xy,vec2(1.0,1.0)))) { + color.a=0.0; //invisible + } else { + +#ifdef USE_SHADOWS + + float angle_to_light = -atan(light_vec.x,light_vec.y); + float PI = 3.14159265358979323846264; + /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays + float ang*/ + + float su,sz; + + float abs_angle = abs(angle_to_light); + vec2 point; + float sh; + if (abs_angle<45.0*PI/180.0) { + point = light_vec; + sh=0.0+(1.0/8.0); + } else if (abs_angle>135.0*PI/180.0) { + point = -light_vec; + sh = 0.5+(1.0/8.0); + } else if (angle_to_light>0.0) { + + point = vec2(light_vec.y,-light_vec.x); + sh = 0.25+(1.0/8.0); + } else { + + point = vec2(-light_vec.y,light_vec.x); + sh = 0.75+(1.0/8.0); + + } + + + highp vec4 s = shadow_matrix * highp vec4(point,0.0,1.0); + s.xyz/=s.w; + su=s.x*0.5+0.5; + sz=s.z*0.5+0.5; + + highp float shadow_attenuation=0.0; + +#ifdef USE_DEPTH_SHADOWS + +#define SHADOW_DEPTH(m_tex,m_uv) (texture2D((m_tex),(m_uv)).z) + +#else + +//#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) +#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) + +#endif + + + +#ifdef SHADOW_PCF5 + + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation/=5.0; + +#endif + +#ifdef SHADOW_PCF13 + + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*3.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*4.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*5.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*6.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*3.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*4.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*5.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*6.0,sh))<sz?0.0:1.0; + shadow_attenuation/=13.0; + +#endif + +#ifdef SHADOW_ESM + + + { + float unnormalized = su/shadowpixel_size; + float fractional = fract(unnormalized); + unnormalized = floor(unnormalized); + float zc = SHADOW_DEPTH(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh)); + float zn = SHADOW_DEPTH(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh)); + float z = mix(zc,zn,fractional); + shadow_attenuation=clamp(exp(shadow_esm_multiplier* ( z - sz )),0.0,1.0); + } + +#endif + +#if !defined(SHADOW_PCF5) && !defined(SHADOW_PCF13) && !defined(SHADOW_ESM) + + shadow_attenuation = SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; + +#endif + +#if defined(USE_LIGHT_SHADOW_COLOR) + color=mix(shadow_color,color,shadow_attenuation); +#else + color*=shadow_attenuation; +#endif +//use shadows +#endif + } + +//use lighting +#endif // color.rgb*=color.a; gl_FragColor = color; diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl new file mode 100644 index 0000000000..40cf321dce --- /dev/null +++ b/drivers/gles2/shaders/canvas_shadow.glsl @@ -0,0 +1,62 @@ +[vertex] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + +uniform highp mat4 projection_matrix; +uniform highp mat4 light_matrix; +uniform highp mat4 world_matrix; + +attribute highp vec3 vertex; // attrib:0 + +#ifndef USE_DEPTH_SHADOWS + +varying vec4 position_interp; + +#endif + + +void main() { + + gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0))); + +#ifndef USE_DEPTH_SHADOWS + position_interp = gl_Position; +#endif + +} + +[fragment] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + +#ifndef USE_DEPTH_SHADOWS + +varying vec4 position_interp; + +#endif + +void main() { + +#ifdef USE_DEPTH_SHADOWS + +#else + highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias; + highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); + comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); + gl_FragColor = comp; +#endif + +} + diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index 44337e1197..38fb03ab5c 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 @@ -595,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; @@ -609,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 @@ -771,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 @@ -918,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; @@ -934,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 @@ -1186,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 @@ -1202,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 @@ -1224,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 e1f9aacf5f..cd8125c9af 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 5cdc3ea1c0..dd59890064 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 316397ed80..6fc20f36f7 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 67e486c577..56532f4eeb 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 a898f6e618..462051b21e 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 7da50150e2..116d425d24 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 6a3e474eae..9fbb467baa 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 0000000000..dfe9ddc55f --- /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 0000000000..e82e0c24be --- /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/pvr/AlphaBitmap.h b/drivers/pvr/AlphaBitmap.h new file mode 100644 index 0000000000..57c6b026ea --- /dev/null +++ b/drivers/pvr/AlphaBitmap.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Bitmap.h" + +namespace Javelin { + +class AlphaBitmap : public Bitmap { +public: + AlphaBitmap(int w, int h) + : Bitmap(w, h, 1) { + } + + const unsigned char *GetData() const { return data; } + + unsigned char *GetData() { return data; } +}; + +} diff --git a/drivers/pvr/BitScale.cpp b/drivers/pvr/BitScale.cpp new file mode 100644 index 0000000000..97b3f0aa25 --- /dev/null +++ b/drivers/pvr/BitScale.cpp @@ -0,0 +1,184 @@ +#include "BitScale.h" + + +const uint8_t Javelin::Data::BITSCALE_5_TO_8[32] = { + 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, + 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, + 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, + 246, 255}; + +const uint8_t Javelin::Data::BITSCALE_4_TO_8[16] = { + 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, + 170, 187, 204, 221, 238, 255}; + +const uint8_t Javelin::Data::BITSCALE_3_TO_8[8] = { + 0, 36, 72, 109, 145, 182, 218, 255}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_5_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, + 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, + 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, + 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, + 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, + 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, + 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, + 30, 30, 30, 30, 30, 31}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_4_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_3_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 7}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_5_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, + 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, + 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, + 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, + 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, + 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, + 31, 31, 31, 31, 31, 31}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_4_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_3_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7}; + diff --git a/drivers/pvr/BitScale.h b/drivers/pvr/BitScale.h new file mode 100644 index 0000000000..36613aeeee --- /dev/null +++ b/drivers/pvr/BitScale.h @@ -0,0 +1,28 @@ +//============================================================================ + +#pragma once + +#include "typedefs.h" + +//============================================================================ + +namespace Javelin +{ + namespace Data + { +//============================================================================ + + extern const uint8_t BITSCALE_5_TO_8[32]; + extern const uint8_t BITSCALE_4_TO_8[16]; + extern const uint8_t BITSCALE_3_TO_8[8]; + extern const uint8_t BITSCALE_8_TO_5_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_4_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_3_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_5_CEIL[256]; + extern const uint8_t BITSCALE_8_TO_4_CEIL[256]; + extern const uint8_t BITSCALE_8_TO_3_CEIL[256]; + +//============================================================================ + } // namespace Data +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/BitUtility.h b/drivers/pvr/BitUtility.h new file mode 100644 index 0000000000..588ff3e892 --- /dev/null +++ b/drivers/pvr/BitUtility.h @@ -0,0 +1,19 @@ +#pragma once + +namespace Javelin { + +class BitUtility { +public: + static bool IsPowerOf2(unsigned int x) { + return (x & (x - 1)) == 0; + } + + static unsigned int RotateRight(unsigned int value, unsigned int shift) { + if ((shift &= sizeof(value) * 8 - 1) == 0) { + return value; + } + return (value >> shift) | (value << (sizeof(value) * 8 - shift)); + } +}; + +} diff --git a/drivers/pvr/Bitmap.h b/drivers/pvr/Bitmap.h new file mode 100644 index 0000000000..508ed8cb75 --- /dev/null +++ b/drivers/pvr/Bitmap.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Point2.h" + +namespace Javelin { + +class Bitmap { +public: + int width; + int height; + unsigned char *data; + + Bitmap(int w, int h, int bytesPerPixel) + : width(w) + , height(h) + , data(new unsigned char[width * height * bytesPerPixel]) { + } + + virtual ~Bitmap() { + delete [] data; + } + + Point2<int> GetSize() const { return Point2<int>(width, height); } + + int GetArea() const { return width * height; } + + int GetBitmapWidth() const { return width; } + + int GetBitmapHeight() const { return height; } + + const unsigned char *GetRawData() const { return data; } +}; + +} diff --git a/drivers/pvr/ColorRgba.h b/drivers/pvr/ColorRgba.h new file mode 100644 index 0000000000..6b46d65e3c --- /dev/null +++ b/drivers/pvr/ColorRgba.h @@ -0,0 +1,152 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class ColorRgb { +public: + T b; + T g; + T r; + + + ColorRgb() + : r(0) + , g(0) + , b(0) { + } + + ColorRgb(T red, T green, T blue) + : r(red) + , g(green) + , b(blue) { + } + + ColorRgb(const ColorRgb<T> &x) + : r(x.r) + , g(x.g) + , b(x.b) { + } + + ColorRgb<int> operator *(int x) { + return ColorRgb<int>(r * x, g * x, b * x); + } + + ColorRgb<int> operator +(const ColorRgb<T> &x) const { + return ColorRgb<int>(r + (int)x.r, g + (int)x.g, b + (int)x.b); + } + + ColorRgb<int> operator -(const ColorRgb<T> &x) const { + return ColorRgb<int>(r - (int)x.r, g - (int)x.g, b - (int)x.b); + } + + int operator %(const ColorRgb<T> &x) const { + return r * (int)x.r + g * (int)x.g + b * (int)x.b; + } + + bool operator ==(const ColorRgb<T> &x) const { + return r == x.r && g == x.g && b == x.b; + } + + bool operator !=(const ColorRgb<T> &x) const { + return r != x.r || g != x.g || b != x.b; + } + + void SetMin(const ColorRgb<T> &x) { + if (x.r < r) { + r = x.r; + } + if (x.g < g) { + g = x.g; + } + if (x.b < b) { + b = x.b; + } + } + + void SetMax(const ColorRgb<T> &x) { + if (x.r > r) { + r = x.r; + } + if (x.g > g) { + g = x.g; + } + if (x.b > b) { + b = x.b; + } + } +}; + +template<typename T> +class ColorRgba : public ColorRgb<T> { +public: + T a; + + ColorRgba() : + a(0) { + } + + ColorRgba(T red, T green, T blue, T alpha) + : ColorRgb<T>(red, green, blue) + , a(alpha) { + } + + ColorRgba(const ColorRgba<T> &x) + : ColorRgb<T>(x.r, x.g, x.b) + , a(x.a) { + } + + ColorRgba<int> operator *(int x) { + return ColorRgba<T>(ColorRgb<T>::r * x, + ColorRgb<T>::g * x, + ColorRgb<T>::b * x, + a * x); + } + + ColorRgba<int> operator +(const ColorRgba<T> &x) { + return ColorRgba<T>(ColorRgb<T>::r + (int)x.r, + ColorRgb<T>::g + (int)x.g, + ColorRgb<T>::b + (int)x.b, + a + (int)x.a); + } + + ColorRgba<int> operator -(const ColorRgba<T> &x) { + return ColorRgba<T>(ColorRgb<T>::r - (int)x.r, + ColorRgb<T>::g - (int)x.g, + ColorRgb<T>::b - (int)x.b, + a - (int)x.a); + } + + int operator %(const ColorRgba<T> &x) { + return ColorRgb<T>::r * (int)x.r + + ColorRgb<T>::g * (int)x.g + + ColorRgb<T>::b * (int)x.b + + a * (int)x.a; + } + + bool operator ==(const ColorRgba<T> &x) { + return ColorRgb<T>::r == x.r && ColorRgb<T>::g == x.g && + ColorRgb<T>::b == x.b && a == x.a; + } + + bool operator !=(const ColorRgba<T> &x) { + return ColorRgb<T>::r != x.r || ColorRgb<T>::g != x.g || + ColorRgb<T>::b != x.b || a != x.a; + } + + void SetMin(const ColorRgba<T> &x) { + ColorRgb<T>::SetMin(x); + if (x.a < a) { + a = x.a; + } + } + + void SetMax(const ColorRgba<T> &x) { + ColorRgb<T>::SetMax(x); + if (x.a > a) { + a = x.a; + } + } +}; + +} diff --git a/drivers/pvr/Interval.h b/drivers/pvr/Interval.h new file mode 100644 index 0000000000..a7252e8375 --- /dev/null +++ b/drivers/pvr/Interval.h @@ -0,0 +1,21 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class Interval { +public: + T min; + T max; + + Interval() { + } + + Interval<T> &operator|=(const T &x) { + min.SetMin(x); + max.SetMax(x); + return *this; + } +}; + +} diff --git a/drivers/pvr/MortonTable.cpp b/drivers/pvr/MortonTable.cpp new file mode 100644 index 0000000000..29a5af67f6 --- /dev/null +++ b/drivers/pvr/MortonTable.cpp @@ -0,0 +1,43 @@ +//============================================================================ + +#include "MortonTable.h" + +//============================================================================ + +const unsigned short Javelin::Data::MORTON_TABLE[256] = +{ + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 +}; + +//============================================================================ diff --git a/drivers/pvr/MortonTable.h b/drivers/pvr/MortonTable.h new file mode 100644 index 0000000000..7a27e59544 --- /dev/null +++ b/drivers/pvr/MortonTable.h @@ -0,0 +1,18 @@ +//============================================================================ + +#pragma once + +//============================================================================ + +namespace Javelin +{ + namespace Data + { +//============================================================================ + + extern const unsigned short MORTON_TABLE[256]; + +//============================================================================ + } // namespace Data +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/Point2.h b/drivers/pvr/Point2.h new file mode 100644 index 0000000000..89fa4b6322 --- /dev/null +++ b/drivers/pvr/Point2.h @@ -0,0 +1,17 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class Point2 { +public: + T x; + T y; + + Point2(int a, int b) + : x(a) + , y(b) { + } +}; + +} diff --git a/drivers/pvr/PvrTcDecoder.cpp b/drivers/pvr/PvrTcDecoder.cpp new file mode 100644 index 0000000000..d8a36b342c --- /dev/null +++ b/drivers/pvr/PvrTcDecoder.cpp @@ -0,0 +1,144 @@ +//============================================================================ + +#include "PvrTcDecoder.h" +#include "PvrTcPacket.h" + +#include "MortonTable.h" +#include <assert.h> + +//============================================================================ + +using namespace Javelin; +using Data::MORTON_TABLE; + +//============================================================================ + +inline unsigned PvrTcDecoder::GetMortonNumber(int x, int y) +{ + return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF]; +} + +//============================================================================ + +void PvrTcDecoder::DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data) +{ + assert(size.x == size.y); + + const int blocks = size.x / 4; + const int blockMask = blocks-1; + const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const PvrTcPacket* packet = packets + GetMortonNumber(x, y); + + unsigned mod = packet->modulationData; + const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha; + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const unsigned char* w = weights[mod&3]; + ColorRgb<unsigned char> c; + c.r = (ca.r * w[0] + cb.r * w[1]) >> 7; + c.g = (ca.g * w[0] + cb.g * w[1]) >> 7; + c.b = (ca.b * w[0] + cb.b * w[1]) >> 7; + + result[(py+y*4)*size.x + (px+x*4)] = c; + mod >>= 2; + factor++; + } + } + } + } +} + +void PvrTcDecoder::DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data) +{ + assert(size.x == size.y); + + const int blocks = size.x / 4; + const int blockMask = blocks-1; + const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const PvrTcPacket* packet = packets + GetMortonNumber(x, y); + + unsigned mod = packet->modulationData; + const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha; + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] + + p1->GetColorRgbaA() * (*factor)[1] + + p2->GetColorRgbaA() * (*factor)[2] + + p3->GetColorRgbaA() * (*factor)[3]; + + ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] + + p1->GetColorRgbaB() * (*factor)[1] + + p2->GetColorRgbaB() * (*factor)[2] + + p3->GetColorRgbaB() * (*factor)[3]; + + const unsigned char* w = weights[mod&3]; + ColorRgba<unsigned char> c; + c.r = (ca.r * w[0] + cb.r * w[1]) >> 7; + c.g = (ca.g * w[0] + cb.g * w[1]) >> 7; + c.b = (ca.b * w[0] + cb.b * w[1]) >> 7; + c.a = (ca.a * w[2] + cb.a * w[3]) >> 7; + + result[(py+y*4)*size.x + (px+x*4)] = c; + mod >>= 2; + factor++; + } + } + } + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcDecoder.h b/drivers/pvr/PvrTcDecoder.h new file mode 100644 index 0000000000..1b6fcf964c --- /dev/null +++ b/drivers/pvr/PvrTcDecoder.h @@ -0,0 +1,25 @@ +//============================================================================ + +#pragma once +#include "Point2.h" +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + class PvrTcDecoder + { + public: + static void DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data); + static void DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data); + + private: + static unsigned GetMortonNumber(int x, int y); + }; + +//============================================================================ +} +//============================================================================ diff --git a/drivers/pvr/PvrTcEncoder.cpp b/drivers/pvr/PvrTcEncoder.cpp new file mode 100644 index 0000000000..587b1320f1 --- /dev/null +++ b/drivers/pvr/PvrTcEncoder.cpp @@ -0,0 +1,474 @@ +//============================================================================ + +#include "PvrTcEncoder.h" +#include "AlphaBitmap.h" +#include "PvrTcPacket.h" +#include "RgbBitmap.h" +#include "RgbaBitmap.h" +#include "MortonTable.h" +#include "BitUtility.h" +#include "Interval.h" +#include <assert.h> +#include <math.h> +#include <stdint.h> + +//============================================================================ + +using namespace Javelin; +using Data::MORTON_TABLE; + +//============================================================================ + +static const unsigned char MODULATION_LUT[16] = +{ + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 +}; + +//============================================================================ + +inline unsigned PvrTcEncoder::GetMortonNumber(int x, int y) +{ + return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF]; +} + +//============================================================================ + +void PvrTcEncoder::EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap) +{ + int size = bitmap.GetBitmapWidth(); + assert(size == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(size)); + + // Blocks in each dimension. + int xBlocks = size/8; + int yBlocks = size/4; + + const unsigned char* bitmapData = bitmap.GetRawData(); + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + for(int y = 0; y < yBlocks; ++y) + { + for(int x = 0; x < xBlocks; ++x) + { + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->colorAIsOpaque = 0; + packet->colorA = 0x7ff; // White, with 0 alpha + packet->colorBIsOpaque = 1; + packet->colorB = 0x7fff; // White with full alpha + + const unsigned char* blockBitmapData = &bitmapData[y*4*size + x*8]; + + uint32_t modulationData = 0; + for(int py = 0; py < 4; ++py) + { + const unsigned char* rowBitmapData = blockBitmapData; + for(int px = 0; px < 8; ++px) + { + unsigned char pixel = *rowBitmapData++; + modulationData = BitUtility::RotateRight(modulationData | (pixel >> 7), 1); + } + blockBitmapData += size; + } + packet->modulationData = modulationData; + } + } +} + +void PvrTcEncoder::EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap) +{ + int size = bitmap.GetBitmapWidth(); + assert(size == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(size)); + + // Blocks in each dimension. + int blocks = size/4; + + const unsigned char* bitmapData = bitmap.GetRawData(); + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->colorAIsOpaque = 0; + packet->colorA = 0x7ff; // White, with 0 alpha + packet->colorBIsOpaque = 1; + packet->colorB = 0x7fff; // White with full alpha + + const unsigned char* blockBitmapData = &bitmapData[(y*size + x)*4]; + + uint32_t modulationData = 0; + for(int py = 0; py < 4; ++py) + { + const unsigned char* rowBitmapData = blockBitmapData; + for(int px = 0; px < 4; ++px) + { + unsigned char pixel = *rowBitmapData++; + modulationData = BitUtility::RotateRight(modulationData | MODULATION_LUT[pixel>>4], 2); + } + blockBitmapData += size; + } + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +typedef Interval<ColorRgb<unsigned char> > ColorRgbBoundingBox; + +static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgb<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgb<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const ColorRgb<unsigned char>& pixel = data[py*size + px]; + ColorRgb<int> d = cb - ca; + ColorRgb<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + ColorRgb<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const ColorRgb<unsigned char>& pixel = data[py*size + px]; + ColorRgb<int> d = cb - ca; + ColorRgb<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + ColorRgb<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +typedef Interval<ColorRgba<unsigned char> > ColorRgbaBoundingBox; + +static void CalculateBoundingBox(ColorRgbaBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbaBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] + + p1->GetColorRgbaA() * (*factor)[1] + + p2->GetColorRgbaA() * (*factor)[2] + + p3->GetColorRgbaA() * (*factor)[3]; + + ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] + + p1->GetColorRgbaB() * (*factor)[1] + + p2->GetColorRgbaB() * (*factor)[2] + + p3->GetColorRgbaB() * (*factor)[3]; + + const ColorRgba<unsigned char>& pixel = data[py*size + px]; + ColorRgba<int> d = cb - ca; + ColorRgba<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + p.a=pixel.a*16; + ColorRgba<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcEncoder.h b/drivers/pvr/PvrTcEncoder.h new file mode 100644 index 0000000000..b9344367d9 --- /dev/null +++ b/drivers/pvr/PvrTcEncoder.h @@ -0,0 +1,40 @@ +//============================================================================ + +#pragma once +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + class AlphaBitmap; + class RgbBitmap; + class RgbaBitmap; + + class PvrTcEncoder + { + public: + // Result must be large enough for bitmap.GetArea()/4 bytes + static void EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap); + + private: + static unsigned GetMortonNumber(int x, int y); + }; + +//============================================================================ +} +//============================================================================ diff --git a/drivers/pvr/PvrTcPacket.cpp b/drivers/pvr/PvrTcPacket.cpp new file mode 100644 index 0000000000..2e40d371e8 --- /dev/null +++ b/drivers/pvr/PvrTcPacket.cpp @@ -0,0 +1,209 @@ +//============================================================================ + +#include "PvrTcPacket.h" +#include "BitScale.h" + +//============================================================================ + +using namespace Javelin; + +//============================================================================ + +const unsigned char PvrTcPacket::BILINEAR_FACTORS[16][4] = +{ + { 4, 4, 4, 4 }, + { 2, 6, 2, 6 }, + { 8, 0, 8, 0 }, + { 6, 2, 6, 2 }, + + { 2, 2, 6, 6 }, + { 1, 3, 3, 9 }, + { 4, 0, 12, 0 }, + { 3, 1, 9, 3 }, + + { 8, 8, 0, 0 }, + { 4, 12, 0, 0 }, + { 16, 0, 0, 0 }, + { 12, 4, 0, 0 }, + + { 6, 6, 2, 2 }, + { 3, 9, 1, 3 }, + { 12, 0, 4, 0 }, + { 9, 3, 3, 1 }, +}; + +// Weights are { colorA, colorB, alphaA, alphaB } +const unsigned char PvrTcPacket::WEIGHTS[8][4] = +{ + // Weights for Mode=0 + { 8, 0, 8, 0 }, + { 5, 3, 5, 3 }, + { 3, 5, 3, 5 }, + { 0, 8, 0, 8 }, + + // Weights for Mode=1 + { 8, 0, 8, 0 }, + { 4, 4, 4, 4 }, + { 4, 4, 0, 0 }, + { 0, 8, 0, 8 }, +}; + +//============================================================================ + +ColorRgb<int> PvrTcPacket::GetColorRgbA() const +{ + if(colorAIsOpaque) + { + unsigned char r = colorA >> 9; + unsigned char g = colorA >> 4 & 0x1f; + unsigned char b = colorA & 0xf; + return ColorRgb<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_4_TO_8[b]); + } + else + { + unsigned char r = (colorA >> 7) & 0xf; + unsigned char g = (colorA >> 3) & 0xf; + unsigned char b = colorA & 7; + return ColorRgb<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_3_TO_8[b]); + } +} + +ColorRgb<int> PvrTcPacket::GetColorRgbB() const +{ + if(colorBIsOpaque) + { + unsigned char r = colorB >> 10; + unsigned char g = colorB >> 5 & 0x1f; + unsigned char b = colorB & 0x1f; + return ColorRgb<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_5_TO_8[b]); + } + else + { + unsigned char r = colorB >> 8 & 0xf; + unsigned char g = colorB >> 4 & 0xf; + unsigned char b = colorB & 0xf; + return ColorRgb<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_4_TO_8[b]); + } +} + +ColorRgba<int> PvrTcPacket::GetColorRgbaA() const +{ + if(colorAIsOpaque) + { + unsigned char r = colorA >> 9; + unsigned char g = colorA >> 4 & 0x1f; + unsigned char b = colorA & 0xf; + return ColorRgba<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_4_TO_8[b], + 255); + } + else + { + unsigned char a = colorA >> 11 & 7; + unsigned char r = colorA >> 7 & 0xf; + unsigned char g = colorA >> 3 & 0xf; + unsigned char b = colorA & 7; + return ColorRgba<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_3_TO_8[b], + Data::BITSCALE_3_TO_8[a]); + } +} + +ColorRgba<int> PvrTcPacket::GetColorRgbaB() const +{ + if(colorBIsOpaque) + { + unsigned char r = colorB >> 10; + unsigned char g = colorB >> 5 & 0x1f; + unsigned char b = colorB & 0x1f; + return ColorRgba<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_5_TO_8[b], + 255); + } + else + { + unsigned char a = colorB >> 12 & 7; + unsigned char r = colorB >> 8 & 0xf; + unsigned char g = colorB >> 4 & 0xf; + unsigned char b = colorB & 0xf; + return ColorRgba<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_4_TO_8[b], + Data::BITSCALE_3_TO_8[a]); + } +} + +//============================================================================ + +void PvrTcPacket::SetColorA(const ColorRgb<unsigned char>& c) +{ + int r = Data::BITSCALE_8_TO_5_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_5_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_4_FLOOR[c.b]; + colorA = r<<9 | g<<4 | b; + colorAIsOpaque = true; +} + +void PvrTcPacket::SetColorB(const ColorRgb<unsigned char>& c) +{ + int r = Data::BITSCALE_8_TO_5_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_5_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_5_CEIL[c.b]; + colorB = r<<10 | g<<5 | b; + colorBIsOpaque = true; +} + +void PvrTcPacket::SetColorA(const ColorRgba<unsigned char>& c) +{ + int a = Data::BITSCALE_8_TO_3_FLOOR[c.a]; + if(a == 7) + { + int r = Data::BITSCALE_8_TO_5_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_5_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_4_FLOOR[c.b]; + colorA = r<<9 | g<<4 | b; + colorAIsOpaque = true; + } + else + { + int r = Data::BITSCALE_8_TO_4_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_4_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_3_FLOOR[c.b]; + colorA = a<<11 | r<<7 | g<<3 | b; + colorAIsOpaque = false; + } +} + +void PvrTcPacket::SetColorB(const ColorRgba<unsigned char>& c) +{ + int a = Data::BITSCALE_8_TO_3_CEIL[c.a]; + if(a == 7) + { + int r = Data::BITSCALE_8_TO_5_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_5_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_5_CEIL[c.b]; + colorB = r<<10 | g<<5 | b; + colorBIsOpaque = true; + } + else + { + int r = Data::BITSCALE_8_TO_4_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_4_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_4_CEIL[c.b]; + colorB = a<<12 | r<<8 | g<<4 | b; + colorBIsOpaque = false; + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcPacket.h b/drivers/pvr/PvrTcPacket.h new file mode 100644 index 0000000000..ac3b6a4dd1 --- /dev/null +++ b/drivers/pvr/PvrTcPacket.h @@ -0,0 +1,65 @@ +//============================================================================ +// +// Modulation data specifies weightings of colorA to colorB for each pixel +// +// For mode = 0 +// 00: 0/8 +// 01: 3/8 +// 10: 5/8 +// 11: 8/8 +// +// For mode = 1 +// 00: 0/8 +// 01: 4/8 +// 10: 4/8 with alpha punchthrough +// 11: 8/8 +// +// For colorIsOpaque=0 +// 3 bits A +// 4 bits R +// 4 bits G +// 3/4 bits B +// +// For colorIsOpaque=1 +// 5 bits R +// 5 bits G +// 4/5 bits B +// +//============================================================================ + +#pragma once +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + struct PvrTcPacket + { + unsigned int modulationData; + unsigned usePunchthroughAlpha : 1; + unsigned colorA : 14; + unsigned colorAIsOpaque : 1; + unsigned colorB : 15; + unsigned colorBIsOpaque : 1; + + ColorRgb<int> GetColorRgbA() const; + ColorRgb<int> GetColorRgbB() const; + ColorRgba<int> GetColorRgbaA() const; + ColorRgba<int> GetColorRgbaB() const; + + void SetColorA(const ColorRgb<unsigned char>& c); + void SetColorB(const ColorRgb<unsigned char>& c); + + void SetColorA(const ColorRgba<unsigned char>& c); + void SetColorB(const ColorRgba<unsigned char>& c); + + static const unsigned char BILINEAR_FACTORS[16][4]; + static const unsigned char WEIGHTS[8][4]; + }; + +//============================================================================ +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/RgbBitmap.h b/drivers/pvr/RgbBitmap.h new file mode 100644 index 0000000000..cf1d78667d --- /dev/null +++ b/drivers/pvr/RgbBitmap.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Bitmap.h" +#include "ColorRgba.h" + +namespace Javelin { + +class RgbBitmap : public Bitmap { +public: + RgbBitmap(int w, int h) + : Bitmap(w, h, 3) { + } + + const ColorRgb<unsigned char> *GetData() const { + return reinterpret_cast<ColorRgb<unsigned char> *>(data); + } + + ColorRgb<unsigned char> *GetData() { + return reinterpret_cast<ColorRgb<unsigned char> *>(data); + } +}; + +} diff --git a/drivers/pvr/RgbaBitmap.h b/drivers/pvr/RgbaBitmap.h new file mode 100644 index 0000000000..66b5542c1a --- /dev/null +++ b/drivers/pvr/RgbaBitmap.h @@ -0,0 +1,23 @@ +#pragma once + +#include "ColorRgba.h" +#include "Bitmap.h" + +namespace Javelin { + +class RgbaBitmap : public Bitmap { +public: + RgbaBitmap(int w, int h) + : Bitmap(w, h, 4) { + } + + const ColorRgba<unsigned char> *GetData() const { + return reinterpret_cast<ColorRgba<unsigned char> *>(data); + } + + ColorRgba<unsigned char> *GetData() { + return reinterpret_cast<ColorRgba<unsigned char> *>(data); + } +}; + +} diff --git a/drivers/pvr/SCsub b/drivers/pvr/SCsub index bd4c6f3f88..44b8c3d6bb 100644 --- a/drivers/pvr/SCsub +++ b/drivers/pvr/SCsub @@ -2,10 +2,14 @@ Import('env') pvr_sources = [ + "pvr/BitScale.cpp", + "pvr/MortonTable.cpp", + "pvr/PvrTcDecoder.cpp", + "pvr/PvrTcEncoder.cpp", + "pvr/PvrTcPacket.cpp", "pvr/texture_loader_pvr.cpp" ] env.drivers_sources+=pvr_sources #env.add_source_files(env.drivers_sources, pvr_sources) - diff --git a/drivers/pvr/texture_loader_pvr.cpp b/drivers/pvr/texture_loader_pvr.cpp index b12e0c28b8..5268b953f4 100644 --- a/drivers/pvr/texture_loader_pvr.cpp +++ b/drivers/pvr/texture_loader_pvr.cpp @@ -1,6 +1,8 @@ #include "texture_loader_pvr.h" #include "os/file_access.h" #include <string.h> +#include "PvrTcEncoder.h" +#include "RgbaBitmap.h" static void _pvrtc_decompress(Image* p_img); @@ -154,10 +156,59 @@ String ResourceFormatPVR::get_resource_type(const String &p_path) const { } + +static void _compress_pvrtc4(Image * p_img) { + + Image img = *p_img; + + bool make_mipmaps=false; + if (img.get_width()%8 || img.get_height()%8) { + make_mipmaps=img.get_mipmaps()>0; + img.resize(img.get_width()+(8-(img.get_width()%8)),img.get_height()+(8-(img.get_height()%8))); + } + img.convert(Image::FORMAT_RGBA); + if (img.get_mipmaps()==0 && make_mipmaps) + img.generate_mipmaps(); + + bool use_alpha=img.detect_alpha(); + + Image new_img; + new_img.create(img.get_width(),img.get_height(),true,use_alpha?Image::FORMAT_PVRTC4_ALPHA:Image::FORMAT_PVRTC4); + DVector<uint8_t> data=new_img.get_data(); + { + DVector<uint8_t>::Write wr=data.write(); + DVector<uint8_t>::Read r=img.get_data().read(); + + + for(int i=0;i<=new_img.get_mipmaps();i++) { + + int ofs,size,w,h; + img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h); + Javelin::RgbaBitmap bm(w,h); + copymem(bm.GetData(),&r[ofs],size); + { + Javelin::ColorRgba<unsigned char> *dp = bm.GetData(); + for(int j=0;j<size/4;j++) { + SWAP(dp[j].r,dp[j].b); + } + } + + new_img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h); + Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs],bm); + } + + } + + *p_img = Image(new_img.get_width(),new_img.get_height(),new_img.get_mipmaps(),new_img.get_format(),data); + +} + ResourceFormatPVR::ResourceFormatPVR() { Image::_image_decompress_pvrtc=_pvrtc_decompress; + Image::_image_compress_pvrtc4_func=_compress_pvrtc4; + Image::_image_compress_pvrtc2_func=_compress_pvrtc4; } diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index e4bb1a343a..e730171fbb 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -222,7 +222,10 @@ void register_driver_types() { #endif #endif +#ifdef ETC1_ENABLED _register_etc1_compress_func(); +#endif + initialize_chibi(); } diff --git a/drivers/theora/SCsub b/drivers/theora/SCsub index d3e5838276..ecabce6c9d 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 023b2c928b..09fb13d8e9 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 b2987c01c4..fe71cf8566 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 3ff9b217cd..d94c51b4d4 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 8c3d2cc3b9..1b5cf0ab13 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 3ee4b83370..16897ee80e 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 87696d12a9..53b211374a 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 b2ff8062cc..9f4a44ae9d 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 { @@ -107,6 +112,8 @@ public: class AudioStreamInput : public AudioStreamResampled { + _THREAD_SAFE_CLASS_; + int channels; int freq; @@ -114,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() { + + _THREAD_SAFE_METHOD_ + + AudioServer::get_singleton()->stream_set_active(stream_rid,false); + //_clear_stream(); + playing=false; + _clear(); }; - virtual void stop() {}; + 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; }; @@ -141,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; }; @@ -181,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 { @@ -206,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))); @@ -215,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); } }; @@ -232,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; }; }; @@ -242,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 { @@ -258,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 { @@ -306,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; @@ -329,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) { @@ -354,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) { @@ -370,6 +452,13 @@ 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); @@ -380,13 +469,18 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) { 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 { @@ -395,6 +489,7 @@ void VideoStreamTheoraplayer::set_file(const String& 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; @@ -407,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 063bf38953..d43c12609f 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/trex/trex.c b/drivers/trex/trex.c index e63a248e9e..b3668c3a11 100644 --- a/drivers/trex/trex.c +++ b/drivers/trex/trex.c @@ -489,7 +489,7 @@ static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *s return cur;
}
case OP_WB:
- if(str == exp->_bol && !isspace(*str)
+ if((str == exp->_bol && !isspace(*str))
|| (str == exp->_eol && !isspace(*(str-1)))
|| (!isspace(*str) && isspace(*(str+1)))
|| (isspace(*str) && !isspace(*(str+1))) ) {
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 452d791d96..5f51865432 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -161,6 +161,7 @@ String DirAccessUnix::get_next() { } + _cishidden=(fname!="." && fname!=".." && fname.begins_with(".")); @@ -173,6 +174,11 @@ bool DirAccessUnix::current_is_dir() const { return _cisdir; } +bool DirAccessUnix::current_is_hidden() const { + + return _cishidden; +} + void DirAccessUnix::list_dir_end() { diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index 119cb5c3f4..f6089ccfe1 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -50,12 +50,14 @@ class DirAccessUnix : public DirAccess { String current_dir; bool _cisdir; + bool _cishidden; public: virtual bool list_dir_begin(); ///< This starts dir listing virtual String get_next(); virtual bool current_is_dir() const; + virtual bool current_is_hidden() const; virtual void list_dir_end(); ///< diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 7f85526852..2f91eee90e 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -74,7 +74,7 @@ Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) { else if (p_mode_flags==WRITE) mode_string="wb"; else if (p_mode_flags==READ_WRITE) - mode_string="wb+"; + mode_string="rb+"; else return ERR_INVALID_PARAMETER; diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index c221743457..ad0d4e00ea 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 @@ -50,11 +50,16 @@ #ifdef ANDROID_ENABLED #include "platform/android/ifaddrs_android.h" #else + #ifdef __FreeBSD__ + #include <sys/types.h> + #endif #include <ifaddrs.h> #endif #include <arpa/inet.h> #include <sys/socket.h> - + #ifdef __FreeBSD__ + #include <netinet/in.h> + #endif #endif IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp index fa1266b2df..4711f4f090 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 ef4cf644fd..d51a7c74e8 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -42,8 +42,11 @@ #include "dir_access_unix.h" #include "tcp_server_posix.h" #include "stream_peer_tcp_posix.h" +#include "packet_peer_udp_posix.h" - +#ifdef __FreeBSD__ +#include <sys/param.h> +#endif #include <stdarg.h> #include <sys/time.h> #include <sys/wait.h> @@ -115,6 +118,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; @@ -303,7 +307,17 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo args.push_back((char*)cs[i].get_data());// shitty C cast args.push_back(0); +#ifdef __FreeBSD__ + if(p_path.find("/")) { + // exec name contains path so use it + execv(p_path.utf8().get_data(),&args[0]); + }else{ + // use program name and search through PATH to find it + execvp(getprogname(),&args[0]); + } +#else execv(p_path.utf8().get_data(),&args[0]); +#endif // still alive? something failed.. fprintf(stderr,"**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n",p_path.utf8().get_data()); abort(); @@ -330,6 +344,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; } @@ -413,6 +433,12 @@ String OS_Unix::get_executable_path() const { return OS::get_executable_path(); } return b; +#elif defined(__FreeBSD__) + char resolved_path[MAXPATHLEN]; + + realpath(OS::get_executable_path().utf8().get_data(), resolved_path); + + return String(resolved_path); #else ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly."); return OS::get_executable_path(); diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp new file mode 100644 index 0000000000..26a0b29228 --- /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 0000000000..b14568eb5f --- /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 1c7cccc427..2c137629ac 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 d9b7b1d161..996f75d165 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/codebook.c b/drivers/vorbis/codebook.c index 759d7b4254..8a928cebb9 100644 --- a/drivers/vorbis/codebook.c +++ b/drivers/vorbis/codebook.c @@ -248,7 +248,7 @@ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){ } /* quantized values */ - if((quantvals*s->q_quant+7>>3)>opb->storage-oggpack_bytes(opb)) + if(((quantvals*s->q_quant+7)>>3)>opb->storage-oggpack_bytes(opb)) goto _eofout; s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals); for(i=0;i<quantvals;i++) diff --git a/drivers/vorbis/floor1.c b/drivers/vorbis/floor1.c index 9f3154a6a3..ae3dcedb1f 100644 --- a/drivers/vorbis/floor1.c +++ b/drivers/vorbis/floor1.c @@ -1035,7 +1035,7 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ } } - fit_value[i]=val+predicted&0x7fff; + fit_value[i]=(val+predicted)&0x7fff; fit_value[look->loneighbor[i-2]]&=0x7fff; fit_value[look->hineighbor[i-2]]&=0x7fff; diff --git a/drivers/vorbis/os.h b/drivers/vorbis/os.h index 276b4decc7..3df1d194e9 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 9ff53174d4..afe30413c6 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 d80b497149..43cd948fd4 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 df6cc6c5e2..4c265a1ab2 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -68,6 +68,7 @@ struct DirAccessWindowsPrivate { bool DirAccessWindows::list_dir_begin() { _cisdir=false; + _cishidden=false; if (unicode) { list_dir_end(); @@ -95,6 +96,8 @@ String DirAccessWindows::get_next() { if (unicode) { _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); + String name=p->fu.cFileName; if (FindNextFileW(p->h, &p->fu) == 0) { @@ -106,7 +109,9 @@ String DirAccessWindows::get_next() { return name; } else { +#ifndef WINRT_ENABLED _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); String name=p->f.cFileName; @@ -117,7 +122,8 @@ String DirAccessWindows::get_next() { } return name; - +#endif + return ""; } } @@ -126,6 +132,11 @@ bool DirAccessWindows::current_is_dir() const { return _cisdir; } +bool DirAccessWindows::current_is_hidden() const { + + return _cishidden; +} + void DirAccessWindows::list_dir_end() { if (p->h!=INVALID_HANDLE_VALUE) { @@ -268,7 +279,7 @@ Error DirAccessWindows::make_dir(String p_dir) { return OK; }; - if (err == ERROR_ALREADY_EXISTS) { + if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED) { return ERR_ALREADY_EXISTS; }; @@ -358,6 +369,7 @@ bool DirAccessWindows::dir_exists(String p_dir) { return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); } else { +#ifndef WINRT_ENABLED DWORD fileAttr; fileAttr = GetFileAttributesExA(p_dir.ascii().get_data(), GetFileExInfoStandard, &fileInfo); @@ -366,8 +378,8 @@ bool DirAccessWindows::dir_exists(String p_dir) { return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); +#endif } - return false; } diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index 36530ba9b3..4a668a7364 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -58,12 +58,14 @@ class DirAccessWindows : public DirAccess { bool unicode; bool _cisdir; + bool _cishidden; public: virtual bool list_dir_begin(); ///< This starts dir listing virtual String get_next(); virtual bool current_is_dir() const; + virtual bool current_is_hidden() const; virtual void list_dir_end(); ///< virtual int get_drive_count(); diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 3cd065841f..19a62967ea 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -28,14 +28,20 @@ /*************************************************************************/ #ifdef WINDOWS_ENABLED +#define WINVER 0x0500 + +#include <windows.h> +#include "shlwapi.h" #include "file_access_windows.h" + #include <sys/types.h> #include <sys/stat.h> #include <wchar.h> #include <tchar.h> #include "print_string.h" + #ifdef _MSC_VER #define S_ISREG(m) ((m)&_S_IFREG) #endif @@ -54,7 +60,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(); @@ -66,7 +71,7 @@ Error FileAccessWindows::_open(const String& p_filename, int p_mode_flags) { else if (p_mode_flags==WRITE) mode_string=L"wb"; else if (p_mode_flags==READ_WRITE) - mode_string=L"wb+"; + mode_string=L"rb+"; else return ERR_INVALID_PARAMETER; @@ -112,10 +117,20 @@ void FileAccessWindows::close() { //unlink(save_path.utf8().get_data()); //print_line("renaming.."); - _wunlink(save_path.c_str()); //unlink if exists - int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str()); + //_wunlink(save_path.c_str()); //unlink if exists + //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str()); + + + bool rename_error; + if (!PathFileExistsW(save_path.c_str())) { + //creating new file + rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str())!=0; + } else { + //atomic replace for existing file + rename_error = !ReplaceFileW(save_path.c_str(), (save_path+".tmp").c_str(), NULL, 2|4, NULL, NULL); + } save_path=""; - ERR_FAIL_COND( rename_error != 0); + ERR_FAIL_COND( rename_error ); } |