diff --git a/.gitignore b/.gitignore index c02aa6f6..f24b914b 100644 --- a/.gitignore +++ b/.gitignore @@ -49,7 +49,8 @@ platform/wiiu/* *.d *.so *.os - +*.rpx +*.3dsx # QT project files *.config *.creator diff --git a/demos/2d/rubegoldberg/.fscache b/demos/2d/rubegoldberg/.fscache new file mode 100644 index 00000000..50c0d2b3 --- /dev/null +++ b/demos/2d/rubegoldberg/.fscache @@ -0,0 +1,16 @@ +::res://::1705781638 +ball.xml::PackedScene::1705781638:: +box.xml::PackedScene::1705781638:: +domino.xml::PackedScene::1705781638:: +icon.png::ImageTexture::1705781638:: +pendulum.xml::PackedScene::1705781638:: +platform.xml::PackedScene::1705781638:: +rubegoldberg.xml::PackedScene::1705781638:: +seesaw.xml::PackedScene::1705781638:: +::res://art::1705781638 +bowling_ball.png::ImageTexture::1705781638:: +box.png::ImageTexture::1705781638:: +domino.png::ImageTexture::1705781638:: +platform.png::ImageTexture::1705781638:: +seesaw_base.png::ImageTexture::1705781638:: +seesaw_top.png::ImageTexture::1705781638:: diff --git a/demos/3d/balls/.fscache b/demos/3d/balls/.fscache index 804b241e..f7cb1aad 100644 --- a/demos/3d/balls/.fscache +++ b/demos/3d/balls/.fscache @@ -1,5 +1,10 @@ +<<<<<<< HEAD +::res://::1708862929 +char_controller.gd::GDScript::1708780813:: +======= ::res://::1710360441 char_controller.gd::GDScript::1710360441:: +>>>>>>> fbdd36df3a8b2e204567fa7fd666453ee94e0c0c cube.scn::PackedScene::1705843654::scene_3d<>Models/cube.dae<>466036871213f4c3460df5cc83c6a860<>1682196562 floor.scn::PackedScene::1705844193::scene_3d<>Models/floor.dae<>b125887aa8250cd928758a60a3a1bfb5<>1682251078 icon.png::ImageTexture::1705843536:: diff --git a/demos/3d/fixed_materials/.fscache b/demos/3d/fixed_materials/.fscache new file mode 100644 index 00000000..30958d25 --- /dev/null +++ b/demos/3d/fixed_materials/.fscache @@ -0,0 +1,14 @@ +::res://::1705781638 +brick_color.png::ImageTexture::1705781638:: +brick_detail.png::ImageTexture::1705781638:: +brick_detail_emission.png::ImageTexture::1705781638:: +brick_detail_glow.png::ImageTexture::1705781638:: +brick_emission.png::ImageTexture::1705781638:: +brick_normal.png::ImageTexture::1705781638:: +fixed_materials.scn::PackedScene::1705781638::scene_3d<>./boxsphere.dae<>97feba9c1b870d4caf1d354f6adcb5db<>0 +icon.png::ImageTexture::1705781638:: +refmap.png::ImageTexture::1705781638:: +rim.png::ImageTexture::1705781638:: +rocky_specular.png::ImageTexture::1705781638:: +s.xml::Mesh::1705781638:: +tournesol.png::ImageTexture::1705781638:: diff --git a/demos/3d/sat_test/.fscache b/demos/3d/sat_test/.fscache new file mode 100644 index 00000000..b5e549c3 --- /dev/null +++ b/demos/3d/sat_test/.fscache @@ -0,0 +1,7 @@ +::res://::1705781638 +box.scn::PackedScene::1705781638::scene_3d<>./shapes.dae<>53bcfe8d39f1cc21dd4552d41b542c80<>1705781638 +capsule.scn::PackedScene::1705781638::scene_3d<>./shapes.dae<>53bcfe8d39f1cc21dd4552d41b542c80<>1705781638 +convex.scn::PackedScene::1705781638::scene_3d<>./shapes.dae<>53bcfe8d39f1cc21dd4552d41b542c80<>1705781638 +sat_test.xml::PackedScene::1705781638:: +shapes.scn::PackedScene::1705781638::scene_3d<>./shapes.dae<>53bcfe8d39f1cc21dd4552d41b542c80<>1705781638 +sphere.scn::PackedScene::1705781638::scene_3d<>./shapes.dae<>53bcfe8d39f1cc21dd4552d41b542c80<>1705781638 diff --git a/demos/3d/simple/.fscache b/demos/3d/simple/.fscache new file mode 100644 index 00000000..a6b02d80 --- /dev/null +++ b/demos/3d/simple/.fscache @@ -0,0 +1,2 @@ +::res://::1708965924 +icon.png::ImageTexture::1708965924:: diff --git a/demos/3d/simple/cube.dae b/demos/3d/simple/cube.dae new file mode 100644 index 00000000..d9293d60 --- /dev/null +++ b/demos/3d/simple/cube.dae @@ -0,0 +1,101 @@ + + + + + Blender User + Blender 2.80.75 commit date:2019-07-29, commit time:14:47, hash:f6cb5f54494e + + 2024-02-26T17:50:03 + 2024-02-26T17:50:03 + + Z_UP + + + + + + + + 0 0 0 1 + + + 0.8 0.8 0.8 1 + + + 1.45 + + + + + + + + + + + + + + + + + 1 1 1 1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 1 -1 -1 -1 1 -1 -1 -1 + + + + + + + + + + 0 0 1 0 -1 0 -1 0 0 0 0 -1 1 0 0 0 1 0 + + + + + + + + + + 0.625 0 0.375 0.25 0.375 0 0.625 0.25 0.375 0.5 0.375 0.25 0.625 0.5 0.375 0.75 0.375 0.5 0.625 0.75 0.375 1 0.375 0.75 0.375 0.5 0.125 0.75 0.125 0.5 0.875 0.5 0.625 0.75 0.625 0.5 0.625 0 0.625 0.25 0.375 0.25 0.625 0.25 0.625 0.5 0.375 0.5 0.625 0.5 0.625 0.75 0.375 0.75 0.625 0.75 0.625 1 0.375 1 0.375 0.5 0.375 0.75 0.125 0.75 0.875 0.5 0.875 0.75 0.625 0.75 + + + + + + + + + + + + + + +

4 0 0 2 0 1 0 0 2 2 1 3 7 1 4 3 1 5 6 2 6 5 2 7 7 2 8 1 3 9 7 3 10 5 3 11 0 4 12 3 4 13 1 4 14 4 5 15 1 5 16 5 5 17 4 0 18 6 0 19 2 0 20 2 1 21 6 1 22 7 1 23 6 2 24 4 2 25 5 2 26 1 3 27 3 3 28 7 3 29 0 4 30 2 4 31 3 4 32 4 5 33 0 5 34 1 5 35

+
+
+
+
+ + + + 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/demos/3d/simple/cube.scn b/demos/3d/simple/cube.scn new file mode 100644 index 00000000..d28d5903 Binary files /dev/null and b/demos/3d/simple/cube.scn differ diff --git a/demos/3d/simple/engine.cfg b/demos/3d/simple/engine.cfg new file mode 100644 index 00000000..72ee4aa6 --- /dev/null +++ b/demos/3d/simple/engine.cfg @@ -0,0 +1,5 @@ +[application] + +name="simple" +main_scene="res://main.scn" +icon="icon.png" diff --git a/demos/3d/simple/icon.png b/demos/3d/simple/icon.png new file mode 100644 index 00000000..0c422e37 Binary files /dev/null and b/demos/3d/simple/icon.png differ diff --git a/demos/3d/simple/icon.png.flags b/demos/3d/simple/icon.png.flags new file mode 100644 index 00000000..dbef2209 --- /dev/null +++ b/demos/3d/simple/icon.png.flags @@ -0,0 +1 @@ +gen_mipmaps=true diff --git a/demos/3d/simple/main.scn b/demos/3d/simple/main.scn new file mode 100644 index 00000000..7d1f1305 Binary files /dev/null and b/demos/3d/simple/main.scn differ diff --git a/demos/misc/simple_audio/.fscache b/demos/misc/simple_audio/.fscache new file mode 100644 index 00000000..e8de5dcf --- /dev/null +++ b/demos/misc/simple_audio/.fscache @@ -0,0 +1,4 @@ +::res://::1708967223 +icon.png::ImageTexture::1708966717:: +k_jose_-_its_time.ogg::AudioStreamOGGVorbis::1708967006:: +main.scn::PackedScene::1708967223:: diff --git a/demos/misc/simple_audio/engine.cfg b/demos/misc/simple_audio/engine.cfg new file mode 100644 index 00000000..23c8a3d0 --- /dev/null +++ b/demos/misc/simple_audio/engine.cfg @@ -0,0 +1,5 @@ +[application] + +name="simple_audio" +main_scene="res://main.scn" +icon="icon.png" diff --git a/demos/misc/simple_audio/icon.png b/demos/misc/simple_audio/icon.png new file mode 100644 index 00000000..0c422e37 Binary files /dev/null and b/demos/misc/simple_audio/icon.png differ diff --git a/demos/misc/simple_audio/icon.png.flags b/demos/misc/simple_audio/icon.png.flags new file mode 100644 index 00000000..dbef2209 --- /dev/null +++ b/demos/misc/simple_audio/icon.png.flags @@ -0,0 +1 @@ +gen_mipmaps=true diff --git a/demos/misc/simple_audio/k_jose_-_its_time.ogg b/demos/misc/simple_audio/k_jose_-_its_time.ogg new file mode 100644 index 00000000..47815616 Binary files /dev/null and b/demos/misc/simple_audio/k_jose_-_its_time.ogg differ diff --git a/demos/misc/simple_audio/k_jose_-_its_time.spx b/demos/misc/simple_audio/k_jose_-_its_time.spx new file mode 100644 index 00000000..21f049bd Binary files /dev/null and b/demos/misc/simple_audio/k_jose_-_its_time.spx differ diff --git a/demos/misc/simple_audio/main.scn b/demos/misc/simple_audio/main.scn new file mode 100644 index 00000000..a96e7b6d Binary files /dev/null and b/demos/misc/simple_audio/main.scn differ diff --git a/drivers/SCsub b/drivers/SCsub index 40af5fc3..99d2ddd4 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -8,11 +8,13 @@ Export('env') SConscript('unix/SCsub'); SConscript('alsa/SCsub'); SConscript('windows/SCsub'); -if env["platform"] in ("x11", "vita"): + +if env["platform"] in ("x11", "vita", "javascript"): SConscript('gles2/SCsub'); if env["platform"] in ("x11soft", "windows"): SConscript('gl11/SCsub'); -elif env["platform"] != "vita": +else: + SConscript('gles1/SCsub'); SConscript('gl_context/SCsub'); SConscript('openssl/SCsub'); diff --git a/drivers/gles1/rasterizer_gles1.cpp b/drivers/gles1/rasterizer_gles1.cpp index f3e8c201..b4ccb9d3 100644 --- a/drivers/gles1/rasterizer_gles1.cpp +++ b/drivers/gles1/rasterizer_gles1.cpp @@ -26,7 +26,7 @@ /* 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 +#if defined(GLES1_ENABLED) || defined(__psp2__) #include "rasterizer_gles1.h" #include "os/os.h" @@ -38,6 +38,27 @@ #include "gl_context/context_gl.h" #include +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT +#define GL_TEXTURE_CUBE_MAP_OES GL_TEXTURE_CUBE_MAP_EXT +#endif + +#ifdef __psp2__ +#include +#include +#endif + +#ifndef GL_TEXTURE_GEN_MODE_OES +#define GL_TEXTURE_GEN_MODE_OES GL_TEXTURE_GEN_MODE +#define GL_REFLECTION_MAP_OES GL_REFLECTION_MAP_ARB +#define glTexGeniOES glTexGeni +#endif + _FORCE_INLINE_ static void _gl_load_transform(const Transform& tr) { GLfloat matrix[16]={ /* build a 16x16 matrix */ @@ -2201,45 +2222,126 @@ RID RasterizerGLES1::immediate_create() { void RasterizerGLES1::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(im->building); + + Immediate::Chunk ic; + ic.texture=p_texture; + ic.primitive=p_rimitive; + im->chunks.push_back(ic); + im->mask=0; + im->building=true; + } void RasterizerGLES1::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + Immediate::Chunk *c = &im->chunks.back()->get(); + + + if (c->vertices.empty() && im->chunks.size()==1) { + + im->aabb.pos=p_vertex; + im->aabb.size=Vector3(); + } else { + im->aabb.expand_to(p_vertex); + } + + if (im->mask&VS::ARRAY_FORMAT_NORMAL) + c->normals.push_back(chunk_normal); + if (im->mask&VS::ARRAY_FORMAT_TANGENT) + c->tangents.push_back(chunk_tangent); + if (im->mask&VS::ARRAY_FORMAT_COLOR) + c->colors.push_back(chunk_color); + if (im->mask&VS::ARRAY_FORMAT_TEX_UV) + c->uvs.push_back(chunk_uv); + if (im->mask&VS::ARRAY_FORMAT_TEX_UV2) + c->uvs2.push_back(chunk_uv2); + im->mask|=VS::ARRAY_FORMAT_VERTEX; + c->vertices.push_back(p_vertex); } + + void RasterizerGLES1::immediate_normal(RID p_immediate,const Vector3& p_normal){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_NORMAL; + chunk_normal=p_normal; } void RasterizerGLES1::immediate_tangent(RID p_immediate,const Plane& p_tangent){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TANGENT; + chunk_tangent=p_tangent; } void RasterizerGLES1::immediate_color(RID p_immediate,const Color& p_color){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_COLOR; + chunk_color=p_color; } void RasterizerGLES1::immediate_uv(RID p_immediate,const Vector2& tex_uv){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TEX_UV; + chunk_uv=tex_uv; } void RasterizerGLES1::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TEX_UV2; + chunk_uv2=tex_uv; } void RasterizerGLES1::immediate_end(RID p_immediate){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->building=false; } void RasterizerGLES1::immediate_clear(RID p_immediate) { + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(im->building); + im->chunks.clear(); } AABB RasterizerGLES1::immediate_get_aabb(RID p_immediate) const { - return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND_V(!im,AABB()); + return im->aabb; } void RasterizerGLES1::immediate_set_material(RID p_immediate,RID p_material) { @@ -2247,6 +2349,7 @@ 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 { @@ -2933,21 +3036,80 @@ RID RasterizerGLES1::viewport_data_create() { RID RasterizerGLES1::render_target_create(){ - return RID(); + RenderTarget *rt = memnew( RenderTarget ); + rt->fbo=0; + rt->width=0; + rt->height=0; + rt->last_pass=0; + rt->color = 0; // Add color texture to rt to use for blitting + Texture *texture = memnew(Texture); + texture->active=false; + texture->total_data_size=0; + texture->render_target=rt; + // texture->ignore_mipmaps=true; + rt->texture_ptr=texture; + rt->texture=texture_owner.make_rid( texture ); + rt->texture_ptr->active=false; + return render_target_owner.make_rid(rt); } -void RasterizerGLES1::render_target_set_size(RID p_render_target, int p_width, int p_height){ + +void RasterizerGLES1::render_target_set_size(RID p_render_target,int p_width,int p_height){ + + RenderTarget *rt = render_target_owner.get(p_render_target); + + if (p_width==rt->width && p_height==rt->height) + return; + + if (rt->width!=0 && rt->height!=0) { + + glDeleteTextures(1,&rt->color); + + rt->width=0; + rt->height=0; + rt->texture_ptr->tex_id=0; + rt->texture_ptr->active=false; + + } + + if (p_width==0 || p_height==0) + return; + + + rt->width=p_width; + rt->height=p_height; + + + //color texture + 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); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + rt->texture_ptr->tex_id=rt->color; + rt->texture_ptr->active=true; + rt->texture_ptr->width=p_width; + rt->texture_ptr->height=p_height; } -RID RasterizerGLES1::render_target_get_texture(RID p_render_target) const{ - return RID(); +RID RasterizerGLES1::render_target_get_texture(RID p_render_target) const{ + const RenderTarget *rt = render_target_owner.get(p_render_target); + ERR_FAIL_COND_V(!rt,RID()); + return rt->texture; } + bool RasterizerGLES1::render_target_renedered_in_frame(RID p_render_target){ - return false; + RenderTarget *rt = render_target_owner.get(p_render_target); + ERR_FAIL_COND_V(!rt,false); + return rt->last_pass==frame; } @@ -2978,8 +3140,32 @@ void RasterizerGLES1::begin_frame() { } void RasterizerGLES1::capture_viewport(Image* r_capture) { + DVector pixels; + pixels.resize(viewport.width * viewport.height * 4); + DVector::Write w = pixels.write(); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glReadPixels(viewport.x, window_size.height - (viewport.height + viewport.y), viewport.width, viewport.height, GL_RGBA, GL_UNSIGNED_BYTE, w.ptr()); + + bool flip = true;//current_rt == NULL; + + if (flip) { + 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::Write(); + r_capture->create(viewport.width, viewport.height, 0, Image::FORMAT_RGBA, pixels); } @@ -3260,6 +3446,13 @@ void RasterizerGLES1::add_multimesh( const RID& p_multimesh, const InstanceData } +void RasterizerGLES1::add_immediate(const RID &p_immediate, const InstanceData *p_data) { + + Immediate *immediate = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!immediate); + + _add_geometry(immediate, p_data, immediate, NULL); +} void RasterizerGLES1::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ @@ -3386,40 +3579,79 @@ void RasterizerGLES1::_setup_fixed_material(const Geometry *p_geometry,const Mat } - +#ifndef __psp2__ if(p_material->fixed_flags[VS::FIXED_MATERIAL_FLAG_USE_ENVMAP] && p_material->textures[VS::FIXED_MATERIAL_PARAM_ENVMAP].is_valid()) { Texture *texture = texture_owner.get( p_material->textures[VS::FIXED_MATERIAL_PARAM_ENVMAP] ); ERR_FAIL_COND(!texture); - glEnable(GL_TEXTURE_2D); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); - glActiveTexture(GL_TEXTURE0); + + + glTexGeniOES(GL_S, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); + glTexGeniOES(GL_T, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); + glTexGeniOES(GL_R, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); + glBindTexture( GL_TEXTURE_2D,texture->tex_id ); // glDisable(GL_TEXTURE_GEN_S); // glDisable(GL_TEXTURE_GEN_T); + } else { + // glDisable(GL_TEXTURE_CUBE_MAP_OES); + glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_2D); + +#else + + if(p_material->fixed_flags[VS::FIXED_MATERIAL_FLAG_USE_ENVMAP] && p_material->textures[VS::FIXED_MATERIAL_PARAM_ENVMAP].is_valid()) { + + Texture *texture = texture_owner.get( p_material->textures[VS::FIXED_MATERIAL_PARAM_ENVMAP] ); + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_GEN_STR_OES); + + glTexGeniOES(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); + glBindTexture( GL_TEXTURE_2D,texture->tex_id ); + + } else { + glActiveTexture(GL_TEXTURE0); + glDisable(GL_TEXTURE_GEN_STR_OES); glDisable(GL_TEXTURE_2D); +#endif 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); + glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D,texture->tex_id ); + + // tc0_id_cache = texture->tex_id; + } else if(p_material->fixed_flags[VS::FIXED_MATERIAL_FLAG_USE_REFLECTION]) { + glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, reflect_texture); + reflect = true; } else { - + // glDisable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); + } +// #ifndef __psp2__ } - +// #endif } @@ -3729,6 +3961,23 @@ static const int gl_texcoord_index[VS::ARRAY_MAX-1] = { -1, // ARRAY_WEIGHTS }; +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 + +}; Error RasterizerGLES1::_setup_geometry(const Geometry *p_geometry, const Material* p_material, const Skeleton *p_skeleton,const float *p_morphs) { @@ -4014,7 +4263,7 @@ Error RasterizerGLES1::_setup_geometry(const Geometry *p_geometry, const Materia } if (gl_texcoord_index[i] != -1) { - glClientActiveTexture(GL_TEXTURE0+gl_texcoord_index[i]); + glClientActiveTexture(GL_TEXTURE0+client_tex_index); } glEnableClientState(gl_client_states[i]); @@ -4058,7 +4307,98 @@ Error RasterizerGLES1::_setup_geometry(const Geometry *p_geometry, const Materia } break; + case Geometry::GEOMETRY_IMMEDIATE: { + bool restore_tex=false; + const Immediate *im = static_cast( p_geometry ); + if (im->building) { + break; + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glClientActiveTexture(GL_TEXTURE0); + + for (const List::Element *E = im->chunks.front(); E; E = E->next()) { + + const Immediate::Chunk &c = E->get(); + if (c.vertices.empty()) { + continue; + } + + // what on earth? + //for (int i = 0; i < c.vertices.size(); i++) + + if (c.texture.is_valid() && texture_owner.owns(c.texture)) { + + const Texture *t = texture_owner.get(c.texture); + // Texture2D should always be enabled + glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0 + tc0_idx); + glBindTexture(t->target, t->tex_id); + restore_tex = true; + + } + else if (restore_tex) { + + glActiveTexture(GL_TEXTURE0 + tc0_idx); + glBindTexture(GL_TEXTURE_2D, tc0_id_cache); + restore_tex = false; + } + + if (!c.normals.empty()) { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, c.normals.ptr()); + } + else { + glDisableClientState(GL_NORMAL_ARRAY); + } + + if (!c.colors.empty()) { + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_FLOAT, 0, c.colors.ptr()); + } + else { + + glDisableClientState(GL_COLOR_ARRAY); + glColor4f(1, 1, 1, 1); + } + + if (!c.uvs.empty()) { + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, c.uvs.ptr()); + } + else { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, c.vertices.ptr()); + glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size()); + } + + if (restore_tex) { + glActiveTexture(GL_TEXTURE0 + tc0_idx); + glBindTexture(GL_TEXTURE_2D, tc0_id_cache); + restore_tex = false; + } + + // reset the client states just in case cus the driver explodes if I don't + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + // if (restore_tex) { + // + // glActiveTexture(GL_TEXTURE0+tc0_idx); + // glBindTexture(GL_TEXTURE_2D,tc0_id_cache); + // restore_tex=false; + // } + glDisable(GL_TEXTURE_2D); + } break; default: break; }; @@ -4066,23 +4406,7 @@ Error RasterizerGLES1::_setup_geometry(const Geometry *p_geometry, const Materia 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) { @@ -4357,20 +4681,22 @@ void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reve bool bind_baked_light_octree=false; bool bind_baked_lightmap=false; + bool normal_map = 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 + baked_light=NULL; //can't mix // material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,true); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,sl->texture); //bind the texture } } if (baked_light) { - if (baked_light->mode==VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) { + // glEnable(GL_TEXTURE_2D); + /*if (baked_light->mode==VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) { // material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,true); bind_baked_light_octree=true; if (prev_baked_light!=baked_light) { @@ -4391,9 +4717,9 @@ void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reve } - } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { - + } else*/ if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { + int lightmap_idx = e->instance->baked_lightmap_id; // material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false); @@ -4410,10 +4736,11 @@ void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reve Texture *tex = texture_owner.get(texid); if (tex) { - - glActiveTexture(GL_TEXTURE0); - glBindTexture(tex->target,tex->tex_id); //bind the texture - } + // glEnable(GL_TEXTURE_2D); + // glActiveTexture(GL_TEXTURE1); + // glBindTexture(tex->target,tex->tex_id); //bind the texture + // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } prev_baked_light_texture=texid; } @@ -4424,10 +4751,35 @@ void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reve } } + } else { + + // glDisable(GL_TEXTURE_2D); } + + if(!normal_map) { + + glActiveTexture(GL_TEXTURE1); + glClientActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + } if (material!=prev_material || geometry_cmp!=prev_geometry_cmp) { _setup_material(e->geometry,material); + if(material->textures[VS::FIXED_MATERIAL_PARAM_NORMAL].is_valid() && material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE].is_valid()) { + normal_map = true; + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + } + /* + if(bind_baked_lightmap) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + }*/ _rinfo.mat_change_count++; //_setup_material_overrides(e->material,NULL,material_overrides); //_setup_material_skeleton(material,skeleton); @@ -4438,12 +4790,28 @@ void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reve }; } - + client_tex_index = 0; if (geometry_cmp!=prev_geometry_cmp || prev_skeleton!=skeleton) { _setup_geometry(e->geometry, material,e->skeleton,e->instance->morph_values.ptr()); }; + if(normal_map) { + Texture *normal = texture_owner.get( material->textures[VS::FIXED_MATERIAL_PARAM_NORMAL] ); + ERR_FAIL_COND(!normal); + + + + glActiveTexture(GL_TEXTURE1); + + glClientActiveTexture(GL_TEXTURE1); + glEnable(GL_TEXTURE_2D); + // _render(e->geometry, material, skeleton,e->owner); + client_tex_index = 1; + _setup_geometry(e->geometry, material,e->skeleton,e->instance->morph_values.ptr()); + glBindTexture( GL_TEXTURE_2D,normal->tex_id ); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + } // if (i==0 || light_key!=prev_light_key) { // printf("setup\n"); _setup_lights(e->lights,e->light_count); //dunno how inefficent is but it fixes lights @@ -4492,11 +4860,11 @@ void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reve //bool changed_shader = material_shader.bind(); //if ( changed_shader && material->shader_cache && !material->shader_cache->params.empty()) // _setup_shader_params(material); - _render(e->geometry, material, skeleton,e->owner); + prev_material=material; prev_skeleton=skeleton; // prev_geometry=geometry; @@ -4511,7 +4879,7 @@ void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reve }; void RasterizerGLES1::_process_blur(int times, float inc) { - +#ifndef __psp2__ float spost = 0.0f; float alphainc = 0.9f / times; float alpha = 0.2f; @@ -4619,6 +4987,7 @@ void RasterizerGLES1::_process_blur(int times, float inc) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); +#endif } @@ -4798,8 +5167,16 @@ void RasterizerGLES1::end_scene() { // material_shader.set_conditional( MaterialShaderGLES1::USE_FOG,false); if(current_env->fx_enabled[VS::ENV_FX_ES1_BLUR] && !is_editor) _process_blur(current_env->fx_param[VS::ENV_FX_PARAM_ES1_BLUR_TIMES], current_env->fx_param[VS::ENV_FX_PARAM_ES1_BLUR_ALPHA]); - - + if(!is_editor && reflect) { + // glEnable(GL_TEXTURE_CUBE_MAP_OES); + glViewport(0,0,256,256); + glBindTexture(GL_TEXTURE_2D, reflect_texture); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 256, 256, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); + + } + reflect = false; // _debug_shadows(); } @@ -5058,6 +5435,7 @@ void RasterizerGLES1::end_frame() { */ //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(); } @@ -6276,13 +6654,20 @@ void RasterizerGLES1::init() { glewInit(); #endif - +#ifdef __psp2__ + glTexGeniOES = (PFNGLTEXGENIOESPROC)eglGetProcAddress("glTexGeniOES"); + + if (!glTexGeniOES) { + printf("Failed to load glTexGeniOES\n"); + } +#endif scene_pass=1; +#ifndef __psp2__ if (ContextGL::get_singleton()) ContextGL::get_singleton()->make_current(); - +#endif Set extensions; @@ -6342,17 +6727,55 @@ void RasterizerGLES1::init() { s3tc_supported=false; _rinfo.texture_mem=0; - unsigned int* data; - - data = (GLuint *)calloc( 1, ((256 * 256)* 4 * sizeof(GLuint)) ); glGenTextures(1, &BlurTexture); glBindTexture(GL_TEXTURE_2D, BlurTexture); glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); + GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - // free(data); TODO + + glGenTextures(1, &reflect_texture); + glBindTexture(GL_TEXTURE_2D, reflect_texture); +/* + + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES, 0, 4, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES, 0, 4, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES, 0, 4, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES, 0, 4, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES, 0, 4, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES, 0, 4, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, 0);*/ + + +#ifdef __psp2__ + glEnable(GL_TEXTURE_GEN_STR_OES); + glTexGeniOES(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); +#else + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glTexGeniOES(GL_S, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); + glTexGeniOES(GL_T, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); + glTexGeniOES(GL_R, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES); + +#endif + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#ifdef __psp2__ + glDisable(GL_TEXTURE_GEN_STR_OES); +#else + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); +#endif } void RasterizerGLES1::finish() { diff --git a/drivers/gles1/rasterizer_gles1.h b/drivers/gles1/rasterizer_gles1.h index eb5e9efd..b3bcd338 100644 --- a/drivers/gles1/rasterizer_gles1.h +++ b/drivers/gles1/rasterizer_gles1.h @@ -31,7 +31,7 @@ #include "servers/visual/rasterizer.h" -#ifdef GLES1_ENABLED +#if defined(GLES1_ENABLED) || defined(__psp2__) #include "image.h" #include "rid.h" @@ -62,14 +62,25 @@ class RasterizerGLES1 : public Rasterizer { MAX_SCENE_LIGHTS=2048, LIGHT_SPOT_BIT=0x80, DEFAULT_SKINNED_BUFFER_SIZE = 1024 * 1024, // 10k vertices +#ifdef __psp2__ + MAX_HW_LIGHTS = 8, //Yay! 8 Lights :blush: +#else MAX_HW_LIGHTS = 4, +#endif }; + +#ifdef __psp2__ + typedef void (*PFNGLTEXGENIOESPROC)(GLenum coord, GLenum pname, GLint param); + PFNGLTEXGENIOESPROC glTexGeniOES = NULL; +#endif + #ifdef PSP void glActiveTexture(int a1) { }; void glClientActiveTexture(int a1) { }; #endif GLuint BlurTexture; + GLuint reflect_texture; uint8_t *skinned_buffer; int skinned_buffer_size; @@ -80,10 +91,13 @@ class RasterizerGLES1 : public Rasterizer { bool pack_arrays; bool use_reload_hooks; bool is_editor; - + uint8_t client_tex_index = 0; + bool reflect = false; 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); + + class RenderTarget; struct Texture { @@ -100,6 +114,7 @@ class RasterizerGLES1 : public Rasterizer { bool compressed; bool disallow_mipmaps; int total_data_size; + RenderTarget *render_target; Image image[6]; @@ -110,7 +125,7 @@ class RasterizerGLES1 : public Rasterizer { StringName reloader_func; Texture() { - + render_target = NULL; flags=width=height=0; tex_id=0; data_size=0; @@ -213,6 +228,7 @@ class RasterizerGLES1 : public Rasterizer { enum Type { GEOMETRY_INVALID, GEOMETRY_SURFACE, + GEOMETRY_IMMEDIATE, GEOMETRY_POLY, GEOMETRY_PARTICLES, GEOMETRY_MULTISURFACE, @@ -409,10 +425,27 @@ class RasterizerGLES1 : public Rasterizer { mutable RID_Owner multimesh_owner; mutable SelfList::List _multimesh_dirty_list; - struct Immediate { + struct Immediate : public Geometry { + + struct Chunk { + + RID texture; + VS::PrimitiveType primitive; + Vector vertices; + Vector normals; + Vector tangents; + Vector colors; + Vector uvs; + Vector uvs2; + }; + + List chunks; + bool building; + int mask; + AABB aabb; + + Immediate() { type=GEOMETRY_IMMEDIATE; building=false;} - RID material; - int empty; }; mutable RID_Owner immediate_owner; @@ -451,6 +484,21 @@ class RasterizerGLES1 : public Rasterizer { mutable RID_Owner skeleton_owner; + + struct RenderTarget { + + Texture *texture_ptr; + RID texture; + GLuint fbo; + GLuint color; + GLuint depth; + int width,height; + uint64_t last_pass; + + }; + + mutable RID_Owner render_target_owner; + struct Light { VS::LightType type; @@ -716,7 +764,8 @@ class RasterizerGLES1 : public Rasterizer { RenderList opaque_render_list; RenderList alpha_render_list; - + // RenderList reflection_render_list; + RID default_material; struct FX { @@ -796,7 +845,14 @@ class RasterizerGLES1 : public Rasterizer { 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); - + Vector3 chunk_vertex; + Vector3 chunk_normal; + Plane chunk_tangent; + Color chunk_color; + Vector2 chunk_uv; + Vector2 chunk_uv2; + GLuint tc0_id_cache; + GLuint tc0_idx = 0; /***********/ /* SHADOWS */ @@ -1192,7 +1248,7 @@ class RasterizerGLES1 : public Rasterizer { 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_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(); diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 50b63e1a..ed636da5 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -488,10 +488,10 @@ Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) { header+=_typestr(fnode->arguments[i].type)+" "+replace_string(fnode->arguments[i].name); } - header+=") {"ENDL; + header+=") {" ENDL; String fcode=header; fcode+=dump_node_code(fnode->body,1); - fcode+="}"ENDL; + fcode+="}" ENDL; global_code+=fcode; } diff --git a/drivers/mpc/mpc_reader.c b/drivers/mpc/mpc_reader.c index e1d151fe..05197751 100644 --- a/drivers/mpc/mpc_reader.c +++ b/drivers/mpc/mpc_reader.c @@ -36,6 +36,7 @@ #include #include "internal.h" #include +#include #define STDIO_MAGIC 0xF34B963C ///< Just a random safe-check value... typedef struct mpc_reader_stdio_t { diff --git a/drivers/theoraplayer/SCsub b/drivers/theoraplayer/SCsub index cd8cabcc..dd349af1 100644 --- a/drivers/theoraplayer/SCsub +++ b/drivers/theoraplayer/SCsub @@ -2,7 +2,7 @@ Import("env") import string -sources = string.split(""" +sources = """ src/TheoraVideoClip.cpp src/FFmpeg/TheoraVideoClip_FFmpeg.cpp src/TheoraAsync.cpp @@ -59,7 +59,7 @@ src/YUV/C/yuv420_grey_c.c src/YUV/C/yuv420_yuv_c.c src/YUV/C/yuv420_rgb_c.c src/TheoraVideoFrame.cpp -""") +""".split() if env["platform"] == "iphone": sources.append("src/AVFoundation/TheoraVideoClip_AVFoundation.mm") diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index e84a1790..58173035 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -28,9 +28,11 @@ /*************************************************************************/ #include "dir_access_unix.h" -#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__psp2__) -#if !defined(PSP) && !defined(__psp2__) && !defined(DREAMCAST) +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__psp2__) || defined(__3DS__) + +#if !defined(PSP) && !defined(__psp2__) && !defined(DREAMCAST) && !defined(__3DS__) + #include #endif @@ -300,7 +302,8 @@ Error DirAccessUnix::remove(String p_path) { size_t DirAccessUnix::get_space_left() { -#if !defined(PSP) && !defined(__psp2__) && !defined(DREAMCAST) + +#if !defined(PSP) && !defined(__psp2__) && !defined(DREAMCAST) && !defined(__3DS__) struct statvfs vfs; if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) { diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index c6d98191..350ec446 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -29,7 +29,8 @@ #ifndef DIR_ACCESS_UNIX_H #define DIR_ACCESS_UNIX_H -#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__psp2__) +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__3DS__) || defined(__psp2__) + #include #include diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 5b4ec897..05f67f53 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -28,14 +28,15 @@ /*************************************************************************/ #include "file_access_unix.h" -#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__psp2__) +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__psp2__) || defined(__3DS__) #include #include #include "print_string.h" #include "core/os/os.h" -#if !defined(PSP) && !defined(__psp2__) && !defined(DREAMCAST) +#if !defined(PSP) && !defined(__psp2__) && !defined(DREAMCAST) && !defined(__3DS__) + #include #endif diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 8de993f3..1ce68aa5 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -33,7 +33,8 @@ #include "os/memory.h" #include -#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__psp2__) +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) || defined(PSP) || defined(__psp2__) || defined(__3DS__) + /** @author Juan Linietsky diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index a91b5f2d..d8a3f9f3 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -28,7 +28,9 @@ /*************************************************************************/ #include "ip_unix.h" -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) && !defined(WINRT_ENABLED) || defined(PSP) + +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) && !defined(WINRT_ENABLED) || defined(__3DS__) || defined(PSP) + #ifdef WINDOWS_ENABLED @@ -47,7 +49,7 @@ #endif #else #include -#ifndef PSP +#if !defined(__3DS__) && !defined(PSP) #ifdef ANDROID_ENABLED #include "platform/android/ifaddrs_android.h" #else @@ -74,12 +76,15 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { } -#if defined(PSP) + +#if defined(PSP) || defined(__3DS__) + void IP_Unix::get_local_addresses(List *r_addresses) const { }; -#else + +#else #if defined(WINDOWS_ENABLED) @@ -146,6 +151,9 @@ void IP_Unix::get_local_addresses(List *r_addresses) const { #endif + +// #else + #else void IP_Unix::get_local_addresses(List *r_addresses) const { diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index 9f3db553..32c557e3 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -31,7 +31,8 @@ #include "io/ip.h" -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(PSP) +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(__3DS__) || defined(PSP) + class IP_Unix : public IP { OBJ_TYPE(IP_Unix, IP); diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 26a0b292..226f565a 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -117,7 +117,7 @@ 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) { + while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), 0, (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); diff --git a/drivers/unix/semaphore_posix.cpp b/drivers/unix/semaphore_posix.cpp index 6f1b8931..0f9c8179 100644 --- a/drivers/unix/semaphore_posix.cpp +++ b/drivers/unix/semaphore_posix.cpp @@ -56,8 +56,9 @@ Error SemaphorePosix::post() { int SemaphorePosix::get() const { int val; +#ifndef JAVASCRIPT_ENABLED sem_getvalue(&sem, &val); - +#endif return val; } diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index b354f983..1c593b31 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -26,9 +26,12 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if defined(UNIX_ENABLED) || defined(PSP) + +#if defined(UNIX_ENABLED) || defined(__3DS__) || defined(PSP) #include "stream_peer_tcp_posix.h" + #include + #ifndef PSP #include @@ -62,7 +65,7 @@ #endif static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { - + // printf("%s\n", p_host.host); their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(p_port); // short, network byte order their_addr.sin_addr = *((struct in_addr*)&p_host.host); @@ -169,7 +172,9 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { //perror("socket"); return FAILED; }; -#ifndef PSP +#if !defined(__3DS__) && ! defined(PSP) + + #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); #else @@ -177,6 +182,38 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { ioctl(sockfd, FIONBIO, &bval); #endif #endif + +#ifdef __3DS__ + #define atoa(x) #x + struct addrinfo hints; + struct addrinfo *resaddr = NULL, *resaddr_cur; + memset(&hints, 0, sizeof(struct addrinfo)); + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + //TODO: Do not embed this + if(getaddrinfo("google.com", "80", &hints, &resaddr)!=0) + { + printf("getaddrinfo() failed.\n"); + closesocket(sockfd); + // return; + } + + for(resaddr_cur = resaddr; resaddr_cur!=NULL; resaddr_cur = resaddr_cur->ai_next) + { + if(::connect(sockfd, resaddr_cur->ai_addr, resaddr_cur->ai_addrlen)==0)break; + } + + freeaddrinfo(resaddr); + + if(resaddr_cur==NULL) + { + printf("Failed to connect.\n"); + closesocket(sockfd); + // return; + } +#else + struct sockaddr_in their_addr; set_addr_in(their_addr, p_host, p_port); @@ -187,7 +224,7 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { disconnect(); return FAILED; }; - +#endif if (errno == EINPROGRESS) { status = STATUS_CONNECTING; } else { @@ -227,8 +264,11 @@ Error StreamPeerTCPPosix::write(const uint8_t* p_data,int p_bytes, int &r_sent, int total_sent = 0; while (data_to_send) { - +#ifdef JAVASCRIPT_ENABLED + int sent_amount = send(sockfd, offset, data_to_send, 0); +#else int sent_amount = send(sockfd, offset, data_to_send, MSG_NOSIGNAL); +#endif //printf("Sent TCP data of %d bytes, errno %d\n", sent_amount, errno); if (sent_amount == -1) { diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index 58c5dffb..b978fde5 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -26,7 +26,9 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if defined(UNIX_ENABLED) || defined(PSP) + +#if defined(UNIX_ENABLED) || defined(PSP) || defined(__3DS__) + #ifndef STREAM_PEER_TCP_POSIX_H #define STREAM_PEER_TCP_POSIX_H diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 76e151e3..7a9a6b6a 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -29,10 +29,14 @@ #include "tcp_server_posix.h" #include "stream_peer_tcp_posix.h" -#if defined(UNIX_ENABLED) || defined(PSP) +#if defined(UNIX_ENABLED) || defined(__3DS__) || defined(PSP) + #ifndef PSP #include + + #include + #else #include #endif diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index 0ff5aaaf..732fa690 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -29,7 +29,8 @@ #ifndef TCP_SERVER_POSIX_H #define TCP_SERVER_POSIX_H -#if defined(UNIX_ENABLED) || defined(PSP) +#if defined(UNIX_ENABLED) || defined(PSP) || defined(__3DS__) + #include "core/io/tcp_server.h" class TCPServerPosix : public TCP_Server { diff --git a/platform/3ds/SCsub b/platform/3ds/SCsub new file mode 100644 index 00000000..2fa14e07 --- /dev/null +++ b/platform/3ds/SCsub @@ -0,0 +1,16 @@ +import shlex +from SCons.Node import NodeList + +Import('env') + +SConscript("shaders/SCsub") + +common_3ds=[\ + "os_3ds.cpp",\ + "rasterizer_3ds.cpp",\ + "audio_driver_3ds.cpp",\ + "thread_3ds.cpp",\ + "thread_wrap.cpp",\ +] + +prog = env.Program('#bin/godot_3ds',['godot_3ds.cpp']+common_3ds) diff --git a/platform/3ds/audio_driver_3ds.cpp b/platform/3ds/audio_driver_3ds.cpp new file mode 100644 index 00000000..60180e54 --- /dev/null +++ b/platform/3ds/audio_driver_3ds.cpp @@ -0,0 +1,182 @@ +/*************************************************************************/ +/* audio_driver_3ds.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 __3DS__ +#include "audio_driver_3ds.h" +#include "thread_3ds.h" +#include "globals.h" +#include "os/os.h" +#include + +static int channel_num = 1; + + +Error AudioDriver3ds::init() { + if (ndspInit() < 0) + return FAILED; + + active=false; + thread_exited=false; + exit_thread=false; + pcm_open = false; + samples_in = NULL; + + mix_rate = 44100; + output_format = OUTPUT_STEREO; + channels = 2; + + 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); + + ndspWaveBuf* buffer = ndsp_buffers; + for (int i = 0; i < NDSP_BUFFER_COUNT; ++i) { + memset(buffer, 0, sizeof(ndspWaveBuf)); + buffer->data_vaddr = linearAlloc(buffer_size * channels * sizeof(int16_t)); + buffer->nsamples = buffer_size; + buffer->looping = false; + buffer->status = NDSP_WBUF_DONE; + buffer++; + } + + ndspChnReset(channel_num); + ndspChnSetInterp(channel_num, NDSP_INTERP_LINEAR); + ndspChnSetRate(channel_num, mix_rate); + ndspChnSetFormat(channel_num, (channels == 1) ? NDSP_FORMAT_MONO_PCM16 : NDSP_FORMAT_STEREO_PCM16); + + mutex = Mutex::create(); + thread = Thread3ds::create(AudioDriver3ds::thread_func, this); + + return OK; +}; + +void AudioDriver3ds::thread_func(void* p_udata) { + + int buffer_index = 0; + ndspWaveBuf* buffer; + + AudioDriver3ds* ad = (AudioDriver3ds*)p_udata; + + int sample_count = ad->buffer_size * ad->channels; + + while (!ad->exit_thread) { + + buffer = &ad->ndsp_buffers[buffer_index % NDSP_BUFFER_COUNT]; + + while (!ad->exit_thread && (!ad->active || buffer->status != NDSP_WBUF_DONE)) + OS::get_singleton()->delay_usec(10000); + + if (ad->exit_thread) + break; + + buffer->status = NDSP_WBUF_FREE; + + if (ad->active) { + ad->lock(); + ad->audio_server_process(ad->buffer_size, ad->samples_in); + ad->unlock(); + + for(int i = 0; i < sample_count; ++i) + buffer->data_pcm16[i] = ad->samples_in[i] >> 16; + + } else + memset(buffer->data_pcm16, 0, sample_count * sizeof(int16_t)); + + DSP_FlushDataCache(buffer->data_pcm16, sample_count * sizeof(int16_t)); + ndspChnWaveBufAdd(channel_num, buffer); + + buffer_index++; + } + + ndspChnWaveBufClear(channel_num); + + ad->thread_exited=true; +}; + +void AudioDriver3ds::start() { + + active = true; +}; + +int AudioDriver3ds::get_mix_rate() const { + + return mix_rate; +}; + +AudioDriverSW::OutputFormat AudioDriver3ds::get_output_format() const { + + return output_format; +}; +void AudioDriver3ds::lock() { + + if (!thread || !mutex) + return; + mutex->lock(); +}; +void AudioDriver3ds::unlock() { + + if (!thread || !mutex) + return; + mutex->unlock(); +}; + +void AudioDriver3ds::finish() { + + if (!thread) + return; + + exit_thread = true; + Thread3ds::wait_to_finish(thread); + + if (samples_in) { + memdelete_arr(samples_in); + }; + + for (int i = 0; i < NDSP_BUFFER_COUNT; ++i) + linearFree(ndsp_buffers[i].data_pcm16); + + memdelete(thread); + if (mutex) + memdelete(mutex); + thread = NULL; + + ndspExit(); +}; + +AudioDriver3ds::AudioDriver3ds() { + + mutex = NULL; + thread = NULL; +}; + +AudioDriver3ds::~AudioDriver3ds() { + +}; + +#endif diff --git a/platform/3ds/audio_driver_3ds.h b/platform/3ds/audio_driver_3ds.h new file mode 100644 index 00000000..fe69c974 --- /dev/null +++ b/platform/3ds/audio_driver_3ds.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* audio_driver_3ds.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 AUDIO_DRIVER_3DS_H +#define AUDIO_DRIVER_3DS_H + +#include "servers/audio/audio_server_sw.h" + +#include "core/os/thread.h" +#include "core/os/mutex.h" + +extern "C" { +#include <3ds/types.h> +#include <3ds/ndsp/ndsp.h> +#include <3ds/ndsp/channel.h> +#include <3ds/allocator/linear.h> +#include <3ds/services/dsp.h> +} + + +class AudioDriver3ds : public AudioDriverSW { + + enum { + NDSP_BUFFER_COUNT = 3, + }; + + Thread* thread; + Mutex* mutex; + + int32_t* samples_in; + + ndspWaveBuf ndsp_buffers[NDSP_BUFFER_COUNT]; + + static void thread_func(void* p_udata); + int buffer_size; + + unsigned int mix_rate; + OutputFormat output_format; + + int channels; + + bool active; + bool thread_exited; + mutable bool exit_thread; + bool pcm_open; + +public: + + const char* get_name() const { + return "3DS NDSP"; + }; + + 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(); + + AudioDriver3ds(); + ~AudioDriver3ds(); +}; + +#endif diff --git a/platform/3ds/detect.py b/platform/3ds/detect.py new file mode 100644 index 00000000..3af00e3e --- /dev/null +++ b/platform/3ds/detect.py @@ -0,0 +1,92 @@ + +import os +import sys + + +def is_active(): + return True + + +def get_name(): + return "Server" + + +def can_build(): + if (os.name!="posix"): + return False + + return True # enabled + + +def get_opts(): + return [] + + +def get_flags(): + return [ + ('builtin_zlib', 'no'), + ('theora','no'), #use builtin openssl + ] + +def build_shader_gen(target, source, env, for_signature): + return "picasso -o {} {}".format(target[0], source[0]) + + +def build_shader_header(target, source, env): + import os + data = source[0].get_contents() + data_str = ",".join([str(x) for x in data]) + name = os.path.basename(str(target[0]))[:-2] + target[0].prepare() + with open(str(target[0]), 'w') as f: + f.write("/* Auto-generated from {} */\n".format(str(source[0]))) + f.write("static uint8_t shader_builtin_{}[] =\n{{{}}};".format( + name, data_str)) + + +def configure(env): + + env.Append(CPPPATH=['#platform/3ds']) + + devkit_path = os.environ["DEVKITPRO"] + dev_path = os.environ["DEVKITARM"] + + + env.Append(BUILDERS={'PICA': env.Builder(generator=build_shader_gen, suffix='.shbin', src_suffix='.pica')}) + env.Append(BUILDERS={'PICA_HEADER': env.Builder(action=build_shader_header, suffix='.h', src_suffix='.shbin')}) + + + env["CC"]=dev_path+"/bin/arm-none-eabi-gcc" + env["CXX"]=dev_path+"/bin/arm-none-eabi-g++" + env["LD"]=dev_path+"/bin/arm-none-eabi-g++" + env["AR"]=dev_path+"/bin/arm-none-eabi-ar" + env["AS"]=dev_path+"/bin/arm-none-eabi-as" + env["RANLIB"]=dev_path+"/bin/arm-none-eabi-ranlib" + + env["bits"]="32" + + + + arch = ['-march=armv6k', '-mtune=mpcore','-mfloat-abi=hard','-mtp=soft' ] + + env.Append(CPPPATH=[dev_path+"/arm-none-eabi/include/", devkit_path+"/portlibs/3ds/include/", devkit_path+"/libctru/include/"]) + env.Append(LIBPATH=[dev_path+"/arm-none-eabi/lib/armv6k/fpu/", devkit_path+"/portlibs/3ds/lib/", devkit_path+"/libctru/lib/"]) + + + + if env["target"]=="release": + env.Append(CCFLAGS=['-mword-relocations','-ffunction-sections', '-fno-rtti', '-fno-exceptions']+arch) + elif env["target"]=="release_debug": + env.Append(CCFLAGS=['-O2','-ffast-math','-DDEBUG_ENABLED']) + elif env["target"]=="debug": + env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED']) + + env.Append(CCFLAGS=['-D__3DS__','-DNEED_LONG_INT', '-D_3DS_ENABLED', '-DNO_THREADS','-DNO_SAFE_CAST']) + env.Append(LIBS=['pthread', 'z', 'citro3d', 'ctru']) + env.Append(LINKFLAGS=['-specs=3dsx.specs', '-g'] + arch) + + if (env["CXX"]=="clang++"): + env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) + env["CC"]="clang" + env["LD"]="clang++" + diff --git a/platform/3ds/godot_3ds.cpp b/platform/3ds/godot_3ds.cpp new file mode 100644 index 00000000..ad1bac29 --- /dev/null +++ b/platform/3ds/godot_3ds.cpp @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* godot_server.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 "main/main.h" +#include "os_3ds.h" + + +extern "C" { +#include <3ds/gfx.h> +#include <3ds/os.h> +#include <3ds/console.h> +u32 __stacksize__ = 1024 * 128; +}; + +int main(int argc, char* argv[]) { + + gfxInitDefault(); + gfxSetDoubleBuffering(GFX_TOP, true); + consoleInit(GFX_BOTTOM, NULL); + osSetSpeedupEnable(true); + + OS_3DS os; + + char* args[] = {"-path", "./fe"}; + + Error err = Main::setup("3ds", 2, args, true); + if (err!=OK) + return 255; + + if (Main::start()) { + printf("game running\n"); + os.run(); // it is actually the OS that decides how to run + } + Main::cleanup(); + + return 0; +} diff --git a/platform/3ds/logo.png b/platform/3ds/logo.png new file mode 100644 index 00000000..6b749009 Binary files /dev/null and b/platform/3ds/logo.png differ diff --git a/platform/3ds/os_3ds.cpp b/platform/3ds/os_3ds.cpp new file mode 100644 index 00000000..860b73be --- /dev/null +++ b/platform/3ds/os_3ds.cpp @@ -0,0 +1,407 @@ +/*************************************************************************/ +/* OS_3DS.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 "servers/visual/visual_server_raster.h" +#include "rasterizer_3ds.h" + +#include "os_3ds.h" +#include +#include +#include "print_string.h" +#include "servers/physics/physics_server_sw.h" +#include "drivers/unix/memory_pool_static_malloc.h" +#include "drivers/unix/dir_access_unix.h" +#include "drivers/unix/file_access_unix.h" +#include "os/memory_pool_dynamic_static.h" +#include "core/os/thread_dummy.h" +#include "main/main.h" +#include +#include +#include "thread_3ds.h" +#include "drivers/unix/tcp_server_posix.h" +#include "drivers/unix/stream_peer_tcp_posix.h" +// #include "packet_peer_udp_posix.h" +#include +#include "drivers/unix/ip_unix.h" +extern "C" { +#include <3ds/services/hid.h> +#include <3ds/services/soc.h> +#include <3ds/services/sslc.h> +}; + +#define SOC_ALIGN 0x1000 +#define SOC_BUFFERSIZE 0x100000 + + + +/* +void socShutdown() { + + printf("waiting for socExit...\n"); + socExit(); + +}*/ + + + + // atexit(socShutdown); + +int OS_3DS::get_video_driver_count() const { + + return 1; +} +const char * OS_3DS::get_video_driver_name(int p_driver) const { + + return "citro3D"; +} +OS::VideoMode OS_3DS::get_default_video_mode() const { + + return OS::VideoMode(800,480,false); +} + +static MemoryPoolStaticMalloc *mempool_static=NULL; +static MemoryPoolDynamicStatic *mempool_dynamic=NULL; +static u32 *SOC_buffer = NULL; + +void OS_3DS::initialize_core() { + + + //TODO: Make audio single threaded so I don't need threads + Thread3ds::make_default(); + SemaphoreDummy::make_default(); + MutexDummy::make_default(); + + FileAccess::make_default(FileAccess::ACCESS_RESOURCES); + FileAccess::make_default(FileAccess::ACCESS_USERDATA); + FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); + //FileAccessBufferedFA::make_default(); + DirAccess::make_default(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default(DirAccess::ACCESS_USERDATA); + DirAccess::make_default(DirAccess::ACCESS_FILESYSTEM); + + + mempool_static = new MemoryPoolStaticMalloc; + mempool_dynamic = memnew( MemoryPoolDynamicStatic ); + + ticks_start = 0; + ticks_start = get_ticks_usec(); +/* + FileAccess::make_default(FileAccess::ACCESS_RESOURCES); + FileAccess::make_default(FileAccess::ACCESS_USERDATA); + FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); + //FileAccessBufferedFA::make_default(); + DirAccess::make_default(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default(DirAccess::ACCESS_USERDATA); + DirAccess::make_default(DirAccess::ACCESS_FILESYSTEM);*/ + + SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE); + + if(SOC_buffer == NULL) { + printf("memalign: failed to allocate\n"); + } + int ret; + if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) { + printf("socInit: 0x%08X\n", (unsigned int)ret); + } + sslcInit(0); + + TCPServerPosix::make_default(); + StreamPeerTCPPosix::make_default(); + // PacketPeerUDPPosix::make_default(); + IP_Unix::make_default(); +} + +void OS_3DS::finalize_core() { + if (mempool_dynamic) + memdelete( mempool_dynamic ); + delete mempool_static; +} + +void OS_3DS::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { + + args=OS::get_singleton()->get_cmdline_args(); + current_videomode=p_desired; + main_loop=NULL; + + + rasterizer = memnew( Rasterizer3DS ); + + visual_server = memnew( VisualServerRaster(rasterizer) ); + + AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); + + if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) { + + ERR_PRINT("Initializing audio failed."); + } + + sample_manager = memnew( SampleManagerMallocSW ); + audio_server = memnew( AudioServerSW(sample_manager) ); + audio_server->init(); + spatial_sound_server = memnew( SpatialSoundServerSW ); + spatial_sound_server->init(); + spatial_sound_2d_server = memnew( SpatialSound2DServerSW ); + spatial_sound_2d_server->init(); + + + ERR_FAIL_COND(!visual_server); + + visual_server->init(); + // + physics_server = memnew( PhysicsServerSW ); + physics_server->init(); + physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server->init(); + + input = memnew( InputDefault ); + +} +void OS_3DS::finalize() { + + if(main_loop) + memdelete(main_loop); + main_loop=NULL; + + spatial_sound_server->finish(); + memdelete(spatial_sound_server); + spatial_sound_2d_server->finish(); + memdelete(spatial_sound_2d_server); + + //if (debugger_connection_console) { +// memdelete(debugger_connection_console); +//} + + audio_server->finish(); + memdelete(audio_server); + memdelete(sample_manager); + + visual_server->finish(); + memdelete(visual_server); + memdelete(rasterizer); + + physics_server->finish(); + memdelete(physics_server); + + physics_2d_server->finish(); + memdelete(physics_2d_server); + + memdelete(input); + + args.clear(); +} + +void OS_3DS::set_mouse_show(bool p_show) { + + +} +void OS_3DS::set_mouse_grab(bool p_grab) { + + grab=p_grab; +} +bool OS_3DS::is_mouse_grab_enabled() const { + + return grab; +} + +int OS_3DS::get_mouse_button_state() const { + + return 0; +} + +Point2 OS_3DS::get_mouse_pos() const { + + return Point2(); +} + +void OS_3DS::set_window_title(const String& p_title) { + + +} + +void OS_3DS::set_video_mode(const VideoMode& p_video_mode,int p_screen) { + + +} + +OS::Date OS_3DS::get_date() const { + Date ret; + return ret; +} + +OS::Time OS_3DS::get_time() const { + Time ret; + return ret; +} + + +void OS_3DS::delay_usec(uint32_t p_usec) const{ + usleep(p_usec); +} + +uint64_t OS_3DS::get_ticks_usec() const{ + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + + uint64_t longtime = (uint64_t)tv_now.tv_usec + (uint64_t)tv_now.tv_sec * 1000000L; + longtime -= ticks_start; + + return longtime; +} + +OS::VideoMode OS_3DS::get_video_mode(int p_screen) const { + + return current_videomode; +} +void OS_3DS::get_fullscreen_mode_list(List *p_list,int p_screen) const { + + +} + + +MainLoop *OS_3DS::get_main_loop() const { + + return main_loop; +} + +void OS_3DS::delete_main_loop() { + + if (main_loop) + memdelete(main_loop); + main_loop=NULL; +} + +void OS_3DS::set_main_loop( MainLoop * p_main_loop ) { + + main_loop=p_main_loop; + input->set_main_loop(p_main_loop); +} + +bool OS_3DS::can_draw() const { + + return true; +}; + + +String OS_3DS::get_name() { + + return "Nintendo 3DS"; +} + + + +void OS_3DS::move_window_to_foreground() { + +} + +void OS_3DS::set_cursor_shape(CursorShape p_shape) { + + +} + +static u32 buttons[16] = { + KEY_B, + KEY_A, + KEY_Y, + KEY_X, + KEY_L, + KEY_R, + KEY_ZL, // L2 + KEY_ZR, // R2 + KEY_TOUCH, + KEY_TOUCH, + KEY_SELECT, + KEY_START, + KEY_DUP, + KEY_DDOWN, + KEY_DLEFT, + KEY_DRIGHT, +}; + +void OS_3DS::process_keys() { + hidScanInput(); + + last++; + + u32 down = hidKeysDown(); + + for(int i = 0; i < 16; i++) { + if (down & buttons[i]) { + InputEvent event; + event.type = InputEvent::JOYSTICK_BUTTON; + event.device = 0; + event.joy_button.button_index = i; + event.joy_button.pressed = true; + event.ID = last; + input->parse_input_event(event); + } else { + InputEvent event; + event.type = InputEvent::JOYSTICK_BUTTON; + event.device = 0; + event.joy_button.button_index = i; + event.joy_button.pressed = false; + event.ID = last; + input->parse_input_event(event); + } + } + + circlePosition pos; + hidCircleRead(&pos); + + input->set_joy_axis(0, 0, pos.dx); + input->set_joy_axis(0, 1, pos.dy); +} + +void OS_3DS::run() { + + force_quit = false; + + if (!main_loop) + return; + + main_loop->init(); + + while (!force_quit) { + process_keys(); + + if (Main::iteration()==true) + break; + }; + + main_loop->finish(); +} + +void OS_3DS::swap_buffers() { +} + +OS_3DS::OS_3DS() { + + AudioDriverManagerSW::add_driver(&driver_3ds); + //adriver here + grab=false; + +}; diff --git a/platform/3ds/os_3ds.h b/platform/3ds/os_3ds.h new file mode 100644 index 00000000..d863252b --- /dev/null +++ b/platform/3ds/os_3ds.h @@ -0,0 +1,146 @@ +/*************************************************************************/ +/* os_server.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 OS_3DS_H +#define OS_3DS_H + +#include "os/input.h" +#include "drivers/unix/os_unix.h" +#include "servers/visual_server.h" +#include "servers/visual/rasterizer.h" +#include "servers/audio/audio_driver_dummy.h" +#include "servers/physics_server.h" +#include "servers/audio/audio_server_sw.h" +#include "servers/audio/sample_manager_sw.h" +#include "servers/spatial_sound/spatial_sound_server_sw.h" +#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" +#include "drivers/rtaudio/audio_driver_rtaudio.h" +#include "servers/physics_2d/physics_2d_server_sw.h" +#include "audio_driver_3ds.h" +#undef CursorShape + +class OS_3DS : public OS { + + Rasterizer *rasterizer; + VisualServer *visual_server; + VideoMode current_videomode; + List args; + MainLoop *main_loop; + + + AudioDriver3ds driver_3ds; + bool grab; + uint64_t ticks_start; + + + PhysicsServer *physics_server; + Physics2DServer *physics_2d_server; + + virtual void delete_main_loop(); + // IP_Unix *ip_unix; + + AudioServerSW *audio_server; + SampleManagerMallocSW *sample_manager; + SpatialSoundServerSW *spatial_sound_server; + SpatialSound2DServerSW *spatial_sound_2d_server; + + bool force_quit; + + int last; + + InputDefault *input; + + + +protected: + + virtual int get_video_driver_count() const; + virtual const char * get_video_driver_name(int p_driver) const; + virtual VideoMode get_default_video_mode() const; + + virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver); + virtual void finalize(); + + virtual void set_main_loop( MainLoop * p_main_loop ); + +public: + virtual void initialize_core(); + virtual void finalize_core(); + virtual String get_name(); + + virtual void set_cursor_shape(CursorShape p_shape); + + virtual int get_audio_driver_count() const { return 1; }; + virtual const char * get_audio_driver_name(int p_driver) const { return "Dummy"; }; + virtual void vprint(const char* p_format, va_list p_list, bool p_stderr=false) { if (p_stderr) { + + vfprintf(stderr,p_format,p_list); + fflush(stderr); + } else { + + vprintf(p_format,p_list); + fflush(stdout); + }}; + virtual void alert(const String& p_alert,const String& p_title="ALERT!") {}; + virtual String get_stdin_string(bool p_block = true) { return ""; }; + virtual Error execute(const String& p_path, const List& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL) { return FAILED; }; + virtual Error kill(const ProcessID& p_pid) { return FAILED; }; + virtual bool has_environment(const String& p_var) const { return false; }; + virtual String get_environment(const String& p_var) const { return ""; }; + virtual Date get_date() const; + virtual Time get_time() const; + // virtual TimeZoneInfo get_time_zone_info() const; + virtual void delay_usec(uint32_t p_usec) const; + virtual uint64_t get_ticks_usec() const; + + virtual void process_keys(); + + virtual void set_mouse_show(bool p_show); + virtual void set_mouse_grab(bool p_grab); + virtual bool is_mouse_grab_enabled() const; + virtual Point2 get_mouse_pos() const; + virtual int get_mouse_button_state() const; + virtual void set_window_title(const String& p_title); + + virtual MainLoop *get_main_loop() const; + + virtual bool can_draw() const; + + virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0); + virtual VideoMode get_video_mode(int p_screen=0) const; + virtual void get_fullscreen_mode_list(List *p_list,int p_screen=0) const; + + virtual void move_window_to_foreground(); + virtual void swap_buffers(); + + void run(); + + OS_3DS(); +}; + +#endif diff --git a/platform/3ds/platform_config.h b/platform/3ds/platform_config.h new file mode 100644 index 00000000..1bb5afb0 --- /dev/null +++ b/platform/3ds/platform_config.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* platform_config.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 + diff --git a/platform/3ds/rasterizer_3ds Kopie Kopie.cpp b/platform/3ds/rasterizer_3ds Kopie Kopie.cpp new file mode 100644 index 00000000..c6d92e1e --- /dev/null +++ b/platform/3ds/rasterizer_3ds Kopie Kopie.cpp @@ -0,0 +1,2268 @@ +/*************************************************************************/ +/* rasterizer_3ds.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 "rasterizer_3ds.h" +#include "shaders/simple_3d.h" +#include "shaders/simple_2d.h" + +static const vertex3ds vertex_list[] = +{ + { 200.0f, 200.0f, 0.5f }, + { 100.0f, 40.0f, 0.5f }, + { 300.0f, 40.0f, 0.5f }, +}; + +#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0])) + +#define DISPLAY_TRANSFER_FLAGS \ + (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \ + GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \ + GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) + + +#define TEXTURE_TRANSFER_FLAGS (GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | \ + GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) + + +void _set_uniform(int uniform_location, const Matrix32& p_transform) +{ + const Matrix32& tr = p_transform; + + C3D_Mtx mtx; + + float matrix[16] = { /* build a 16x16 matrix */ + tr.elements[2][0], 0, tr.elements[1][0], tr.elements[0][0], + tr.elements[2][1], 0, tr.elements[1][1], tr.elements[0][1], + 0, 1, 0, 0, + 1, 0, 0, 0, + }; + + memcpy(mtx.m, matrix, sizeof(matrix)); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mtx); +} + +void _set_uniform(int uniform_location, const CameraMatrix& p_matrix) +{ + // Swap X/Y axis due to 3DS screens being sideways + // and adjust clipping range from [-1, 1] to [-1, 0] + float m[16] = { + 0, -1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0.5, 0, + 0, 0, -0.5, 1, + }; + + CameraMatrix p = *reinterpret_cast(m) * p_matrix; + + C3D_Mtx mtx; + float *to = mtx.m; + const float *from = reinterpret_cast(p.matrix); + + + to[0] = from[12]; + to[1] = from[8]; + to[2] = from[4]; + to[3] = from[0]; + to[4] = from[13]; + to[5] = from[9]; + to[6] = from[5]; + to[7] = from[1]; + to[8] = from[14]; + to[9] = from[10]; + to[10] = from[6]; + to[11] = from[2]; + to[12] = from[15]; + to[13] = from[11]; + to[14] = from[7]; + to[15] = from[3]; + + + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mtx); +} + +/* TEXTURE API */ + + +RID Rasterizer3DS::texture_create() { + + Texture *texture = memnew(Texture); + ERR_FAIL_COND_V(!texture,RID()); + return texture_owner.make_rid( texture ); + +} + +void Rasterizer3DS::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { + + + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + C3D_TexInit(&texture->texture, p_width, p_height, GPU_RGBA8); + texture->width=p_width; + texture->height=p_height; + texture->format=p_format; + texture->flags=p_flags; +} + +void Rasterizer3DS::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->format != p_image.get_format() ); + + texture->image[p_cube_side]=p_image; + + DVector d = p_image.get_data(); + const u32* buffer = reinterpret_cast(d.read().ptr()); + u8 * gpuBuffer = (u8 *)linearAlloc(texture->width * texture->height * 4); + + u32 * src = (u32 *)buffer; + u32 * dst = (u32 *)gpuBuffer; + + for (unsigned y = 0; y < texture->height; y++) + { + for (unsigned x = 0; x < texture->width; x++) + { + u32 clr = *src; + // *dst = __builtin_bswap32(clr); + *dst = 0x0; + } + dst += 4; + } + + GSPGPU_FlushDataCache((u32 *)gpuBuffer, texture->width * texture->height * 4); + + C3D_SyncDisplayTransfer((u32 *)gpuBuffer, GX_BUFFER_DIM(texture->width, texture->height), (u32 *)texture->texture.data, GX_BUFFER_DIM(texture->width, texture->height), TEXTURE_TRANSFER_FLAGS); + + // gspWaitForPPF(); + C3D_TexSetFilter(&texture->texture, GPU_LINEAR, GPU_NEAREST); + C3D_TexBind(0, &texture->texture); + + linearFree(gpuBuffer); + + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, (GPU_TEVSRC)0, (GPU_TEVSRC)0); + C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + + +} + +Image Rasterizer3DS::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()); + + return texture->image[p_cube_side]; +} + +void Rasterizer3DS::texture_set_flags(RID p_texture,uint32_t p_flags) { + + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; + texture->flags=p_flags|cube; // can't remove a cube from being a cube + +} +uint32_t Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::texture_get_height(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,0); + + return texture->height; +} + +bool Rasterizer3DS::texture_has_alpha(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,0); + + return false; + +} + +void Rasterizer3DS::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 Rasterizer3DS::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const { + + +} + +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); + + // int type = prim_type[p_points - 1]; + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, p_vertices, sizeof(Vector3), 2, 0x10); + + C3D_DrawArrays(GPU_TRIANGLE_FAN, 0, 4); +}; +//--------------------------------------------------------------------------------- +static void drawSpriteImmediate( size_t idx, int x, int y, int width, int height ) { +//--------------------------------------------------------------------------------- + + float left = 0;//images[image].left; + float right = 0.5;//images[image].right; + float top = 0;//images[image].top; + float bottom = 0.5;//images[image].bottom; + + if (idx > 500) + return; + + // Draw a textured quad directly + C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP); + C3D_ImmSendAttrib(x, y, 0.5f, 0.0f); // v0=position + C3D_ImmSendAttrib( left, top, 0.0f, 0.0f); + + C3D_ImmSendAttrib(x, y+height, 0.5f, 0.0f); + C3D_ImmSendAttrib( left, bottom, 0.0f, 0.0f); + + C3D_ImmSendAttrib(x+width, y, 0.5f, 0.0f); + C3D_ImmSendAttrib( right, top, 0.0f, 0.0f); + + C3D_ImmSendAttrib(x+width, y+height, 0.5f, 0.0f); + C3D_ImmSendAttrib( right, bottom, 0.0f, 0.0f); + C3D_ImmDrawEnd(); +} +void Rasterizer3DS::_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 ) { + VertexArray dscoords[4]= { + {Vector3( p_src_region.pos.x/p_tex_size.width, + p_src_region.pos.y/p_tex_size.height, 0), + Vector2( p_rect.pos.x, p_rect.pos.y )}, + + + {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), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y )}, + + {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), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height )}, + + {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), + Vector2( p_rect.pos.x,p_rect.pos.y+p_rect.size.height )} + }; + + VertexArray dscoords23[4]= { + {Vector3( 0, + 0, 0), + Vector2( p_rect.pos.x, p_rect.pos.y )}, + + + {Vector3(5, + 0, 0), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y )}, + + {Vector3( 0, + 5, 0), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height )}, + + {Vector3( 5, + 5, 0), + Vector2( p_rect.pos.x,p_rect.pos.y+p_rect.size.height )} + }; + + + if (p_flip_h) { + SWAP( dscoords[0], dscoords[1] ); + SWAP( dscoords[2], dscoords[3] ); + } + if (p_flip_v) { + SWAP( dscoords[1], dscoords[2] ); + SWAP( dscoords[0], dscoords[3] ); + } + + Vector3 coords[4]= { + + }; + + // void* vbo_data = linearAlloc(sizeof(dscoords)); + // memcpy(vbo_data, dscoords, sizeof(dscoords)); + // memcpy(vbo_data+sizeof(coords), texcoords, sizeof(texcoords)); + /* + C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); + AttrInfo_Init(attrInfo); + AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position + AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=color + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, dscoords, sizeof(VertexArray), 2, 0x10); + + C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, sizeof(dscoords));*/ +/* + C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP); + C3D_ImmSendAttrib(p_src_region.pos.x/p_tex_size.width, p_src_region.pos.y/p_tex_size.height, 0.5f, 0.0f); // v0=position + C3D_ImmSendAttrib(p_rect.pos.x, p_rect.pos.y, 0.0f, 0.0f); // v1=color + + C3D_ImmSendAttrib((p_src_region.pos.x+p_src_region.size.width)/p_tex_size.width, p_src_region.pos.y/p_tex_size.height, 0.5f, 0.0f); + C3D_ImmSendAttrib(p_rect.pos.x+p_rect.size.width, p_rect.pos.y, 0.0f, 0.0f); + + C3D_ImmSendAttrib((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.5f, 0.0f); + C3D_ImmSendAttrib(p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height, 0.0f, 0.0f); + + C3D_ImmSendAttrib(p_src_region.pos.x/p_tex_size.width, (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height, 0.5f, 0.0f); + C3D_ImmSendAttrib(p_rect.pos.x, p_rect.pos.y+p_rect.size.height, 0.0f, 0.0f); + + C3D_ImmDrawEnd();*/ + + // drawSpriteImmediate(0, 0, 0, 32, 32); + C3D_DrawArrays(GPU_TRIANGLES, 0, vertex_list_count); + + // Mtx_Identity(&modelView); + + // Mtx_Translate(&modelView, 0.0, 0.0, -2.5, true); + + // C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView); + + // Draw the triangle directly + + + // _draw_primitive(4,coords,0,0,texcoords); + + // linearFree(vbo_data); +} + +/* SHADER API */ + +/* SHADER API */ + +RID Rasterizer3DS::shader_create(VS::ShaderMode p_mode) { + + Shader *shader = memnew( Shader ); + shader->mode=p_mode; + shader->fragment_line=0; + shader->vertex_line=0; + shader->light_line=0; + RID rid = shader_owner.make_rid(shader); + + return rid; + +} + + + +void Rasterizer3DS::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); + shader->mode=p_mode; + +} +VS::ShaderMode Rasterizer3DS::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 Rasterizer3DS::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); + 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_vertex_ofs; + +} + + +String Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::shader_get_param_list(RID p_shader, List *p_param_list) const { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + +} + +/* COMMON MATERIAL API */ + + +RID Rasterizer3DS::material_create() { + + return material_owner.make_rid( memnew( Material ) ); +} + +void Rasterizer3DS::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 Rasterizer3DS::material_get_shader(RID p_material) const { + + Material *material = material_owner.get(p_material); + ERR_FAIL_COND_V(!material,RID()); + return material->shader; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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; +} + +/* MESH API */ + + +RID Rasterizer3DS::mesh_create() { + + + return mesh_owner.make_rid( memnew( Mesh ) ); +} + + +void Rasterizer3DS::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); + + Surface s; + + + s.format=0; + + for(int i=0;imorph_target_count; + s.morph_format=s.format; + + + Surface *surface = memnew( Surface ); + *surface=s; + + mesh->surfaces.push_back(surface); + + +} + + + +void Rasterizer3DS::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) { + + ERR_EXPLAIN("Dummy Rasterizer does not support custom surfaces. Running on wrong platform?"); + ERR_FAIL_V(); +} + +Array Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 ); + + Vector3Array arr = surface->data[VS::ARRAY_VERTEX]; + return arr.size(); + +} + +int Rasterizer3DS::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 ); + + IntArray arr = surface->data[VS::ARRAY_INDEX]; + return arr.size(); + +} +uint32_t Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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); + + memdelete( mesh->surfaces[p_index] ); + mesh->surfaces.remove(p_index); + +} +int Rasterizer3DS::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 Rasterizer3DS::mesh_get_aabb(RID p_mesh,RID p_skeleton) const { + + Mesh *mesh = mesh_owner.get( p_mesh ); + ERR_FAIL_COND_V(!mesh,AABB()); + + AABB aabb; + + for (int i=0;isurfaces.size();i++) { + + if (i==0) + aabb=mesh->surfaces[i]->aabb; + else + aabb.merge_with(mesh->surfaces[i]->aabb); + } + + return aabb; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::multimesh_create() { + + return multimesh_owner.make_rid( memnew( MultiMesh )); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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->elements[p_index].xform=p_transform; + +} +void Rasterizer3DS::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->elements[p_index].color=p_color; + +} + +RID Rasterizer3DS::multimesh_get_mesh(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.get(p_multimesh); + ERR_FAIL_COND_V(!multimesh,RID()); + + return multimesh->mesh; +} +AABB Rasterizer3DS::multimesh_get_aabb(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.get(p_multimesh); + ERR_FAIL_COND_V(!multimesh,AABB()); + + return multimesh->aabb; +} + +Transform Rasterizer3DS::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()); + + return multimesh->elements[p_index].xform; + +} +Color Rasterizer3DS::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()); + + return multimesh->elements[p_index].color; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::immediate_create() { + + Immediate *im = memnew( Immediate ); + return immediate_owner.make_rid(im); + +} + +void Rasterizer3DS::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){ + + +} +void Rasterizer3DS::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ + + +} +void Rasterizer3DS::immediate_normal(RID p_immediate,const Vector3& p_normal){ + + +} +void Rasterizer3DS::immediate_tangent(RID p_immediate,const Plane& p_tangent){ + + +} +void Rasterizer3DS::immediate_color(RID p_immediate,const Color& p_color){ + + +} +void Rasterizer3DS::immediate_uv(RID p_immediate,const Vector2& tex_uv){ + + +} +void Rasterizer3DS::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ + + +} + +void Rasterizer3DS::immediate_end(RID p_immediate){ + + +} +void Rasterizer3DS::immediate_clear(RID p_immediate) { + + +} + +AABB Rasterizer3DS::immediate_get_aabb(RID p_immediate) const { + + return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::particles_create() { + + Particles *particles = memnew( Particles ); + ERR_FAIL_COND_V(!particles,RID()); + return particles_owner.make_rid(particles); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::particles_set_emission_points(RID p_particles, const DVector& p_points) { + + Particles* particles = particles_owner.get( p_particles ); + ERR_FAIL_COND(!particles); + + particles->data.emission_points=p_points; +} + +DVector Rasterizer3DS::particles_get_emission_points(RID p_particles) const { + + Particles* particles = particles_owner.get( p_particles ); + ERR_FAIL_COND_V(!particles,DVector()); + + return particles->data.emission_points; + +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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;idata.color_phases[i].color.a<0.99) + particles->has_alpha=true; + } + +} + +Color Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::skeleton_create() { + + Skeleton *skeleton = memnew( Skeleton ); + ERR_FAIL_COND_V(!skeleton,RID()); + return skeleton_owner.make_rid( skeleton ); +} +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_create(VS::LightType p_type) { + + Light *light = memnew( Light ); + light->type=p_type; + return light_owner.make_rid(light); +} + +VS::LightType Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_get_projector(RID p_light) const { + + Light *light = light_owner.get(p_light); + ERR_FAIL_COND_V(!light,RID()); + return light->projector; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_set_operator(RID p_light,VS::LightOp p_op) { + + Light * light = light_owner.get( p_light ); + ERR_FAIL_COND(!light); + + +}; + +VS::LightOp Rasterizer3DS::light_get_operator(RID p_light) const { + + return VS::LightOp(0); +}; + +void Rasterizer3DS::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { + + +} + +VS::LightOmniShadowMode Rasterizer3DS::light_omni_get_shadow_mode(RID p_light) const{ + + return VS::LightOmniShadowMode(0); +} + +void Rasterizer3DS::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) { + + +} + +VS::LightDirectionalShadowMode Rasterizer3DS::light_directional_get_shadow_mode(RID p_light) const { + + return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; +} + +void Rasterizer3DS::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) { + + +} + +float Rasterizer3DS::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const { + + return 0; +} + + +AABB Rasterizer3DS::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 Rasterizer3DS::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; + + + return light_instance_owner.make_rid( light_instance ); +} +void Rasterizer3DS::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 Rasterizer3DS::light_instance_has_shadow(RID p_light_instance) const { + + return false; + +} + + +bool Rasterizer3DS::light_instance_assign_shadow(RID p_light_instance) { + + return false; + +} + + +Rasterizer::ShadowType Rasterizer3DS::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 Rasterizer3DS::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const { + + return SHADOW_NONE; +} +void Rasterizer3DS::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 Rasterizer3DS::light_instance_get_shadow_passes(RID p_light_instance) const { + + return 0; +} + +bool Rasterizer3DS::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { + + return false; +} + + +void Rasterizer3DS::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 Rasterizer3DS::shadow_clear_near() { + + +} + +bool Rasterizer3DS::shadow_allocate_near(RID p_light) { + + return false; +} + +bool Rasterizer3DS::shadow_allocate_far(RID p_light) { + + return false; +} + +/* PARTICLES INSTANCE */ + +RID Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::viewport_data_create() { + + return RID(); +} + +RID Rasterizer3DS::render_target_create(){ + + return RID(); + +} +void Rasterizer3DS::render_target_set_size(RID p_render_target, int p_width, int p_height){ + + +} +RID Rasterizer3DS::render_target_get_texture(RID p_render_target) const{ + + return RID(); + +} +bool Rasterizer3DS::render_target_renedered_in_frame(RID p_render_target){ + + return false; +} + + +void Rasterizer3DS::begin_frame() { + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C3D_RenderTargetClear(top_rt->target, C3D_CLEAR_ALL, clear_color_top, 0); + C3D_FrameDrawOn(top_rt->target); +} + +void Rasterizer3DS::capture_viewport(Image* r_capture) { + + +} + + +void Rasterizer3DS::clear_viewport(const Color& p_color) { + + clear_color_top = convert_color(&p_color); + // begin_frame(); +}; + +void Rasterizer3DS::set_viewport(const VS::ViewportRect& p_viewport) { + + + +} + +void Rasterizer3DS::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) { + + +} + + +void Rasterizer3DS::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) { + /* + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, (GPU_TEVSRC)0); + // C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + + C3D_TexBind(0, NULL);*/ + + // C3D_BindProgram(&program); + // _set_uniform(uLoc_modelView, Matrix32()); +}; + +void Rasterizer3DS::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) { + +} + +void Rasterizer3DS::set_camera(const Transform& p_world,const CameraMatrix& p_projection) { + + // _set_uniform(uLoc_projection, p_projection); +} + +void Rasterizer3DS::add_light( RID p_light_instance ) { + + + +} + + + + +void Rasterizer3DS::add_mesh( const RID& p_mesh, const InstanceData *p_data) { + + +} + +void Rasterizer3DS::add_multimesh( const RID& p_multimesh, const InstanceData *p_data){ + + + + +} + +void Rasterizer3DS::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ + + + +} + + + +void Rasterizer3DS::end_scene() { + // C3D_Flush(); + +} +void Rasterizer3DS::end_shadow_map() { + +} + + +void Rasterizer3DS::end_frame() { + + C3D_FrameEnd(0); + // C3D_FrameBufTransfer(&top_rt->target->frameBuf, top_rt->target->screen, top_rt->target->side, top_rt->target->transferFlags); + // gfxSwapBuffersGpu(); +} + +/* CANVAS API */ + + +void Rasterizer3DS::canvas_begin() { + // C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection); + + + + // Mtx_OrthoTilt(&projection, 0.0, 400.0, 240.0, 0.0, 0.0, 1.0, true); + + // C3D_BindProgram(&program); + + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection); + // drawSpriteImmediate(0, 0, 0, 32, 32); + /* + C3D_ImmDrawBegin(GPU_TRIANGLES); + C3D_ImmSendAttrib(200.0f, 200.0f, 0.5f, 0.0f); // v0=position + C3D_ImmSendAttrib(1.0f, 0.0f, 0.0f, 1.0f); // v1=color + + C3D_ImmSendAttrib(100.0f, 40.0f, 0.5f, 0.0f); + C3D_ImmSendAttrib(1.0f, 1.0f, 0.0f, 1.0f); + + C3D_ImmSendAttrib(300.0f, 40.0f, 0.5f, 0.0f); + C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 1.0f); + C3D_ImmDrawEnd();*/ +} +void Rasterizer3DS::canvas_disable_blending() { + + + +} + +void Rasterizer3DS::canvas_set_opacity(float p_opacity) { + + +} + +void Rasterizer3DS::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { + + +} + + +void Rasterizer3DS::canvas_begin_rect(const Matrix32& p_transform) { + // _set_uniform(uLoc_modelView, p_transform); +} + +void Rasterizer3DS::canvas_set_clip(bool p_clip, const Rect2& p_rect) { + + + + +} + +void Rasterizer3DS::canvas_end_rect() { + + +} + +void Rasterizer3DS::canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width) { + + + +} + +void Rasterizer3DS::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() ) { + + // sceGuEnable(GU_TEXTURE_2D); + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + // glActiveTexture(GL_TEXTURE0); + // glBindTexture( GL_TEXTURE_2D,texture->tex_id ); +/* + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR); + C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + + C3D_TexBind(0, &texture->texture);*/ + + 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 { + + WARN_PRINT("p_texture is not valid"); + + // sceGuDisable(GU_TEXTURE_2D); + // _draw_quad( p_rect ); + + } + +} +void Rasterizer3DS::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) { + + +} +void Rasterizer3DS::canvas_draw_primitive(const Vector& p_points, const Vector& p_colors,const Vector& p_uvs, RID p_texture,float p_width) { + + + +} + + +void Rasterizer3DS::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) { + + + +} + +void Rasterizer3DS::canvas_set_transform(const Matrix32& p_transform) { + + +} + +/* ENVIRONMENT */ + +RID Rasterizer3DS::environment_create() { + + Environment * env = memnew( Environment ); + return environment_owner.make_rid(env); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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]; + +} + + +RID Rasterizer3DS::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void Rasterizer3DS::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + + +/*MISC*/ + +bool Rasterizer3DS::is_texture(const RID& p_rid) const { + + return texture_owner.owns(p_rid); +} +bool Rasterizer3DS::is_material(const RID& p_rid) const { + + return material_owner.owns(p_rid); +} +bool Rasterizer3DS::is_mesh(const RID& p_rid) const { + + return mesh_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_immediate(const RID& p_rid) const { + + return immediate_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_multimesh(const RID& p_rid) const { + + return multimesh_owner.owns(p_rid); +} +bool Rasterizer3DS::is_particles(const RID &p_beam) const { + + return particles_owner.owns(p_beam); +} + +bool Rasterizer3DS::is_light(const RID& p_rid) const { + + return light_owner.owns(p_rid); +} +bool Rasterizer3DS::is_light_instance(const RID& p_rid) const { + + return light_instance_owner.owns(p_rid); +} +bool Rasterizer3DS::is_particles_instance(const RID& p_rid) const { + + return particles_instance_owner.owns(p_rid); +} +bool Rasterizer3DS::is_skeleton(const RID& p_rid) const { + + return skeleton_owner.owns(p_rid); +} +bool Rasterizer3DS::is_environment(const RID& p_rid) const { + + return environment_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_shader(const RID& p_rid) const { + + return false; +} + +void Rasterizer3DS::free(const RID& p_rid) { + + if (texture_owner.owns(p_rid)) { + + // delete the texture + Texture *texture = texture_owner.get(p_rid); + 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 ); + material_owner.free(p_rid); + memdelete(material); + + } else if (mesh_owner.owns(p_rid)) { + + Mesh *mesh = mesh_owner.get(p_rid); + + for (int i=0;isurfaces.size();i++) { + + memdelete( mesh->surfaces[i] ); + }; + + mesh->surfaces.clear(); + mesh_owner.free(p_rid); + memdelete(mesh); + + } else if (multimesh_owner.owns(p_rid)) { + + MultiMesh *multimesh = multimesh_owner.get(p_rid); + multimesh_owner.free(p_rid); + memdelete(multimesh); + + } else if (immediate_owner.owns(p_rid)) { + + Immediate *immediate = immediate_owner.get(p_rid); + immediate_owner.free(p_rid); + memdelete(immediate); + + } else if (particles_owner.owns(p_rid)) { + + Particles *particles = particles_owner.get(p_rid); + particles_owner.free(p_rid); + memdelete(particles); + } else if (particles_instance_owner.owns(p_rid)) { + + ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); + particles_instance_owner.free(p_rid); + memdelete(particles_isntance); + + } else if (skeleton_owner.owns(p_rid)) { + + Skeleton *skeleton = skeleton_owner.get( p_rid ); + skeleton_owner.free(p_rid); + memdelete(skeleton); + + } else if (light_owner.owns(p_rid)) { + + Light *light = light_owner.get( p_rid ); + light_owner.free(p_rid); + memdelete(light); + + } else if (light_instance_owner.owns(p_rid)) { + + LightInstance *light_instance = light_instance_owner.get( p_rid ); + light_instance_owner.free(p_rid); + memdelete( light_instance ); + + + } else if (environment_owner.owns(p_rid)) { + + Environment *env = environment_owner.get( p_rid ); + environment_owner.free(p_rid); + memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + + }; +} + + +void Rasterizer3DS::custom_shade_model_set_shader(int p_model, RID p_shader) { + + +}; + +RID Rasterizer3DS::custom_shade_model_get_shader(int p_model) const { + + return RID(); +}; + +void Rasterizer3DS::custom_shade_model_set_name(int p_model, const String& p_name) { + +}; + +String Rasterizer3DS::custom_shade_model_get_name(int p_model) const { + + return String(); +}; + +void Rasterizer3DS::custom_shade_model_set_param_info(int p_model, const List& p_info) { + +}; + +void Rasterizer3DS::custom_shade_model_get_param_info(int p_model, List* p_info) const { + +}; + + + +void Rasterizer3DS::init() { + C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); + + top_rt = memnew(RenderTarget); + + top_rt->target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(top_rt->target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + + + simple_2ds = DVLB_ParseFile((u32*)shader_builtin_simple_2d, sizeof(shader_builtin_simple_2d)); + shaderProgramInit(&program); + shaderProgramSetVsh(&program, &simple_2ds->DVLE[0]); + C3D_BindProgram(&program); + + uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection"); + // uLoc_modelView = shaderInstanceGetUniformLocation(program.vertexShader, "modelView"); + + // Configure attributes for use with the vertex shader + C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); + AttrInfo_Init(attrInfo); + AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position + // AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=color + AttrInfo_AddFixed(attrInfo, 1); + + // Mtx_PerspTilt(&projection, C3D_AngleFromDegrees(80.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, false); + Mtx_OrthoTilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0, true); + /* + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0, (GPU_TEVSRC)0); + C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);*/ + + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); + // Mtx_OrthoTilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0, true); + + + void* vbo_data = linearAlloc(sizeof(vertex_list)); + memcpy(vbo_data, vertex_list, sizeof(vertex_list)); + + // Configure buffers + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, vbo_data, sizeof(vertex3ds), 1, 0x0); + + C3D_FixedAttribSet(1, 1.0, 1.0, 1.0, 1.0); + printf("Rasterizer::Init OK!\n"); +} + +void Rasterizer3DS::finish() { + + +} + +int Rasterizer3DS::get_render_info(VS::RenderInfo p_info) { + + return 0; +} + +bool Rasterizer3DS::needs_to_draw_next_frame() const { + + return false; +} + + +bool Rasterizer3DS::has_feature(VS::Features p_feature) const { + + return false; + +} + + +Rasterizer3DS::Rasterizer3DS() { + +}; + +Rasterizer3DS::~Rasterizer3DS() { + shaderProgramFree(&program); + DVLB_Free(simple_2ds); + C3D_Fini(); +}; + diff --git a/platform/3ds/rasterizer_3ds Kopie.cpp b/platform/3ds/rasterizer_3ds Kopie.cpp new file mode 100644 index 00000000..c6d92e1e --- /dev/null +++ b/platform/3ds/rasterizer_3ds Kopie.cpp @@ -0,0 +1,2268 @@ +/*************************************************************************/ +/* rasterizer_3ds.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 "rasterizer_3ds.h" +#include "shaders/simple_3d.h" +#include "shaders/simple_2d.h" + +static const vertex3ds vertex_list[] = +{ + { 200.0f, 200.0f, 0.5f }, + { 100.0f, 40.0f, 0.5f }, + { 300.0f, 40.0f, 0.5f }, +}; + +#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0])) + +#define DISPLAY_TRANSFER_FLAGS \ + (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \ + GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \ + GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) + + +#define TEXTURE_TRANSFER_FLAGS (GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | \ + GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) + + +void _set_uniform(int uniform_location, const Matrix32& p_transform) +{ + const Matrix32& tr = p_transform; + + C3D_Mtx mtx; + + float matrix[16] = { /* build a 16x16 matrix */ + tr.elements[2][0], 0, tr.elements[1][0], tr.elements[0][0], + tr.elements[2][1], 0, tr.elements[1][1], tr.elements[0][1], + 0, 1, 0, 0, + 1, 0, 0, 0, + }; + + memcpy(mtx.m, matrix, sizeof(matrix)); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mtx); +} + +void _set_uniform(int uniform_location, const CameraMatrix& p_matrix) +{ + // Swap X/Y axis due to 3DS screens being sideways + // and adjust clipping range from [-1, 1] to [-1, 0] + float m[16] = { + 0, -1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0.5, 0, + 0, 0, -0.5, 1, + }; + + CameraMatrix p = *reinterpret_cast(m) * p_matrix; + + C3D_Mtx mtx; + float *to = mtx.m; + const float *from = reinterpret_cast(p.matrix); + + + to[0] = from[12]; + to[1] = from[8]; + to[2] = from[4]; + to[3] = from[0]; + to[4] = from[13]; + to[5] = from[9]; + to[6] = from[5]; + to[7] = from[1]; + to[8] = from[14]; + to[9] = from[10]; + to[10] = from[6]; + to[11] = from[2]; + to[12] = from[15]; + to[13] = from[11]; + to[14] = from[7]; + to[15] = from[3]; + + + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mtx); +} + +/* TEXTURE API */ + + +RID Rasterizer3DS::texture_create() { + + Texture *texture = memnew(Texture); + ERR_FAIL_COND_V(!texture,RID()); + return texture_owner.make_rid( texture ); + +} + +void Rasterizer3DS::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { + + + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + C3D_TexInit(&texture->texture, p_width, p_height, GPU_RGBA8); + texture->width=p_width; + texture->height=p_height; + texture->format=p_format; + texture->flags=p_flags; +} + +void Rasterizer3DS::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->format != p_image.get_format() ); + + texture->image[p_cube_side]=p_image; + + DVector d = p_image.get_data(); + const u32* buffer = reinterpret_cast(d.read().ptr()); + u8 * gpuBuffer = (u8 *)linearAlloc(texture->width * texture->height * 4); + + u32 * src = (u32 *)buffer; + u32 * dst = (u32 *)gpuBuffer; + + for (unsigned y = 0; y < texture->height; y++) + { + for (unsigned x = 0; x < texture->width; x++) + { + u32 clr = *src; + // *dst = __builtin_bswap32(clr); + *dst = 0x0; + } + dst += 4; + } + + GSPGPU_FlushDataCache((u32 *)gpuBuffer, texture->width * texture->height * 4); + + C3D_SyncDisplayTransfer((u32 *)gpuBuffer, GX_BUFFER_DIM(texture->width, texture->height), (u32 *)texture->texture.data, GX_BUFFER_DIM(texture->width, texture->height), TEXTURE_TRANSFER_FLAGS); + + // gspWaitForPPF(); + C3D_TexSetFilter(&texture->texture, GPU_LINEAR, GPU_NEAREST); + C3D_TexBind(0, &texture->texture); + + linearFree(gpuBuffer); + + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, (GPU_TEVSRC)0, (GPU_TEVSRC)0); + C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + + +} + +Image Rasterizer3DS::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()); + + return texture->image[p_cube_side]; +} + +void Rasterizer3DS::texture_set_flags(RID p_texture,uint32_t p_flags) { + + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; + texture->flags=p_flags|cube; // can't remove a cube from being a cube + +} +uint32_t Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::texture_get_height(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,0); + + return texture->height; +} + +bool Rasterizer3DS::texture_has_alpha(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,0); + + return false; + +} + +void Rasterizer3DS::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 Rasterizer3DS::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const { + + +} + +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); + + // int type = prim_type[p_points - 1]; + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, p_vertices, sizeof(Vector3), 2, 0x10); + + C3D_DrawArrays(GPU_TRIANGLE_FAN, 0, 4); +}; +//--------------------------------------------------------------------------------- +static void drawSpriteImmediate( size_t idx, int x, int y, int width, int height ) { +//--------------------------------------------------------------------------------- + + float left = 0;//images[image].left; + float right = 0.5;//images[image].right; + float top = 0;//images[image].top; + float bottom = 0.5;//images[image].bottom; + + if (idx > 500) + return; + + // Draw a textured quad directly + C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP); + C3D_ImmSendAttrib(x, y, 0.5f, 0.0f); // v0=position + C3D_ImmSendAttrib( left, top, 0.0f, 0.0f); + + C3D_ImmSendAttrib(x, y+height, 0.5f, 0.0f); + C3D_ImmSendAttrib( left, bottom, 0.0f, 0.0f); + + C3D_ImmSendAttrib(x+width, y, 0.5f, 0.0f); + C3D_ImmSendAttrib( right, top, 0.0f, 0.0f); + + C3D_ImmSendAttrib(x+width, y+height, 0.5f, 0.0f); + C3D_ImmSendAttrib( right, bottom, 0.0f, 0.0f); + C3D_ImmDrawEnd(); +} +void Rasterizer3DS::_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 ) { + VertexArray dscoords[4]= { + {Vector3( p_src_region.pos.x/p_tex_size.width, + p_src_region.pos.y/p_tex_size.height, 0), + Vector2( p_rect.pos.x, p_rect.pos.y )}, + + + {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), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y )}, + + {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), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height )}, + + {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), + Vector2( p_rect.pos.x,p_rect.pos.y+p_rect.size.height )} + }; + + VertexArray dscoords23[4]= { + {Vector3( 0, + 0, 0), + Vector2( p_rect.pos.x, p_rect.pos.y )}, + + + {Vector3(5, + 0, 0), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y )}, + + {Vector3( 0, + 5, 0), + Vector2( p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height )}, + + {Vector3( 5, + 5, 0), + Vector2( p_rect.pos.x,p_rect.pos.y+p_rect.size.height )} + }; + + + if (p_flip_h) { + SWAP( dscoords[0], dscoords[1] ); + SWAP( dscoords[2], dscoords[3] ); + } + if (p_flip_v) { + SWAP( dscoords[1], dscoords[2] ); + SWAP( dscoords[0], dscoords[3] ); + } + + Vector3 coords[4]= { + + }; + + // void* vbo_data = linearAlloc(sizeof(dscoords)); + // memcpy(vbo_data, dscoords, sizeof(dscoords)); + // memcpy(vbo_data+sizeof(coords), texcoords, sizeof(texcoords)); + /* + C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); + AttrInfo_Init(attrInfo); + AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position + AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=color + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, dscoords, sizeof(VertexArray), 2, 0x10); + + C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, sizeof(dscoords));*/ +/* + C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP); + C3D_ImmSendAttrib(p_src_region.pos.x/p_tex_size.width, p_src_region.pos.y/p_tex_size.height, 0.5f, 0.0f); // v0=position + C3D_ImmSendAttrib(p_rect.pos.x, p_rect.pos.y, 0.0f, 0.0f); // v1=color + + C3D_ImmSendAttrib((p_src_region.pos.x+p_src_region.size.width)/p_tex_size.width, p_src_region.pos.y/p_tex_size.height, 0.5f, 0.0f); + C3D_ImmSendAttrib(p_rect.pos.x+p_rect.size.width, p_rect.pos.y, 0.0f, 0.0f); + + C3D_ImmSendAttrib((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.5f, 0.0f); + C3D_ImmSendAttrib(p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height, 0.0f, 0.0f); + + C3D_ImmSendAttrib(p_src_region.pos.x/p_tex_size.width, (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height, 0.5f, 0.0f); + C3D_ImmSendAttrib(p_rect.pos.x, p_rect.pos.y+p_rect.size.height, 0.0f, 0.0f); + + C3D_ImmDrawEnd();*/ + + // drawSpriteImmediate(0, 0, 0, 32, 32); + C3D_DrawArrays(GPU_TRIANGLES, 0, vertex_list_count); + + // Mtx_Identity(&modelView); + + // Mtx_Translate(&modelView, 0.0, 0.0, -2.5, true); + + // C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView); + + // Draw the triangle directly + + + // _draw_primitive(4,coords,0,0,texcoords); + + // linearFree(vbo_data); +} + +/* SHADER API */ + +/* SHADER API */ + +RID Rasterizer3DS::shader_create(VS::ShaderMode p_mode) { + + Shader *shader = memnew( Shader ); + shader->mode=p_mode; + shader->fragment_line=0; + shader->vertex_line=0; + shader->light_line=0; + RID rid = shader_owner.make_rid(shader); + + return rid; + +} + + + +void Rasterizer3DS::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); + shader->mode=p_mode; + +} +VS::ShaderMode Rasterizer3DS::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 Rasterizer3DS::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); + 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_vertex_ofs; + +} + + +String Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::shader_get_param_list(RID p_shader, List *p_param_list) const { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + +} + +/* COMMON MATERIAL API */ + + +RID Rasterizer3DS::material_create() { + + return material_owner.make_rid( memnew( Material ) ); +} + +void Rasterizer3DS::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 Rasterizer3DS::material_get_shader(RID p_material) const { + + Material *material = material_owner.get(p_material); + ERR_FAIL_COND_V(!material,RID()); + return material->shader; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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; +} + +/* MESH API */ + + +RID Rasterizer3DS::mesh_create() { + + + return mesh_owner.make_rid( memnew( Mesh ) ); +} + + +void Rasterizer3DS::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); + + Surface s; + + + s.format=0; + + for(int i=0;imorph_target_count; + s.morph_format=s.format; + + + Surface *surface = memnew( Surface ); + *surface=s; + + mesh->surfaces.push_back(surface); + + +} + + + +void Rasterizer3DS::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) { + + ERR_EXPLAIN("Dummy Rasterizer does not support custom surfaces. Running on wrong platform?"); + ERR_FAIL_V(); +} + +Array Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 ); + + Vector3Array arr = surface->data[VS::ARRAY_VERTEX]; + return arr.size(); + +} + +int Rasterizer3DS::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 ); + + IntArray arr = surface->data[VS::ARRAY_INDEX]; + return arr.size(); + +} +uint32_t Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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); + + memdelete( mesh->surfaces[p_index] ); + mesh->surfaces.remove(p_index); + +} +int Rasterizer3DS::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 Rasterizer3DS::mesh_get_aabb(RID p_mesh,RID p_skeleton) const { + + Mesh *mesh = mesh_owner.get( p_mesh ); + ERR_FAIL_COND_V(!mesh,AABB()); + + AABB aabb; + + for (int i=0;isurfaces.size();i++) { + + if (i==0) + aabb=mesh->surfaces[i]->aabb; + else + aabb.merge_with(mesh->surfaces[i]->aabb); + } + + return aabb; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::multimesh_create() { + + return multimesh_owner.make_rid( memnew( MultiMesh )); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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->elements[p_index].xform=p_transform; + +} +void Rasterizer3DS::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->elements[p_index].color=p_color; + +} + +RID Rasterizer3DS::multimesh_get_mesh(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.get(p_multimesh); + ERR_FAIL_COND_V(!multimesh,RID()); + + return multimesh->mesh; +} +AABB Rasterizer3DS::multimesh_get_aabb(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.get(p_multimesh); + ERR_FAIL_COND_V(!multimesh,AABB()); + + return multimesh->aabb; +} + +Transform Rasterizer3DS::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()); + + return multimesh->elements[p_index].xform; + +} +Color Rasterizer3DS::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()); + + return multimesh->elements[p_index].color; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::immediate_create() { + + Immediate *im = memnew( Immediate ); + return immediate_owner.make_rid(im); + +} + +void Rasterizer3DS::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){ + + +} +void Rasterizer3DS::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ + + +} +void Rasterizer3DS::immediate_normal(RID p_immediate,const Vector3& p_normal){ + + +} +void Rasterizer3DS::immediate_tangent(RID p_immediate,const Plane& p_tangent){ + + +} +void Rasterizer3DS::immediate_color(RID p_immediate,const Color& p_color){ + + +} +void Rasterizer3DS::immediate_uv(RID p_immediate,const Vector2& tex_uv){ + + +} +void Rasterizer3DS::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ + + +} + +void Rasterizer3DS::immediate_end(RID p_immediate){ + + +} +void Rasterizer3DS::immediate_clear(RID p_immediate) { + + +} + +AABB Rasterizer3DS::immediate_get_aabb(RID p_immediate) const { + + return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::particles_create() { + + Particles *particles = memnew( Particles ); + ERR_FAIL_COND_V(!particles,RID()); + return particles_owner.make_rid(particles); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::particles_set_emission_points(RID p_particles, const DVector& p_points) { + + Particles* particles = particles_owner.get( p_particles ); + ERR_FAIL_COND(!particles); + + particles->data.emission_points=p_points; +} + +DVector Rasterizer3DS::particles_get_emission_points(RID p_particles) const { + + Particles* particles = particles_owner.get( p_particles ); + ERR_FAIL_COND_V(!particles,DVector()); + + return particles->data.emission_points; + +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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;idata.color_phases[i].color.a<0.99) + particles->has_alpha=true; + } + +} + +Color Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::skeleton_create() { + + Skeleton *skeleton = memnew( Skeleton ); + ERR_FAIL_COND_V(!skeleton,RID()); + return skeleton_owner.make_rid( skeleton ); +} +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_create(VS::LightType p_type) { + + Light *light = memnew( Light ); + light->type=p_type; + return light_owner.make_rid(light); +} + +VS::LightType Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_get_projector(RID p_light) const { + + Light *light = light_owner.get(p_light); + ERR_FAIL_COND_V(!light,RID()); + return light->projector; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_set_operator(RID p_light,VS::LightOp p_op) { + + Light * light = light_owner.get( p_light ); + ERR_FAIL_COND(!light); + + +}; + +VS::LightOp Rasterizer3DS::light_get_operator(RID p_light) const { + + return VS::LightOp(0); +}; + +void Rasterizer3DS::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { + + +} + +VS::LightOmniShadowMode Rasterizer3DS::light_omni_get_shadow_mode(RID p_light) const{ + + return VS::LightOmniShadowMode(0); +} + +void Rasterizer3DS::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) { + + +} + +VS::LightDirectionalShadowMode Rasterizer3DS::light_directional_get_shadow_mode(RID p_light) const { + + return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; +} + +void Rasterizer3DS::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) { + + +} + +float Rasterizer3DS::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const { + + return 0; +} + + +AABB Rasterizer3DS::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 Rasterizer3DS::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; + + + return light_instance_owner.make_rid( light_instance ); +} +void Rasterizer3DS::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 Rasterizer3DS::light_instance_has_shadow(RID p_light_instance) const { + + return false; + +} + + +bool Rasterizer3DS::light_instance_assign_shadow(RID p_light_instance) { + + return false; + +} + + +Rasterizer::ShadowType Rasterizer3DS::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 Rasterizer3DS::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const { + + return SHADOW_NONE; +} +void Rasterizer3DS::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 Rasterizer3DS::light_instance_get_shadow_passes(RID p_light_instance) const { + + return 0; +} + +bool Rasterizer3DS::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { + + return false; +} + + +void Rasterizer3DS::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 Rasterizer3DS::shadow_clear_near() { + + +} + +bool Rasterizer3DS::shadow_allocate_near(RID p_light) { + + return false; +} + +bool Rasterizer3DS::shadow_allocate_far(RID p_light) { + + return false; +} + +/* PARTICLES INSTANCE */ + +RID Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::viewport_data_create() { + + return RID(); +} + +RID Rasterizer3DS::render_target_create(){ + + return RID(); + +} +void Rasterizer3DS::render_target_set_size(RID p_render_target, int p_width, int p_height){ + + +} +RID Rasterizer3DS::render_target_get_texture(RID p_render_target) const{ + + return RID(); + +} +bool Rasterizer3DS::render_target_renedered_in_frame(RID p_render_target){ + + return false; +} + + +void Rasterizer3DS::begin_frame() { + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C3D_RenderTargetClear(top_rt->target, C3D_CLEAR_ALL, clear_color_top, 0); + C3D_FrameDrawOn(top_rt->target); +} + +void Rasterizer3DS::capture_viewport(Image* r_capture) { + + +} + + +void Rasterizer3DS::clear_viewport(const Color& p_color) { + + clear_color_top = convert_color(&p_color); + // begin_frame(); +}; + +void Rasterizer3DS::set_viewport(const VS::ViewportRect& p_viewport) { + + + +} + +void Rasterizer3DS::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) { + + +} + + +void Rasterizer3DS::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) { + /* + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, (GPU_TEVSRC)0); + // C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + + C3D_TexBind(0, NULL);*/ + + // C3D_BindProgram(&program); + // _set_uniform(uLoc_modelView, Matrix32()); +}; + +void Rasterizer3DS::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) { + +} + +void Rasterizer3DS::set_camera(const Transform& p_world,const CameraMatrix& p_projection) { + + // _set_uniform(uLoc_projection, p_projection); +} + +void Rasterizer3DS::add_light( RID p_light_instance ) { + + + +} + + + + +void Rasterizer3DS::add_mesh( const RID& p_mesh, const InstanceData *p_data) { + + +} + +void Rasterizer3DS::add_multimesh( const RID& p_multimesh, const InstanceData *p_data){ + + + + +} + +void Rasterizer3DS::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ + + + +} + + + +void Rasterizer3DS::end_scene() { + // C3D_Flush(); + +} +void Rasterizer3DS::end_shadow_map() { + +} + + +void Rasterizer3DS::end_frame() { + + C3D_FrameEnd(0); + // C3D_FrameBufTransfer(&top_rt->target->frameBuf, top_rt->target->screen, top_rt->target->side, top_rt->target->transferFlags); + // gfxSwapBuffersGpu(); +} + +/* CANVAS API */ + + +void Rasterizer3DS::canvas_begin() { + // C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection); + + + + // Mtx_OrthoTilt(&projection, 0.0, 400.0, 240.0, 0.0, 0.0, 1.0, true); + + // C3D_BindProgram(&program); + + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection); + // drawSpriteImmediate(0, 0, 0, 32, 32); + /* + C3D_ImmDrawBegin(GPU_TRIANGLES); + C3D_ImmSendAttrib(200.0f, 200.0f, 0.5f, 0.0f); // v0=position + C3D_ImmSendAttrib(1.0f, 0.0f, 0.0f, 1.0f); // v1=color + + C3D_ImmSendAttrib(100.0f, 40.0f, 0.5f, 0.0f); + C3D_ImmSendAttrib(1.0f, 1.0f, 0.0f, 1.0f); + + C3D_ImmSendAttrib(300.0f, 40.0f, 0.5f, 0.0f); + C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 1.0f); + C3D_ImmDrawEnd();*/ +} +void Rasterizer3DS::canvas_disable_blending() { + + + +} + +void Rasterizer3DS::canvas_set_opacity(float p_opacity) { + + +} + +void Rasterizer3DS::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { + + +} + + +void Rasterizer3DS::canvas_begin_rect(const Matrix32& p_transform) { + // _set_uniform(uLoc_modelView, p_transform); +} + +void Rasterizer3DS::canvas_set_clip(bool p_clip, const Rect2& p_rect) { + + + + +} + +void Rasterizer3DS::canvas_end_rect() { + + +} + +void Rasterizer3DS::canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width) { + + + +} + +void Rasterizer3DS::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() ) { + + // sceGuEnable(GU_TEXTURE_2D); + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + // glActiveTexture(GL_TEXTURE0); + // glBindTexture( GL_TEXTURE_2D,texture->tex_id ); +/* + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR); + C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + + C3D_TexBind(0, &texture->texture);*/ + + 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 { + + WARN_PRINT("p_texture is not valid"); + + // sceGuDisable(GU_TEXTURE_2D); + // _draw_quad( p_rect ); + + } + +} +void Rasterizer3DS::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) { + + +} +void Rasterizer3DS::canvas_draw_primitive(const Vector& p_points, const Vector& p_colors,const Vector& p_uvs, RID p_texture,float p_width) { + + + +} + + +void Rasterizer3DS::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) { + + + +} + +void Rasterizer3DS::canvas_set_transform(const Matrix32& p_transform) { + + +} + +/* ENVIRONMENT */ + +RID Rasterizer3DS::environment_create() { + + Environment * env = memnew( Environment ); + return environment_owner.make_rid(env); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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]; + +} + + +RID Rasterizer3DS::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void Rasterizer3DS::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + + +/*MISC*/ + +bool Rasterizer3DS::is_texture(const RID& p_rid) const { + + return texture_owner.owns(p_rid); +} +bool Rasterizer3DS::is_material(const RID& p_rid) const { + + return material_owner.owns(p_rid); +} +bool Rasterizer3DS::is_mesh(const RID& p_rid) const { + + return mesh_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_immediate(const RID& p_rid) const { + + return immediate_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_multimesh(const RID& p_rid) const { + + return multimesh_owner.owns(p_rid); +} +bool Rasterizer3DS::is_particles(const RID &p_beam) const { + + return particles_owner.owns(p_beam); +} + +bool Rasterizer3DS::is_light(const RID& p_rid) const { + + return light_owner.owns(p_rid); +} +bool Rasterizer3DS::is_light_instance(const RID& p_rid) const { + + return light_instance_owner.owns(p_rid); +} +bool Rasterizer3DS::is_particles_instance(const RID& p_rid) const { + + return particles_instance_owner.owns(p_rid); +} +bool Rasterizer3DS::is_skeleton(const RID& p_rid) const { + + return skeleton_owner.owns(p_rid); +} +bool Rasterizer3DS::is_environment(const RID& p_rid) const { + + return environment_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_shader(const RID& p_rid) const { + + return false; +} + +void Rasterizer3DS::free(const RID& p_rid) { + + if (texture_owner.owns(p_rid)) { + + // delete the texture + Texture *texture = texture_owner.get(p_rid); + 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 ); + material_owner.free(p_rid); + memdelete(material); + + } else if (mesh_owner.owns(p_rid)) { + + Mesh *mesh = mesh_owner.get(p_rid); + + for (int i=0;isurfaces.size();i++) { + + memdelete( mesh->surfaces[i] ); + }; + + mesh->surfaces.clear(); + mesh_owner.free(p_rid); + memdelete(mesh); + + } else if (multimesh_owner.owns(p_rid)) { + + MultiMesh *multimesh = multimesh_owner.get(p_rid); + multimesh_owner.free(p_rid); + memdelete(multimesh); + + } else if (immediate_owner.owns(p_rid)) { + + Immediate *immediate = immediate_owner.get(p_rid); + immediate_owner.free(p_rid); + memdelete(immediate); + + } else if (particles_owner.owns(p_rid)) { + + Particles *particles = particles_owner.get(p_rid); + particles_owner.free(p_rid); + memdelete(particles); + } else if (particles_instance_owner.owns(p_rid)) { + + ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); + particles_instance_owner.free(p_rid); + memdelete(particles_isntance); + + } else if (skeleton_owner.owns(p_rid)) { + + Skeleton *skeleton = skeleton_owner.get( p_rid ); + skeleton_owner.free(p_rid); + memdelete(skeleton); + + } else if (light_owner.owns(p_rid)) { + + Light *light = light_owner.get( p_rid ); + light_owner.free(p_rid); + memdelete(light); + + } else if (light_instance_owner.owns(p_rid)) { + + LightInstance *light_instance = light_instance_owner.get( p_rid ); + light_instance_owner.free(p_rid); + memdelete( light_instance ); + + + } else if (environment_owner.owns(p_rid)) { + + Environment *env = environment_owner.get( p_rid ); + environment_owner.free(p_rid); + memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + + }; +} + + +void Rasterizer3DS::custom_shade_model_set_shader(int p_model, RID p_shader) { + + +}; + +RID Rasterizer3DS::custom_shade_model_get_shader(int p_model) const { + + return RID(); +}; + +void Rasterizer3DS::custom_shade_model_set_name(int p_model, const String& p_name) { + +}; + +String Rasterizer3DS::custom_shade_model_get_name(int p_model) const { + + return String(); +}; + +void Rasterizer3DS::custom_shade_model_set_param_info(int p_model, const List& p_info) { + +}; + +void Rasterizer3DS::custom_shade_model_get_param_info(int p_model, List* p_info) const { + +}; + + + +void Rasterizer3DS::init() { + C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); + + top_rt = memnew(RenderTarget); + + top_rt->target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(top_rt->target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + + + simple_2ds = DVLB_ParseFile((u32*)shader_builtin_simple_2d, sizeof(shader_builtin_simple_2d)); + shaderProgramInit(&program); + shaderProgramSetVsh(&program, &simple_2ds->DVLE[0]); + C3D_BindProgram(&program); + + uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection"); + // uLoc_modelView = shaderInstanceGetUniformLocation(program.vertexShader, "modelView"); + + // Configure attributes for use with the vertex shader + C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); + AttrInfo_Init(attrInfo); + AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position + // AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=color + AttrInfo_AddFixed(attrInfo, 1); + + // Mtx_PerspTilt(&projection, C3D_AngleFromDegrees(80.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, false); + Mtx_OrthoTilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0, true); + /* + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0, (GPU_TEVSRC)0); + C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);*/ + + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); + // Mtx_OrthoTilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0, true); + + + void* vbo_data = linearAlloc(sizeof(vertex_list)); + memcpy(vbo_data, vertex_list, sizeof(vertex_list)); + + // Configure buffers + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, vbo_data, sizeof(vertex3ds), 1, 0x0); + + C3D_FixedAttribSet(1, 1.0, 1.0, 1.0, 1.0); + printf("Rasterizer::Init OK!\n"); +} + +void Rasterizer3DS::finish() { + + +} + +int Rasterizer3DS::get_render_info(VS::RenderInfo p_info) { + + return 0; +} + +bool Rasterizer3DS::needs_to_draw_next_frame() const { + + return false; +} + + +bool Rasterizer3DS::has_feature(VS::Features p_feature) const { + + return false; + +} + + +Rasterizer3DS::Rasterizer3DS() { + +}; + +Rasterizer3DS::~Rasterizer3DS() { + shaderProgramFree(&program); + DVLB_Free(simple_2ds); + C3D_Fini(); +}; + diff --git a/platform/3ds/rasterizer_3ds Kopie.h b/platform/3ds/rasterizer_3ds Kopie.h new file mode 100644 index 00000000..123edd68 --- /dev/null +++ b/platform/3ds/rasterizer_3ds Kopie.h @@ -0,0 +1,818 @@ +/*************************************************************************/ +/* rasterizer_3ds.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_3DS_H +#define RASTERIZER_3DS_H + +#ifdef __3DS__ +extern "C" { +#include <3ds/types.h> +#include <3ds/gpu/gpu.h> +#include <3ds/gfx.h> +#include <3ds/gpu/gx.h> +#include <3ds/gpu/shaderProgram.h> +#include <3ds/allocator/linear.h> +} +#undef __3DS__ +#include +#define __3DS__ +#endif + +#include "servers/visual/rasterizer.h" + +#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 "servers/visual/particle_system_sw.h" + +static uint32_t convert_color(const Color* ic) { + + uint32_t c=(uint8_t)(ic->r*255); + c<<=8; + c|=(uint8_t)(ic->g*255); + c<<=8; + c|=(uint8_t)(ic->b*255); + c<<=8; + c|=(uint8_t)(ic->a*255); + + return c; +} +typedef struct { float position[3]; float texcoord[2]; float normal[3]; } vertex3ds; + +typedef struct { + Vector3 position; + Vector2 texcoord; +} VertexArray; + +class Rasterizer3DS : public Rasterizer { + + + void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_flip_h,bool p_flip_v ); + DVLB_s* simple_3ds; + DVLB_s* simple_2ds; + shaderProgram_s program; + + C3D_Mtx projection; + C3D_Mtx modelView; + int uLoc_projection, uLoc_modelView; + + struct Texture { + + uint32_t flags; + int width,height; + Image::Format format; + Image image[6]; + C3D_Tex texture; + Texture() { + + flags=width=height=0; + format=Image::FORMAT_GRAYSCALE; + } + + ~Texture() { + + } + }; + + mutable RID_Owner texture_owner; + + struct RenderTarget { + C3D_RenderTarget* target; + }; + + mutable RID_Owner render_target_owner; + uint32_t clear_color_top; + + struct Shader { + + String vertex_code; + String fragment_code; + String light_code; + VS::ShaderMode mode; + Map params; + int fragment_line; + int vertex_line; + int light_line; + bool valid; + bool has_alpha; + bool use_world_transform; + + }; + + mutable RID_Owner shader_owner; + + + struct Material { + + bool flags[VS::MATERIAL_FLAG_MAX]; + + VS::MaterialDepthDrawMode depth_draw_mode; + + VS::MaterialBlendMode blend_mode; + + float line_width; + float point_size; + + RID shader; // shader material + + Map shader_params; + + + Material() { + + + for(int i=0;i 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 { + + Array data; + Array morph_data; + + bool packed; + bool alpha_sort; + int morph_target_count; + AABB aabb; + + VS::PrimitiveType primitive; + + uint32_t format; + uint32_t morph_format; + + RID material; + bool material_owned; + + + Surface() { + + packed=false; + morph_target_count=0; + material_owned=false; + format=0; + morph_format=0; + + primitive=VS::PRIMITIVE_POINTS; + } + + ~Surface() { + + } + }; + + + struct Mesh { + + bool active; + Vector 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_owner; + + struct MultiMesh; + + struct MultiMeshSurface : public Geometry { + + Surface *surface; + MultiMeshSurface() { type=GEOMETRY_MULTISURFACE; } + }; + + struct MultiMesh : public GeometryOwner { + + struct Element { + + Transform xform; + Color color; + }; + + AABB aabb; + RID mesh; + int visible; + + //IDirect3DVertexBuffer9* instance_buffer; + Vector elements; + + MultiMesh() { + visible=-1; + } + + + }; + + + mutable RID_Owner multimesh_owner; + + struct Immediate { + + + RID material; + int empty; + }; + + mutable RID_Owner immediate_owner; + + struct Particles : public Geometry { + + ParticleSystemSW data; // software particle system + + Particles() { + type=GEOMETRY_PARTICLES; + + } + }; + + mutable RID_Owner particles_owner; + + + struct ParticlesInstance : public GeometryOwner { + + RID particles; + + ParticleSystemProcessSW particles_process; + Transform transform; + + ParticlesInstance() { } + }; + + mutable RID_Owner particles_instance_owner; + ParticleSystemDrawInfoSW particle_draw_info; + + struct Skeleton { + + Vector bones; + + }; + + mutable RID_Owner 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 environment_owner; + + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner sampled_light_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; + + + LightInstance() { linear_att=1.0; } + + }; + + mutable RID_Owner light_owner; + mutable RID_Owner light_instance_owner; + + + RID default_material; + + RenderTarget* top_rt; + + +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 *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; + + /* 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 void immediate_set_material(RID p_immediate,RID p_material); + virtual RID immediate_get_material(RID p_immediate) const; + + virtual AABB immediate_get_aabb(RID p_mesh) 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& p_points); + virtual DVector 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& p_points, const Vector& p_colors,const Vector& 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); + + /* 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; + + /* 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*/ + + 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_immediate(const RID& p_rid) const; + virtual bool is_multimesh(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_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& p_info); + virtual void custom_shade_model_get_param_info(int p_model, List* p_info) const; + + + virtual void init(); + virtual void finish(); + + virtual int get_render_info(VS::RenderInfo p_info); + + virtual bool needs_to_draw_next_frame() const; + + virtual bool has_feature(VS::Features p_feature) const; + + + Rasterizer3DS(); + virtual ~Rasterizer3DS(); +}; + + +#endif // RASTERIZER_DUMMY_H diff --git a/platform/3ds/rasterizer_3ds.cpp b/platform/3ds/rasterizer_3ds.cpp new file mode 100644 index 00000000..8278b360 --- /dev/null +++ b/platform/3ds/rasterizer_3ds.cpp @@ -0,0 +1,4923 @@ +/*************************************************************************/ +/* rasterizer_citro3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 _3DS + +#include "rasterizer_3ds.h" +#include "globals.h" +#include "os/os.h" +#include <3ds/services/gspgpu.h> +// #include "util.h" +#define TEX_MIN_SIZE 8 +u32 next_pow2(u32 v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v >= TEX_MIN_SIZE ? v : TEX_MIN_SIZE; +} + +// Grabbed from Citra Emulator (citra/src/video_core/utils.h) +static inline u32 morton_interleave(u32 x, u32 y) +{ + u32 i = (x & 7) | ((y & 7) << 8); // ---- -210 + i = (i ^ (i << 2)) & 0x1313; // ---2 --10 + i = (i ^ (i << 1)) & 0x1515; // ---2 -1-0 + i = (i | ( i >> 7)) & 0x3F; + return i; +} + +//Grabbed from Citra Emulator (citra/src/video_core/utils.h) +static inline u32 get_morton_offset(u32 x, u32 y, u32 bytes_per_pixel) +{ + u32 i = morton_interleave(x, y); + unsigned int offset = (x & ~7) * 8; + return (i + offset) * bytes_per_pixel; +} + +void texture_tile_sw(C3D_Tex *tex, const void *data, int w, int h) +{ + const u32* src = reinterpret_cast(data); + u32* dest = reinterpret_cast(tex->data); + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + { + int dest_y = (tex->height - 1 - y); + u32 coarse_y = dest_y & ~7; + u32 dst_offset = get_morton_offset(x, dest_y, 1) + coarse_y * tex->width; + + u32 v = src[x + y * w]; + dest[dst_offset] = __builtin_bswap32(v); + } + + C3D_TexFlush(tex); +} + + +// Minimum texture dimension seems to be 64 pixels +void texture_tile_hw(C3D_Tex *tex, const void *data, int w, int h) +{ + const u32 flags = (GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | + GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | + GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)); + + GSPGPU_FlushDataCache(data, w*h*4); + + GX_DisplayTransfer( + (u32*)data, + GX_BUFFER_DIM(w, h), + (u32*)tex->data, + GX_BUFFER_DIM(tex->width, tex->height), + flags + ); + + gspWaitForPPF(); + C3D_TexFlush(tex); +} +// Built-in shaders generated in byte array headers +#include "shaders/2d.h" +#include "shaders/3d.h" +#define CLEAR_COLOR 0x68B0D8FF +#define DISPLAY_TRANSFER_FLAGS \ + (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \ + GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \ + GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_XY)) + +/* TEXTURE API */ + +// #define print(...) printf(__VA_ARGS__) +#define print(...) + +RID Rasterizer3DS::texture_create() +{ + Texture *texture = memnew(Texture); + ERR_FAIL_COND_V(!texture,RID()); + return texture_owner.make_rid( texture ); +} + +void Rasterizer3DS::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) +{ + u32 w = next_pow2(p_width); + u32 h = next_pow2(p_height); +// print("texture_allocate %u %u %u\n", w, h, p_texture.get_id()); + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(w > 1024 || h > 1024); + ERR_FAIL_COND(!C3D_TexInit(&texture->tex, w, h, GPU_RGBA8)); + texture->width=p_width; + texture->height=p_height; + texture->format=p_format; + texture->flags=p_flags; +} + +void Rasterizer3DS::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->format != p_image.get_format() ); + + Image &image = texture->image[p_cube_side]; + image = p_image; + image.convert(Image::FORMAT_RGBA); + ERR_FAIL_COND(image.get_format() != Image::FORMAT_RGBA); + + DVector d = image.get_data(); + const u32* imagedata = reinterpret_cast(d.read().ptr()); + + texture_tile_sw(&texture->tex, imagedata, texture->width, texture->height); + +// texture->image[p_cube_side]=image; +} + +Image Rasterizer3DS::texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side) const +{ + print("texture_get_data\n"); + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,Image()); + + return texture->image[p_cube_side]; +} + +void Rasterizer3DS::texture_set_flags(RID p_texture,uint32_t p_flags) +{ + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; + texture->flags=p_flags|cube; // can't remove a cube from being a cube +} +uint32_t Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::texture_get_height(RID p_texture) const +{ + Texture * texture = texture_owner.get(p_texture); + ERR_FAIL_COND_V(!texture,0); + return texture->height; +} + +bool Rasterizer3DS::texture_has_alpha(RID p_texture) const +{ + Texture * texture = texture_owner.get(p_texture); + ERR_FAIL_COND_V(!texture,0); + return false; +} + +void Rasterizer3DS::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>1024); + ERR_FAIL_COND(p_height<=0 || p_height>1024); + //real texture size is in alloc width and height +// texture->width=p_width; +// texture->height=p_height; +} + +void Rasterizer3DS::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const { + + +} + +/* SHADER API */ + +/* SHADER API */ + +RID Rasterizer3DS::shader_create(VS::ShaderMode p_mode) +{ + print("shader_create\n"); + Shader *shader = memnew( Shader ); + shader->mode=p_mode; + shader->fragment_line=0; + shader->vertex_line=0; + shader->light_line=0; + RID rid = shader_owner.make_rid(shader); + + return rid; +} + + + +void Rasterizer3DS::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); + shader->mode=p_mode; + +} +VS::ShaderMode Rasterizer3DS::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 Rasterizer3DS::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); + 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_vertex_ofs; + +} + + +String Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::shader_get_param_list(RID p_shader, List *p_param_list) const { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + +} + + +void Rasterizer3DS::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) +{ + print("shader_set_default_texture_param\n"); +} + +RID Rasterizer3DS::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const { + + return RID(); +} + +Variant Rasterizer3DS::shader_get_default_param(RID p_shader, const StringName& p_name) { + + return Variant(); +} + +/* COMMON MATERIAL API */ + + +RID Rasterizer3DS::material_create() { + print("material_create\n"); + return material_owner.make_rid( memnew( Material ) ); +} + +void Rasterizer3DS::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 Rasterizer3DS::material_get_shader(RID p_material) const { + + Material *material = material_owner.get(p_material); + ERR_FAIL_COND_V(!material,RID()); + return material->shader; +} + +void Rasterizer3DS::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); + + Map::Element *E=material->shader_params.find(p_param); + if (E) + { + if (p_value.get_type()==Variant::NIL) { + material->shader_params.erase(E); +// material->shader_version=0; //get default! + } else { + E->get().value=p_value; + E->get().inuse=true; + } + } else { + if (p_value.get_type()==Variant::NIL) + return; + + Material::UniformData ud; + 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 + } +} +Variant Rasterizer3DS::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.is_valid()) { + //update shader params if necesary + //make sure the shader is compiled and everything + //so the actual parameters can be properly retrieved! + material->shader_cache=shader_owner.get( material->shader ); + if (!material->shader_cache) { + //invalidate + material->shader=RID(); + material->shader_cache=NULL; + } else { + + if (material->shader_cache->dirty_list.in_list()) + _update_shader(material->shader_cache); + if (material->shader_cache->valid && material->shader_cache->version!=material->shader_version) { + //validate + _update_material_shader_params(material); + } + } + } +*/ + + if (material->shader_params.has(p_param) && material->shader_params[p_param].inuse) + return material->shader_params[p_param].value; + else + return Variant(); +} + + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode) +{ + print("material_set_blend_mode\n"); + Material *material = material_owner.get(p_material); + ERR_FAIL_COND(!material); + material->blend_mode=p_mode; +} +VS::MaterialBlendMode Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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; +} + +/* MESH API */ + + +RID Rasterizer3DS::mesh_create() +{ + print("mesh_create\n"); + return mesh_owner.make_rid( memnew( Mesh ) ); +} + +Error Rasterizer3DS::_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=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 array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); + + + DVector::Read read = array.read(); + const Vector3* src=read.ptr(); + + // setting vertices means regenerating the AABB + AABB aabb; + + float scale=1; + + for (int i=0;iarray_len;i++) { + float vector[3]={ src[i].x, src[i].y, src[i].z }; + + memcpy(&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 array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); + + + DVector::Read read = array.read(); + const Vector3* src=read.ptr(); + + // setting vertices means regenerating the AABB + for (int i=0;iarray_len;i++) { + float vector[3]={ src[i].x, src[i].y, src[i].z }; + memcpy(&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 array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_surface->array_len*4, ERR_INVALID_PARAMETER ); + + DVector::Read read = array.read(); + const real_t* src = read.ptr(); + + for (int i=0;iarray_len;i++) { + + float xyzw[4]={ + src[i*4+0], + src[i*4+1], + src[i*4+2], + src[i*4+3] + }; + + memcpy(&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 array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); + + DVector::Read read = array.read(); + const Color* src = read.ptr(); + bool alpha=false; + + for (int i=0;iarray_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 ); + } + + memcpy(&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 array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_surface->array_len , ERR_INVALID_PARAMETER); + + DVector::Read read = array.read(); + + const Vector2 * src=read.ptr(); + float scale=1.0; + + for (int i=0;iarray_len;i++) { + + float uv[2]={ src[i].x , src[i].y }; + + memcpy(&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_WEIGHTS: { + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); + + DVector array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_surface->array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); + + + DVector::Read read = array.read(); + + const real_t * src = read.ptr(); + + for (int i=0;iarray_len;i++) { + + float data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_surface->array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); + + + DVector::Read read = array.read(); + + const int * src = read.ptr(); + + p_surface->max_bone=0; + + for (int i=0;iarray_len;i++) { + + u8 data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;jmax_bone=MAX(data[j],p_surface->max_bone); + + } + + memcpy(&p_mem[a.ofs+i*stride], data, a.size); + } + + } break; + case VS::ARRAY_INDEX: { + +// ERR_FAIL_COND_V(a.size > 2, ERR_INVALID_DATA); + 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 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 8 or 16 bits indices */ + + DVector::Read read = indices.read(); + const int *src=read.ptr(); + + for (int i=0;iindex_array_len;i++) { + if (a.size==2) { + uint16_t v=src[i]; + memcpy(&p_index_mem[i*a.size], &v, a.size); + } else { + uint8_t v=src[i]; + memcpy(&p_index_mem[i*a.size], &v, a.size); + } + } + } break; + + default: { ERR_FAIL_V(ERR_INVALID_PARAMETER);} + } + + p_surface->configured_format|=(1<format&VS::ARRAY_FORMAT_BONES) { + //create AABBs for each detected bone + int total_bones = p_surface->max_bone+1; + if (p_main) { + p_surface->skeleton_bone_aabb.resize(total_bones); + p_surface->skeleton_bone_used.resize(total_bones); + for(int i=0;iskeleton_bone_used[i]=false; + } + DVector vertices = p_arrays[VS::ARRAY_VERTEX]; + DVector bones = p_arrays[VS::ARRAY_BONES]; + DVector weights = p_arrays[VS::ARRAY_WEIGHTS]; + + bool any_valid=false; + + if (vertices.size() && bones.size()==vertices.size()*4 && weights.size()==bones.size()) { + //print_line("MAKING SKELETHONG"); + int vs = vertices.size(); + DVector::Read rv =vertices.read(); + DVector::Read rb=bones.read(); + DVector::Read rw=weights.read(); + + Vector first; + first.resize(total_bones); + for(int i=0;iskeleton_bone_aabb.ptr(); + bool *fptr=first.ptr(); + bool *usedptr=p_surface->skeleton_bone_used.ptr(); + + for(int i=0;iskeleton_bone_aabb.clear(); + p_surface->skeleton_bone_used.clear(); + } + } + + return OK; +} + +void Rasterizer3DS::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) +{ + print("mesh_add_surface\n"); + ERR_FAIL_COND(p_primitive < VS::PRIMITIVE_TRIANGLES); + 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;imorph_target_count!=p_blend_shapes.size() ); + if (mesh->morph_target_count) { + //validate format for morphs + for(int i=0;iarray[i]; + ad.size=0; + ad.ofs=0; + int elem_size=0; + int elem_count=0; + bool valid_local=true; + bool normalize=false; + bool bind=false; + + if (!(format&(1< (1<<16)); // 32 bit index not supported + + /* determine wether using 8 or 16 bits indices */ + if (array_len > (1<<8)) { + elem_size=2; // C3D_UNSIGNED_SHORT + } else { + elem_size=1; // C3D_UNSIGNED_BYTE + } + + 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<stride=total_elem_size; + surface->array_len=array_len; + surface->format=format; + surface->primitive=p_primitive; + surface->morph_target_count=mesh->morph_target_count; + surface->configured_format=0; + surface->mesh=mesh; +// if (keep_copies) { +// surface->data=p_arrays; +// surface->morph_data=p_blend_shapes; +// } + + surface->array_local = (u8*)linearAlloc(surface->array_len*surface->stride); +// u8 *array_ptr= (u8*)linearAlloc(surface->array_len*surface->stride); +// u8 *index_array_ptr=NULL; + +// DVector array_pre_vbo; +// DVector::Write vaw; +// DVector index_array_pre_vbo; +// DVector::Write iaw; + + /* create pointers */ +// 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(); + surface->index_array_local = (u8*) linearAlloc(surface->index_array_len*surface->array[VS::ARRAY_INDEX].size); +// index_array_ptr = (u8*) linearAlloc(surface->index_array_len*surface->array[VS::ARRAY_INDEX].size); + } + + _surface_set_arrays(surface,surface->array_local,surface->index_array_local,p_arrays,true); + + /* create buffers!! */ + + +// 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); +} + +void Rasterizer3DS::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) +{ + ERR_EXPLAIN("Rasterizer does not support custom surfaces. Running on wrong platform?"); + ERR_FAIL_V(); +} + +Array Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 ); + + Vector3Array arr = surface->data[VS::ARRAY_VERTEX]; + return arr.size(); + +} + +int Rasterizer3DS::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 ); + + IntArray arr = surface->data[VS::ARRAY_INDEX]; + return arr.size(); + +} +uint32_t Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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); + + memdelete( mesh->surfaces[p_index] ); + mesh->surfaces.remove(p_index); + +} +int Rasterizer3DS::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 Rasterizer3DS::mesh_get_aabb(RID p_mesh,RID p_skeleton) const { + + Mesh *mesh = mesh_owner.get( p_mesh ); + ERR_FAIL_COND_V(!mesh,AABB()); + + AABB aabb; + + for (int i=0;isurfaces.size();i++) { + + if (i==0) + aabb=mesh->surfaces[i]->aabb; + else + aabb.merge_with(mesh->surfaces[i]->aabb); + } + + return aabb; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::multimesh_create() +{ + print("multimesh_create\n"); + return multimesh_owner.make_rid( memnew( MultiMesh )); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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->elements[p_index].xform=p_transform; + +} +void Rasterizer3DS::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->elements[p_index].color=p_color; + +} + +RID Rasterizer3DS::multimesh_get_mesh(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.get(p_multimesh); + ERR_FAIL_COND_V(!multimesh,RID()); + + return multimesh->mesh; +} +AABB Rasterizer3DS::multimesh_get_aabb(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.get(p_multimesh); + ERR_FAIL_COND_V(!multimesh,AABB()); + + return multimesh->aabb; +} + +Transform Rasterizer3DS::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()); + + return multimesh->elements[p_index].xform; + +} +Color Rasterizer3DS::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()); + + return multimesh->elements[p_index].color; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::immediate_create() { + + print("immediate_create\n"); + Immediate *im = memnew( Immediate ); + return immediate_owner.make_rid(im); + +} + +void Rasterizer3DS::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture) +{ + print("immediate_begin\n"); +} +void Rasterizer3DS::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ + + +} +void Rasterizer3DS::immediate_normal(RID p_immediate,const Vector3& p_normal){ + + +} +void Rasterizer3DS::immediate_tangent(RID p_immediate,const Plane& p_tangent){ + + +} +void Rasterizer3DS::immediate_color(RID p_immediate,const Color& p_color){ + + +} +void Rasterizer3DS::immediate_uv(RID p_immediate,const Vector2& tex_uv){ + + +} +void Rasterizer3DS::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ + + +} + +void Rasterizer3DS::immediate_end(RID p_immediate){ + + print("immediate_end\n"); +} +void Rasterizer3DS::immediate_clear(RID p_immediate) { + + +} + +AABB Rasterizer3DS::immediate_get_aabb(RID p_immediate) const { + + return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::particles_create() +{ + Particles *particles = memnew( Particles ); + ERR_FAIL_COND_V(!particles,RID()); + return particles_owner.make_rid(particles); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::particles_set_emission_points(RID p_particles, const DVector& p_points) { + + Particles* particles = particles_owner.get( p_particles ); + ERR_FAIL_COND(!particles); + + particles->data.emission_points=p_points; +} + +DVector Rasterizer3DS::particles_get_emission_points(RID p_particles) const { + + Particles* particles = particles_owner.get( p_particles ); + ERR_FAIL_COND_V(!particles,DVector()); + + return particles->data.emission_points; + +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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;idata.color_phases[i].color.a<0.99) + particles->has_alpha=true; + } + +} + +Color Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::skeleton_create() { + + Skeleton *skeleton = memnew( Skeleton ); + ERR_FAIL_COND_V(!skeleton,RID()); + return skeleton_owner.make_rid( skeleton ); +} +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_create(VS::LightType p_type) { + print("light_create\n"); + Light *light = memnew( Light ); + light->type=p_type; + return light_owner.make_rid(light); +} + +VS::LightType Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_get_projector(RID p_light) const { + + Light *light = light_owner.get(p_light); + ERR_FAIL_COND_V(!light,RID()); + return light->projector; +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::light_set_operator(RID p_light,VS::LightOp p_op) { + + Light * light = light_owner.get( p_light ); + ERR_FAIL_COND(!light); + + +}; + +VS::LightOp Rasterizer3DS::light_get_operator(RID p_light) const { + + return VS::LightOp(0); +}; + +void Rasterizer3DS::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { + + +} + +VS::LightOmniShadowMode Rasterizer3DS::light_omni_get_shadow_mode(RID p_light) const{ + + return VS::LightOmniShadowMode(0); +} + +void Rasterizer3DS::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) { + + +} + +VS::LightDirectionalShadowMode Rasterizer3DS::light_directional_get_shadow_mode(RID p_light) const { + + return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; +} + +void Rasterizer3DS::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) { + + +} + +float Rasterizer3DS::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const { + + return 0; +} + + +AABB Rasterizer3DS::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 Rasterizer3DS::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; + + return light_instance_owner.make_rid( light_instance ); +} +void Rasterizer3DS::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 Rasterizer3DS::light_instance_has_shadow(RID p_light_instance) const { + + return false; + +} + + +bool Rasterizer3DS::light_instance_assign_shadow(RID p_light_instance) { + + return false; + +} + + +Rasterizer::ShadowType Rasterizer3DS::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 Rasterizer3DS::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const { + + return SHADOW_NONE; +} +void Rasterizer3DS::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 Rasterizer3DS::light_instance_get_shadow_passes(RID p_light_instance) const { + + return 0; +} + +bool Rasterizer3DS::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { + + return false; +} + + +void Rasterizer3DS::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 Rasterizer3DS::shadow_clear_near() { + + +} + +bool Rasterizer3DS::shadow_allocate_near(RID p_light) { + + return false; +} + +bool Rasterizer3DS::shadow_allocate_far(RID p_light) { + + return false; +} + +/* PARTICLES INSTANCE */ + +RID Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::viewport_data_create() +{ + print("viewport_data_create\n"); + return RID(); +} + +RID Rasterizer3DS::render_target_create() +{ + print("render_target_create\n"); + RenderTarget* rt = memnew(RenderTarget); + Texture *texture = memnew(Texture); + + rt->target = C3D_RenderTargetCreate(480, 800, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(rt->target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + C3D_RenderTargetClear(rt->target,C3D_CLEAR_ALL,CLEAR_COLOR,0); + rt->texture_ptr = texture; + rt->texture = texture_owner.make_rid( texture ); + + return render_target_owner.make_rid( rt ); +} +void Rasterizer3DS::render_target_set_size(RID p_render_target, int p_width, int p_height) +{ + RenderTarget* rt = render_target_owner.get( p_render_target ); + +} +RID Rasterizer3DS::render_target_get_texture(RID p_render_target) const +{ + print("render_target_get_texture\n"); + const RenderTarget *rt = render_target_owner.get(p_render_target); + ERR_FAIL_COND_V(!rt,RID()); + return rt->texture; +} +bool Rasterizer3DS::render_target_renedered_in_frame(RID p_render_target) +{ + RenderTarget *rt = render_target_owner.get(p_render_target); + ERR_FAIL_COND_V(!rt,false); +// return rt->last_pass==frame; + return false; +} + + +void Rasterizer3DS::begin_frame() +{ + print("begin_frame\n"); + draw_next_frame = false; + + float time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec + time/=1000.0; // make secs + if (frame != 0) { + time_delta = time_scale * (time - last_time); + } else { + time_delta = 0.0f; + } + scaled_time += time_delta; + last_time=time; + frame++; + C3D_FrameBegin(0); +} + +void Rasterizer3DS::capture_viewport(Image* r_capture) { + + +} + + +void Rasterizer3DS::clear_viewport(const Color& p_color) +{ + print("clear_viewport\n"); + RenderTarget* rt = current_rt ? current_rt : base_framebuffer; + u32 c = (u8)(p_color.r*255); + c <<= 8; + c |= (u8)(p_color.g*255); + c <<= 8; + c |= (u8)(p_color.b*255); + c <<= 8; + c |= (u8)(p_color.a*255); + C3D_RenderTargetClear(rt->target,C3D_CLEAR_ALL,c,0); +}; + +void Rasterizer3DS::set_viewport(const VS::ViewportRect& p_viewport) +{ + print("set_viewport %d %d %d %d\n", p_viewport.x, p_viewport.y, p_viewport.width, p_viewport.height); + u32 top = p_viewport.height - p_viewport.y; + //C3D_SetViewport(top, p_viewport.x, p_viewport.height, p_viewport.width); + C3D_SetViewport(0, 0, p_viewport.height, p_viewport.width); +} + +void Rasterizer3DS::set_time_scale(float p_scale) +{ + time_scale = p_scale; +} +void Rasterizer3DS::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) +{ + print("set_render_target\n"); + current_rt_vflip=p_vflip; + + if (p_render_target.is_valid()) + { + RenderTarget *rt = render_target_owner.get(p_render_target); + ERR_FAIL_COND(!rt); + ERR_FAIL_COND(!rt->target); + //C3D_RenderTargetSetOutput(rt->target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + C3D_SetFrameBuf(&rt->target->frameBuf); + //C3D_RenderBufBind(&rt->target->renderBuf); + current_rt=rt; + current_rt_transparent=p_transparent_bg; + } + else + { + print("null target\n"); + current_rt = NULL; + current_rt_transparent = false; + C3D_SetFrameBuf(&base_framebuffer->target->frameBuf); + //C3D_RenderTargetSetOutput(base_framebuffer->target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + //C3D_RenderBufBind(&base_framebuffer->target->renderBuf); + } +} + + +void Rasterizer3DS::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) +{ + print("begin_scene\n"); + opaque_render_list.clear(); + alpha_render_list.clear(); + + RenderTarget* rt = current_rt ? current_rt : base_framebuffer; + + current_env = p_env.is_valid() ? environment_owner.get(p_env) : NULL; +// current_vd=viewport_data_owner.get(p_viewport_data); + + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR); + C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + + C3D_TexBind(0, NULL); + + C3D_BindProgram(&scene_shader->program); + _set_uniform(scene_shader->location_modelview, Matrix32()); + _set_uniform(scene_shader->location_extra, Matrix32()); +}; + +void Rasterizer3DS::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) { + +} + +void Rasterizer3DS::set_camera(const Transform& p_world, const CameraMatrix& p_projection) +{ + + + print("set_camera\n"); + camera_transform=p_world; +// if (current_rt && current_rt_vflip) { + if (current_rt_vflip) { +// m[4] = -1; +// camera_transform.basis.set_axis(1,-camera_transform.basis.get_axis(1)); + } +// camera_transform.basis.set_axis(0,-camera_transform.basis.get_axis(0)); + + camera_transform_inverse=camera_transform.inverse(); + camera_projection = p_projection; +// camera_projection.get_fov() +// camera_projection=*reinterpret_cast(m) * p_projection; +// camera_projection = camera_projection * m; +// camera_projection.invert(); + 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); + // camera_ortho=p_ortho_hint; + + print("z-near:%f z-far:%f\n", camera_z_near, camera_z_far); + print("x:%f y:%f\n", camera_vp_size.x,camera_vp_size.y); + +// for (int i = 0; i < 4; ++i) +// print("%f %f %f %f\n", m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]); + + _set_uniform(scene_shader->location_modelview, Matrix32()); +// _set_uniform(scene_shader->location_worldTransform, Matrix32()); + _set_uniform(scene_shader->location_worldTransform, camera_transform_inverse); + _set_uniform(scene_shader->location_projection, camera_projection); + +// C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, scene_shader->location_projection, &mtx); +} + +void Rasterizer3DS::add_light( RID p_light_instance ) +{ + // ERR_FAIL_COND( light_instance_count >= MAX_SCENE_LIGHTS ); + + LightInstance *li = light_instance_owner.get(p_light_instance); + ERR_FAIL_COND(!li); + + // light_instances[light_instance_count++]=li; + C3D_LightInit(&li->base->light, &lightEnv); +} + +void Rasterizer3DS::add_immediate( const RID& p_immediate, const InstanceData *p_data) +{ + print("add_immediate\n"); +} + + +void Rasterizer3DS::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;isurfaces[i]; + _add_geometry(s,p_data,s,NULL); + } + + mesh->last_pass=frame; + +} + +void Rasterizer3DS::add_multimesh( const RID& p_multimesh, const InstanceData *p_data) +{ + print("add_multimesh\n"); +} + +void Rasterizer3DS::add_particles( const RID& p_particle_instance, const InstanceData *p_data) +{ + 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); +// draw_next_frame=true; +} + + + +void Rasterizer3DS::end_scene() +{ + print("end_scene\n"); + +// opaque_render_list.sort_mat_light_type_flags(); + _render_list_forward(&opaque_render_list, camera_transform, camera_transform_inverse,camera_projection,false,fragment_lighting); + +// alpha_render_list.sort_z(); +// _render_list_forward(&alpha_render_list, camera_transform, camera_transform_inverse,camera_projection,false,fragment_lighting,true); + +} +void Rasterizer3DS::end_shadow_map() { + +} + + +void Rasterizer3DS::end_frame() +{ + C3D_FrameEnd(GX_CMDLIST_UPDATE_GAS_ACC); + + print("end_frame %d %f\n", vertexArrays.size(), C3D_GetCmdBufUsage()); + + RenderTarget* rt = current_rt ? current_rt : base_framebuffer; + C3D_FrameBufTransfer(&rt->target->frameBuf,rt->target->screen,rt->target->side,rt->target->transferFlags); + VertexArray **varray = vertexArrays.ptr(); + for (int i = 0; i < vertexArrays.size(); ++i) + memdelete(*varray++); + vertexArrays.clear(); + + // OS::get_singleton()->swap_buffers(); + gfxSwapBuffersGpu(); + // if (use_vsync) + gspWaitForVBlank(); +} + +void Rasterizer3DS::flush_frame() +{ +} + +RID Rasterizer3DS::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 Rasterizer3DS::canvas_light_occluder_set_polylines(RID p_occluder, const DVector& p_lines) +{ + CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!co); + return; + + 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 geometry; + DVector indices; + int lc = p_lines.size(); + + geometry.resize(lc*6); + indices.resize(lc*3); + + DVector::Write vw=geometry.write(); + DVector::Write iw=indices.write(); + + + DVector::Read lr=p_lines.read(); + + const int POLY_HEIGHT = 16384; + + for(int i=0;ivertex_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 Rasterizer3DS::canvas_light_shadow_buffer_create(int p_width) +{ + return RID(); + CanvasLightShadow *cls = memnew( CanvasLightShadow ); + if (p_width>1024) + p_width=1024; + + cls->size=p_width; + cls->height=16; + +/* + 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->renderTarget = C3D_RenderTargetCreate(480, 800, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(cls->renderTarget, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + C3D_RenderTargetClear(cls->renderTarget,C3D_CLEAR_ALL,C3D_CLEAR_COLOR,0); + +// ERR_FAIL_COND(!C3D_TexInit(&cls->texture, w, h, GPU_RGBA8)); + + +/* + //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); +} + + + +/* CANVAS API */ + + +void Rasterizer3DS::begin_canvas_bg() +{ + print("begin_canvas_bg\n"); +} +void Rasterizer3DS::canvas_begin() +{ + print("canvas_begin"); + + C3D_Mtx projection; + Mtx_OrthoTilt(&projection, 0.0, 800.0, 480.0, 0.0, 0.0, 1.0, true); + + C3D_BindProgram(&canvas_shader->program); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, canvas_shader->location_projection, &projection); + + _set_uniform(canvas_shader->location_modelview, Matrix32()); + _set_uniform(canvas_shader->location_extra, Matrix32()); + + C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); + AttrInfo_Init(attrInfo); + AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position + AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=texcoord + AttrInfo_AddFixed(attrInfo, 2); // v2=color + + canvas_opacity = 1.0; + + canvas_blend_mode = VS::MATERIAL_BLEND_MODE_MIX; + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); + + print(" %f\n", C3D_GetCmdBufUsage()); +} +void Rasterizer3DS::canvas_disable_blending() +{ + print("canvas_disable_blending\n"); + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); +} + +void Rasterizer3DS::canvas_set_opacity(float p_opacity) +{ + canvas_opacity = p_opacity; +} + +void Rasterizer3DS::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) +{ + if (p_mode==canvas_blend_mode) + return; + + switch(p_mode) + { + case VS::MATERIAL_BLEND_MODE_MIX: { + if (current_rt && current_rt_transparent) { + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + } + else { + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); + } + + } break; + case VS::MATERIAL_BLEND_MODE_ADD: { + + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE, GPU_SRC_ALPHA, GPU_ONE); + + } break; + case VS::MATERIAL_BLEND_MODE_SUB: { + C3D_AlphaBlend(GPU_BLEND_REVERSE_SUBTRACT, GPU_BLEND_REVERSE_SUBTRACT, GPU_SRC_ALPHA, GPU_ONE, GPU_SRC_ALPHA, GPU_ONE); + } break; + case VS::MATERIAL_BLEND_MODE_MUL: { + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_DST_COLOR, GPU_ZERO, GPU_DST_COLOR, GPU_ZERO); + } break; + case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { + C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + } break; + } + + canvas_blend_mode=p_mode; +} + +void Rasterizer3DS::canvas_begin_rect(const Matrix32& p_transform) +{ + _set_uniform(canvas_shader->location_modelview, p_transform); + _set_uniform(canvas_shader->location_extra, Matrix32()); +// canvas_transform = p_transform; +} + +void Rasterizer3DS::canvas_set_clip(bool p_clip, const Rect2& p_rect) { + + + + +} + +void Rasterizer3DS::canvas_end_rect() +{ + print("canvas_end_rect\n"); +} + +void Rasterizer3DS::canvas_draw_line(const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width) +{ + print("canvas_draw_line\n"); +} + +void Rasterizer3DS::canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate) +{ +// print("canvas_draw_rect %.1f %.1f %.1f %.1f\n", p_rect.pos.x, p_rect.pos.y, p_rect.size.width, p_rect.size.height); + + // Set the fixed attribute (color) + C3D_FixedAttribSet(2, p_modulate.r, p_modulate.g, p_modulate.b, p_modulate.a * canvas_opacity); +// C3D_FixedAttribSet(2, 1.f, 1.f, 1.f, 1.f); + C3D_TexEnv* env = C3D_GetTexEnv(0); + + + if (p_texture.is_valid()) + { + Texture* texture = texture_owner.get(p_texture); +// ERR_FAIL_COND(!texture); + + if (p_flags & CANVAS_RECT_TILE && !(texture->flags & VS::TEXTURE_FLAG_REPEAT)) + { + + } + + C3D_TexBind(0, &texture->tex); + + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR); + C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); + + if (!(p_flags&CANVAS_RECT_REGION)) { +// // + Rect2 region = Rect2(0,0,texture->tex.width,texture->tex.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->tex.width,texture->tex.height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V); + + } + } + else + { + C3D_TexBind(0, NULL); + + C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR); + C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + + _draw_quad(p_rect); + } +} +void Rasterizer3DS::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) +{ + print("canvas_draw_style_box\n"); + +// Color m = p_modulate; +// m.a*=canvas_opacity; +// _set_color_attrib(m); + C3D_FixedAttribSet(2, p_modulate.r, p_modulate.g, p_modulate.b, p_modulate.a * canvas_opacity); + + Texture* texture=_bind_texture(p_texture); + ERR_FAIL_COND(!texture); + + Rect2 region = p_rect; + + // Rect2 region( 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] )); + + if (region.size.width <= 0 ) + region.size.width = texture->width; + if (region.size.height <= 0) + region.size.height = texture->height; + /* CORNERS */ + _draw_textured_quad( // top left + Rect2( p_rect.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])), + Rect2( region.pos, 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(region.pos.x+region.size.width-p_margin[MARGIN_RIGHT], region.pos.y), 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(region.pos.x, region.pos.y+region.size.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(region.pos.x+region.size.width-p_margin[MARGIN_RIGHT], region.pos.y+region.size.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(region.pos.x+p_margin[MARGIN_LEFT], region.pos.y+p_margin[MARGIN_TOP]), Size2(region.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], region.size.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(src_center.pos.x,region.pos.y), 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(src_center.pos.x,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(region.pos.x,region.pos.y+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,region.pos.y+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 )); + } + + _rinfo.ci_draw_commands++; +} +void Rasterizer3DS::canvas_draw_primitive(const Vector& p_points, const Vector& p_colors,const Vector& p_uvs, RID p_texture,float p_width) +{ + print("canvas_draw_primitive\n"); +} + + +void Rasterizer3DS::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) +{ + print("canvas_draw_polygon\n"); +} + +Rasterizer3DS::Texture* Rasterizer3DS::_bind_texture(const RID& p_texture) +{ + if (p_texture.is_valid()) + { + Texture*texture=texture_owner.get(p_texture); + C3D_TexBind(0, &texture->tex); + return texture; + } + + C3D_TexBind(0, NULL); + return NULL; +} + +void Rasterizer3DS::_set_uniform(int uniform_location, const Matrix32& p_transform) +{ + const Matrix32& tr = p_transform; + + C3D_Mtx mtx; +// float matrix[16] = { /* build a 16x16 matrix */ +// tr.elements[2][0], tr.elements[2][1], 0, 1, +// 0, 0, 1, 0, +// tr.elements[1][0], tr.elements[1][1], 0, 0, +// tr.elements[0][0], tr.elements[0][1], 0, 0, +// }; + +// float m[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 +// }; + + float matrix[16] = { /* build a 16x16 matrix */ + tr.elements[2][0], 0, tr.elements[1][0], tr.elements[0][0], + tr.elements[2][1], 0, tr.elements[1][1], tr.elements[0][1], + 0, 1, 0, 0, + 1, 0, 0, 0, + }; + + memcpy(mtx.m, matrix, sizeof(matrix)); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mtx); +} + +void Rasterizer3DS::_set_uniform(int uniform_location, const Transform& p_transform) +{ + const Transform& tr = p_transform; + + C3D_Mtx mtx; +// float 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 +// }; + float matrix[16]={ /* build a 16x16 matrix */ + tr.origin.x, tr.basis.elements[0][2], tr.basis.elements[0][1], tr.basis.elements[0][0], + tr.origin.y, tr.basis.elements[1][2], tr.basis.elements[1][1], tr.basis.elements[1][0], + tr.origin.z, tr.basis.elements[2][2], tr.basis.elements[2][1], tr.basis.elements[2][0], + 1, 0, 0, 0, + }; + + memcpy(mtx.m, matrix, sizeof(matrix)); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mtx); +} + + +void Rasterizer3DS::_set_uniform(int uniform_location, const Color& p_color) +{/* + const Color& c = p_color; + + C3D_Mtx mat = {{ + { { c.r, c.g, c.b, 1.0f } }, // Ambient + { { c.r, c.g, c.b, 1.0f } }, // Diffuse + { { 1.0f, 0.0f, 0.0f, 1.0f } }, // Specular + { { 1.0f, 0.0f, 0.0f, 1.0f } }, // Emission + }};*/ + /* + C3D_Mtx material = +{ + { + { { 1.0f, 0.2f, 1.0f, 1.0f } }, // Ambient + { { 1.0f, 0.4f, 0.4f, 1.0f } }, // Diffuse + { { 1.0f, 0.8f, 0.8f, 1.0f } }, // Specular + { { 1.0f, 0.0f, 0.0f, 1.0f } }, // Emission + } +};*/ + // memcpy(mtx.m, matrix, sizeof(matrix)); + // C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mat); + + +} + +void Rasterizer3DS::_set_uniform(int uniform_location, const CameraMatrix& p_matrix) +{ + // Swap X/Y axis due to 3DS screens being sideways + // and adjust clipping range from [-1, 1] to [-1, 0] + float m[16] = { + 0, -1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0.5, 0, +// 0, 0, 1, 0, + 0, 0, -0.5, 1, + }; + + CameraMatrix p = *reinterpret_cast(m) * p_matrix; + + C3D_Mtx mtx; + float *to = mtx.m; + const float *from = reinterpret_cast(p.matrix); +// for (int i = 0; i < 4; ++i) +// { +// mtx.r[i].x = *from++; +// mtx.r[i].y = *from++; +// mtx.r[i].z = *from++; +// mtx.r[i].w = *from++; +// } + + to[0] = from[12]; + to[1] = from[8]; + to[2] = from[4]; + to[3] = from[0]; + to[4] = from[13]; + to[5] = from[9]; + to[6] = from[5]; + to[7] = from[1]; + to[8] = from[14]; + to[9] = from[10]; + to[10] = from[6]; + to[11] = from[2]; + to[12] = from[15]; + to[13] = from[11]; + to[14] = from[7]; + to[15] = from[3]; + +// for (int i = 0; i < 4; ++i) +// print("%f %f %f %f\n", to[i*4], to[i*4+1], to[i*4+2], to[i*4+3]); + + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniform_location, &mtx); +} + +void Rasterizer3DS::canvas_set_transform(const Matrix32& p_transform) +{ + _set_uniform(canvas_shader->location_extra, p_transform); +} + +static void _set_scissor(int x, int y, int w, int h) +{ + print("set_scissor %d %d %d %d\n", x, y, w, h); + // Keep in mind the sideway 3ds screen, so it seems screwy + int bottom = 400 - x; + int top = 240 - y; + int left = top - h; + int right = bottom - w; + if (bottom < 0) bottom = 0; + if (top < 0) top = 0; + if (left < 0) left = 0; + if (right < 0) right = 0; + C3D_SetScissor(GPU_SCISSOR_NORMAL, left, right, top, bottom); +// C3D_SetScissor(GPU_SCISSOR_NORMAL, 240 - (y + h), 400 - (x + w), 240 - y, 400 - x); +} +#if 0 + +void Rasterizer3DS::_set_canvas_scissor(CanvasItem* p_item) +{ + int x, y, w, h; + + if (current_rt) { + x = p_item->final_clip_rect.pos.x; + y = p_item->final_clip_rect.pos.y; + w = p_item->final_clip_rect.size.x; + h = p_item->final_clip_rect.size.y; + } + else + { + x = p_item->final_clip_rect.pos.x; + y = 240 - (p_item->final_clip_rect.pos.y + p_item->final_clip_rect.size.y); + w = p_item->final_clip_rect.size.x; + h = p_item->final_clip_rect.size.y; + } + + _set_scissor(x, y, w, h); +} + +template +void Rasterizer3DS::_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(); + +// print("_canvas_item_render_commands\n"); + + for(int i=0;itype) { + case CanvasItem::Command::TYPE_LINE: { + + CanvasItem::CommandLine* line = static_cast(c); + canvas_draw_line(line->from,line->to,line->color,line->width); + } break; + case CanvasItem::Command::TYPE_RECT: { + + CanvasItem::CommandRect* rect = static_cast(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(c); +// if (use_normalmap) +// _canvas_normal_set_flip(Vector2(1,1)); + canvas_draw_style_box(style->rect,style->source,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(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(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(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(c); + static const int numpoints=32; + Vector2 points[numpoints+1]; + points[numpoints]=circle->pos; + int indices[numpoints*3]; + + for(int i=0;ipos+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(c); + canvas_set_transform(transform->xform); + } break; + case CanvasItem::Command::TYPE_BLEND_MODE: { + + CanvasItem::CommandBlendMode* bm = static_cast(c); + canvas_set_blend_mode(bm->blend_mode); + + } break; + case CanvasItem::Command::TYPE_CLIP_IGNORE: { + + CanvasItem::CommandClipIgnore* ci = static_cast(c); + if (current_clip) { + + if (ci->ignore!=reclip) { + if (ci->ignore) { + C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0); + reclip = true; + } else { + _set_canvas_scissor(current_clip); + reclip=false; + } + } + } + } break; + } + } + +} + +void Rasterizer3DS::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) +{ +// print("canvas_render_items Z:%d\n", p_z); + + canvas_opacity=1.0; +// canvas_use_modulate=p_modulate!=Color(1,1,1,1); +// canvas_modulate=p_modulate; + +// C3D_FixedAttribSet(2, p_modulate.r, p_modulate.g, p_modulate.b, canvas_opacity); +// C3D_FixedAttribSet(2, 1.f, 1.f, 1.f, 1.f); + + CanvasItem *current_clip = NULL; + + while(p_item_list) + { + CanvasItem *ci = p_item_list; + + // Handle clipping (scissor test) + if (current_clip != ci->final_clip_owner) + { + current_clip = ci->final_clip_owner; + if (current_clip) + { +// int x, y, w, h; +// +// if (current_rt) { +// x = current_clip->final_clip_rect.pos.x; +// y = current_clip->final_clip_rect.pos.y; +// w = current_clip->final_clip_rect.size.x; +// h = current_clip->final_clip_rect.size.y; +// } +// else { +// x = current_clip->final_clip_rect.pos.x; +// y = 240 - (current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y); +// w = current_clip->final_clip_rect.size.x; +// h = current_clip->final_clip_rect.size.y; +// } +// _set_scissor(x, y, w, h); + _set_canvas_scissor(current_clip); + } + else + C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0); + } + + // Handle material/shader + CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci; + CanvasItemMaterial *material = material_owner->material; + + _set_uniform(canvas_shader->location_modelview,ci->final_transform); + _set_uniform(canvas_shader->location_extra, Matrix32()); + + bool unshaded = (material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX; + + bool reclip=false; + + if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) + canvas_set_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) && !ci->light_masked )) + _canvas_item_render_commands(ci, current_clip, reclip); + + if (reclip) + { + _set_canvas_scissor(current_clip); + } + + p_item_list = p_item_list->next; + } + + if (current_clip) + C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0); +} +#endif +/* ENVIRONMENT */ + +RID Rasterizer3DS::environment_create() +{ + print("environment_create\n"); + Environment * env = memnew( Environment ); + return environment_owner.make_rid(env); +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::environment_set_group(RID p_env,VS::Group p_param, const Variant& p_value){ + + ERR_FAIL_INDEX(p_param,VS::ENV_GROUP_MAX); + Environment * env = environment_owner.get(p_env); + ERR_FAIL_COND(!env); + env->group[p_param]=p_value; + +} +Variant Rasterizer3DS::environment_get_group(RID p_env,VS::Group p_param) const{ + + ERR_FAIL_INDEX_V(p_param,VS::ENV_GROUP_MAX,Variant()); + const Environment * env = environment_owner.get(p_env); + ERR_FAIL_COND_V(!env,Variant()); + return env->group[p_param]; + +} + +void Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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 Rasterizer3DS::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]; + +} + + +RID Rasterizer3DS::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void Rasterizer3DS::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + + +/*MISC*/ + +bool Rasterizer3DS::is_texture(const RID& p_rid) const { + + return texture_owner.owns(p_rid); +} +bool Rasterizer3DS::is_material(const RID& p_rid) const { + + return material_owner.owns(p_rid); +} +bool Rasterizer3DS::is_mesh(const RID& p_rid) const { + + return mesh_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_immediate(const RID& p_rid) const { + + return immediate_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_multimesh(const RID& p_rid) const { + + return multimesh_owner.owns(p_rid); +} +bool Rasterizer3DS::is_particles(const RID &p_beam) const { + + return particles_owner.owns(p_beam); +} + +bool Rasterizer3DS::is_light(const RID& p_rid) const { + + return light_owner.owns(p_rid); +} +bool Rasterizer3DS::is_light_instance(const RID& p_rid) const { + + return light_instance_owner.owns(p_rid); +} +bool Rasterizer3DS::is_particles_instance(const RID& p_rid) const { + + return particles_instance_owner.owns(p_rid); +} +bool Rasterizer3DS::is_skeleton(const RID& p_rid) const { + + return skeleton_owner.owns(p_rid); +} +bool Rasterizer3DS::is_environment(const RID& p_rid) const { + + return environment_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_canvas_light_occluder(const RID& p_rid) const { + + return canvas_occluder_owner.owns(p_rid); +} + +bool Rasterizer3DS::is_shader(const RID& p_rid) const { + + return shader_owner.owns(p_rid); +} + +void Rasterizer3DS::free(const RID& p_rid) { + + if (texture_owner.owns(p_rid)) { + +// print("delete texture\n"); + Texture *texture = texture_owner.get(p_rid); + texture_owner.free(p_rid); + memdelete(texture); + + } else if (shader_owner.owns(p_rid)) { + + print("delete shader\n"); + 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 ); + material_owner.free(p_rid); + memdelete(material); + + } else if (mesh_owner.owns(p_rid)) { + + Mesh *mesh = mesh_owner.get(p_rid); + + for (int i=0;isurfaces.size();i++) { + Surface *surface = mesh->surfaces[i]; + if (surface->array_local) + linearFree(surface->array_local); + if (surface->index_array_local) + linearFree(surface->index_array_local); + + if (mesh->morph_target_count>0) { + + for(int i=0;imorph_target_count;i++) { + + memdelete_arr(surface->morph_targets_local[i].array); + } + memdelete_arr(surface->morph_targets_local); + surface->morph_targets_local=NULL; + } + + memdelete( mesh->surfaces[i] ); + }; + + mesh->surfaces.clear(); + mesh_owner.free(p_rid); + memdelete(mesh); + + } else if (multimesh_owner.owns(p_rid)) { + + MultiMesh *multimesh = multimesh_owner.get(p_rid); + multimesh_owner.free(p_rid); + memdelete(multimesh); + + } else if (immediate_owner.owns(p_rid)) { + + Immediate *immediate = immediate_owner.get(p_rid); + immediate_owner.free(p_rid); + memdelete(immediate); + + } else if (particles_owner.owns(p_rid)) { + + Particles *particles = particles_owner.get(p_rid); + particles_owner.free(p_rid); + memdelete(particles); + } else if (particles_instance_owner.owns(p_rid)) { + + ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); + particles_instance_owner.free(p_rid); + memdelete(particles_isntance); + + } else if (skeleton_owner.owns(p_rid)) { + + Skeleton *skeleton = skeleton_owner.get( p_rid ); + skeleton_owner.free(p_rid); + memdelete(skeleton); + + } else if (light_owner.owns(p_rid)) { + + Light *light = light_owner.get( p_rid ); + light_owner.free(p_rid); + memdelete(light); + + } else if (light_instance_owner.owns(p_rid)) { + + LightInstance *light_instance = light_instance_owner.get( p_rid ); + light_instance_owner.free(p_rid); + memdelete( light_instance ); + + } else if (canvas_occluder_owner.owns(p_rid)) { + + CanvasOccluder *co = canvas_occluder_owner.get(p_rid); + + 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); + C3D_RenderTargetDelete(cls->renderTarget); + + canvas_light_shadow_owner.free(p_rid); + memdelete(cls); + + } else if (environment_owner.owns(p_rid)) { + + Environment *env = environment_owner.get( p_rid ); + environment_owner.free(p_rid); + memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + + }; +} + + +void Rasterizer3DS::custom_shade_model_set_shader(int p_model, RID p_shader) { + + +}; + +RID Rasterizer3DS::custom_shade_model_get_shader(int p_model) const { + + return RID(); +}; + +void Rasterizer3DS::custom_shade_model_set_name(int p_model, const String& p_name) { + +}; + +String Rasterizer3DS::custom_shade_model_get_name(int p_model) const { + + return String(); +}; + +void Rasterizer3DS::custom_shade_model_set_param_info(int p_model, const List& p_info) { + +}; + +void Rasterizer3DS::custom_shade_model_get_param_info(int p_model, List* p_info) const { + +}; + + + + +void Rasterizer3DS::_render_list_forward(RenderList *p_render_list,const Transform& p_view_transform, const Transform& p_view_transform_inverse,const CameraMatrix& p_projection,bool p_reverse_cull,bool p_fragment_light,bool p_alpha_pass) +{ + print("_render_list_forward\n"); + + if (current_rt && current_rt_vflip) { + //p_reverse_cull=!p_reverse_cull; +// glFrontFace(GL_CCW); + + } + + const Material *prev_material=NULL; + uint16_t prev_light=0x777E; + const Geometry *prev_geometry_cmp=NULL; + uint8_t prev_light_type=0xEF; + const Skeleton *prev_skeleton =NULL; + uint8_t prev_sort_flags=0xFF; + const BakedLightData *prev_baked_light=NULL; + RID prev_baked_light_texture; + const float *prev_morph_values=NULL; + int prev_receive_shadows_state=-1; + + +/* + material_shader.set_conditional(MaterialShaderGLES2::USE_VERTEX_LIGHTING,!shadow && !p_fragment_light); + material_shader.set_conditional(MaterialShaderGLES2::USE_FRAGMENT_LIGHTING,!shadow && p_fragment_light); + material_shader.set_conditional(MaterialShaderGLES2::USE_SKELETON,false); + + if (shadow) { + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_DIRECTIONAL,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_OMNI,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,false); + material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,false); + 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_TEXTURE,false); + + } +*/ + + +// 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); + /* + C3D_Mtx material = + { + { + { { 0.0f, 0.2f, 0.2f, 0.2f } }, // Ambient + { { 0.0f, 0.8f, 0.8f, 0.4f } }, // Diffuse + { { 0.0f, 0.8f, 0.8f, 0.8f } }, // Specular + { { 1.0f, 0.0f, 0.0f, 0.0f } }, // Emission + } + }; + + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, scene_shader->location_material, &material);*/ + for (int i=0;ielement_count;i++) { + + RenderList::Element *e = p_render_list->elements[i]; + const Material *material = e->material; + uint16_t light = e->light; + uint8_t light_type = e->light_type; + uint8_t sort_flags= e->sort_flags; + const Skeleton *skeleton = e->skeleton; + const Geometry *geometry_cmp = e->geometry_cmp; + const BakedLightData *baked_light = e->instance->baked_light; + const float *morph_values = e->instance->morph_values.ptr(); + // int receive_shadows_state = e->instance->receive_shadows == true ? 1 : 0; + + bool rebind=false; + bool bind_baked_light_octree=false; + bool bind_baked_lightmap=false; + bool additive=false; + bool bind_dp_sampler=false; + +/* + if (!shadow) { + + if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) { + texscreen_copied=true; + _copy_to_texscreen(); + + //force reset state + prev_material=NULL; + prev_light=0x777E; + prev_geometry_cmp=NULL; + prev_light_type=0xEF; + prev_skeleton =NULL; + prev_sort_flags=0xFF; + prev_morph_values=NULL; + prev_receive_shadows_state=-1; + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + + } + + if (light_type!=prev_light_type || receive_shadows_state!=prev_receive_shadows_state) { + + if (material->flags[VS::MATERIAL_FLAG_UNSHADED] || current_debug==VS::SCENARIO_DEBUG_SHADELESS) { + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_DIRECTIONAL,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_OMNI,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,false); + material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,true); + } else { + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_DIRECTIONAL,(light_type&0x3)==VS::LIGHT_DIRECTIONAL); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_OMNI,(light_type&0x3)==VS::LIGHT_OMNI); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_TYPE_SPOT,(light_type&0x3)==VS::LIGHT_SPOT); + if (receive_shadows_state==1) { + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW,(light_type&0x8)); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,(light_type&0x10)); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,(light_type&0x20)); + } + else { + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_SHADOW,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,false); + material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,false); + } + material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,false); + } + + rebind=true; + } + + + if (!*e->additive_ptr) { + + additive=false; + *e->additive_ptr=true; + } else { + additive=true; + } + + + if (stores_glow) + material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,!additive); + + + bool desired_blend=false; + VS::MaterialBlendMode desired_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; + + if (additive) { + desired_blend=true; + desired_blend_mode=VS::MATERIAL_BLEND_MODE_ADD; + } else { + desired_blend=p_alpha_pass; + desired_blend_mode=material->blend_mode; + } + + if (prev_blend!=desired_blend) { + + if (desired_blend) { + glEnable(GL_BLEND); + if (!current_rt || !current_rt_transparent) + glColorMask(1,1,1,0); + } else { + glDisable(GL_BLEND); + glColorMask(1,1,1,1); + + } + + prev_blend=desired_blend; + } + + if (desired_blend && desired_blend_mode!=current_blend_mode) { + + + switch(desired_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(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,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); + 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; + + } + + current_blend_mode=desired_blend_mode; + } + + 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); + + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_COLOR, false); + + + if (material->flags[VS::MATERIAL_FLAG_UNSHADED] == false && current_debug != VS::SCENARIO_DEBUG_SHADELESS) { + + if (baked_light != NULL) { + if (baked_light->realtime_color_enabled) { + float realtime_energy = baked_light->realtime_energy; + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_COLOR, true); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_COLOR, Vector3(baked_light->realtime_color.r*realtime_energy, baked_light->realtime_color.g*realtime_energy, baked_light->realtime_color.b*realtime_energy)); + } + } + + 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) { + + if (baked_light->mode == VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) { + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE, true); + bind_baked_light_octree = true; + if (prev_baked_light != baked_light) { + Texture *tex = texture_owner.get(baked_light->octree_texture); + if (tex) { + + 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) { + + + int lightmap_idx = e->instance->baked_lightmap_id; + + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, false); + bind_baked_lightmap = false; + + + if (baked_light->lightmaps.has(lightmap_idx)) { + + + RID texid = baked_light->lightmaps[lightmap_idx]; + + if (prev_baked_light != baked_light || texid != prev_baked_light_texture) { + + + Texture *tex = texture_owner.get(texid); + if (tex) { + + glActiveTexture(GL_TEXTURE0 + max_texture_units - 3); + glBindTexture(tex->target, tex->tex_id); //bind the texture + } + + prev_baked_light_texture = texid; + } + + if (texid.is_valid()) { + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, true); + bind_baked_lightmap = true; + } + + } + } + } + + if (int(prev_baked_light != NULL) ^ int(baked_light != NULL)) { + rebind = true; + } + } + } // !shadow + + if (sort_flags!=prev_sort_flags) { + + if (sort_flags&RenderList::SORT_FLAG_INSTANCING) { + material_shader.set_conditional(MaterialShaderGLES2::USE_UNIFORM_INSTANCING,!use_texture_instancing && !use_attribute_instancing); + material_shader.set_conditional(MaterialShaderGLES2::USE_ATTRIBUTE_INSTANCING,use_attribute_instancing); + material_shader.set_conditional(MaterialShaderGLES2::USE_TEXTURE_INSTANCING,use_texture_instancing); + } else { + material_shader.set_conditional(MaterialShaderGLES2::USE_UNIFORM_INSTANCING,false); + material_shader.set_conditional(MaterialShaderGLES2::USE_ATTRIBUTE_INSTANCING,false); + material_shader.set_conditional(MaterialShaderGLES2::USE_TEXTURE_INSTANCING,false); + } + rebind=true; + } + + if (use_hw_skeleton_xform && (skeleton!=prev_skeleton||morph_values!=prev_morph_values)) { + if (!prev_skeleton || !skeleton) + rebind=true; //went from skeleton <-> no skeleton, needs rebind + + if (morph_values==NULL) + _setup_skeleton(skeleton); + else + _setup_skeleton(NULL); + } +*/ + if (material!=prev_material || rebind) { + + rebind = _setup_material(e->geometry,material,additive,!p_alpha_pass); + + print("Setup material\n"); + _rinfo.mat_change_count++; + } else { + + if (prev_skeleton!=skeleton) { + //_setup_material_skeleton(material,skeleton); + }; + } + + + if (geometry_cmp!=prev_geometry_cmp || prev_skeleton!=skeleton) { + + _setup_geometry(e->geometry, material,e->skeleton,e->instance->morph_values.ptr()); + _rinfo.surface_count++; +// DEBUG_TEST_ERROR("Setup geometry"); + }; + + // if (i==0 || light!=prev_light || rebind) { + // if (e->light!=0xFFFF) { + _setup_light(e->light); + // } +// _setup_lights(e->lights,e->light_count); + // } +/* + if (bind_baked_light_octree && (baked_light!=prev_baked_light || rebind)) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_INVERSE_TRANSFORM, *e->instance->baked_light_octree_xform); + 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,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); + + + } + + if (bind_baked_lightmap && (baked_light!=prev_baked_light || rebind)) { + + 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); + + + if (i==0 || rebind) { + material_shader.set_uniform(MaterialShaderGLES2::CAMERA_INVERSE_TRANSFORM, p_view_transform_inverse); + material_shader.set_uniform(MaterialShaderGLES2::PROJECTION_TRANSFORM, p_projection); + if (!shadow) { + + if (!additive && current_env && current_env->fx_enabled[VS::ENV_FX_AMBIENT_LIGHT]) { + Color ambcolor = _convert_color(current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR]); + float ambnrg = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY]; + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHT,Vector3(ambcolor.r*ambnrg,ambcolor.g*ambnrg,ambcolor.b*ambnrg)); + } else { + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHT,Vector3()); + } + } + + _rinfo.shader_change_count++; + } + + if (skeleton != prev_skeleton || rebind) { + if (skeleton && morph_values == NULL) { + material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES, max_texture_units - 2); + material_shader.set_uniform(MaterialShaderGLES2::SKELTEX_PIXEL_SIZE, skeleton->pixel_size); + } + } +*/ +// if (e->instance->billboard || e->instance->billboard_y || e->instance->depth_scale) { + if (false) { + print("billboard\n"); + Transform xf=e->instance->transform; + if (e->instance->depth_scale) { + + if (p_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*p_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(); + + if (current_rt && current_rt_vflip) { + xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), -p_view_transform.get_basis().get_axis(1)); + } else { + xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), p_view_transform.get_basis().get_axis(1)); + } + + xf.basis.scale(scale); + } + + if (e->instance->billboard_y) { + + Vector3 scale = xf.basis.get_scale(); + Vector3 look_at = p_view_transform.get_origin(); + look_at.y = 0.0; + Vector3 look_at_norm = look_at.normalized(); + + if (current_rt && current_rt_vflip) { + xf.set_look_at(xf.origin,xf.origin + look_at_norm, Vector3(0.0, -1.0, 0.0)); + } else { + xf.set_look_at(xf.origin,xf.origin + look_at_norm, Vector3(0.0, 1.0, 0.0)); + } + xf.basis.scale(scale); + } +// material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, xf); + + } else { +// Transform tr = camera_transform_inverse * e->instance->transform; + _set_uniform(scene_shader->location_modelview, e->instance->transform); +// material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, e->instance->transform); + } + +// material_shader.set_uniform(MaterialShaderGLES2::NORMAL_MULT, e->mirror?-1.0:1.0); +// material_shader.set_uniform(MaterialShaderGLES2::CONST_LIGHT_MULT,additive?0.0:1.0); + + + _render(e->geometry, material, skeleton,e->owner,e->instance->transform); +// DEBUG_TEST_ERROR("Rendering"); + + prev_material=material; + prev_skeleton=skeleton; + prev_geometry_cmp=geometry_cmp; + prev_light=e->light; + prev_light_type=e->light_type; + prev_sort_flags=sort_flags; + prev_baked_light=baked_light; + prev_morph_values=morph_values; + // prev_receive_shadows_state=receive_shadows_state; + } + + //print_line("shaderchanges: "+itos(p_alpha_pass)+": "+itos(_rinfo.shader_change_count)); + + + if (current_rt && current_rt_vflip) { +// glFrontFace(GL_CW); + } + +}; +/* +void Rasterizer3DS::_setup_fixed_material(const Geometry *p_geometry,const Material *p_material) { + + Color diffuse_color=p_material->parameters[VS::FIXED_MATERIAL_PARAM_DIFFUSE]; + + _set_uniform(scene_shader->location_material, diffuse_color); +}*/ + +bool Rasterizer3DS::_setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light,bool p_opaque_pass) +{ + Texture *texture = NULL; + + if (p_material->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED]) { +// glDisable(GL_CULL_FACE); + // C3D_CullFace(GPU_CULL_NONE); + C3D_CullFace(GPU_CULL_FRONT_CCW); + + } else { +// glEnable(GL_CULL_FACE); + C3D_CullFace(GPU_CULL_NONE); + } + +// C3D_TexEnv* env = C3D_GetTexEnv(0); +// C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, 0); +// C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); +// C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + + C3D_TexEnv *env = C3D_GetTexEnv(1); + + + +// if (p_material->line_width) +// glLineWidth(p_material->line_width); +/* + //all goes to false by default + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PASS,shadow!=NULL); + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,shadow_filter==SHADOW_FILTER_PCF5 || shadow_filter==SHADOW_FILTER_PCF13); + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF13); + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM); + material_shader.set_conditional(MaterialShaderGLES2::USE_LIGHTMAP_ON_UV2,p_material->flags[VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2]); + material_shader.set_conditional(MaterialShaderGLES2::USE_COLOR_ATTRIB_SRGB_TO_LINEAR,p_material->flags[VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB] && current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); + + if (p_opaque_pass && p_material->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA && p_material->shader_cache && p_material->shader_cache->has_alpha) { + + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,true); + } else { + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,false); + + } +*/ + +// if (!shadow) { + + bool depth_test=!p_material->flags[VS::MATERIAL_FLAG_ONTOP]; + bool depth_write=p_material->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_NEVER && (p_opaque_pass || p_material->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_ALWAYS); + //bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW] && (p_opaque_pass || !p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]); + + if (current_depth_mask!=depth_write) + { + current_depth_mask=depth_write; +// glDepthMask( depth_write ); + } + + + if (current_depth_test!=depth_test) + { + current_depth_test=depth_test; +// if(depth_test) +// glEnable(GL_DEPTH_TEST); +// else +// glDisable(GL_DEPTH_TEST); + } + + +// material_shader.set_conditional(MaterialShaderGLES2::USE_FOG,current_env && current_env->fx_enabled[VS::ENV_FX_FOG]); +// } + + +// DEBUG_TEST_ERROR("Pre Shader Bind"); + + bool rebind=false; + +// if (p_material->shader_cache && p_material->shader_cache->valid) { + + // // reduce amount of conditional compilations + // for(int i=0;i<_tex_version_count;i++) + // material_shader.set_conditional((MaterialShaderGLES2::Conditionals)_tex_version[i],false); + + + // material_shader.set_custom_shader(p_material->shader_cache->custom_code_id); + +// if (p_material->shader_version!=p_material->shader_cache->version) { + //shader changed somehow, must update uniforms + +// _update_material_shader_params((Material*)p_material); + +// } +// material_shader.set_custom_shader(p_material->shader_cache->custom_code_id); +// rebind = material_shader.bind(); + +// DEBUG_TEST_ERROR("Shader Bind"); + + //set uniforms! + int texcoord=0; + for (Map::Element *E=p_material->shader_params.front();E;E=E->next()) + { + +// if (E->get().index<0) +// continue; + + if (!texture && E->get().istexture) { + //clearly a texture.. + RID rid = E->get().value; + print("rid:%u\n", rid.get_id()); +// int loc = material_shader.get_custom_uniform_location(E->get().index); //should be automatic.. + + texture=_bind_texture(rid); +// if (rid.is_valid()) { +// texture=texture_owner.get(rid); +// if (!texture) { +// E->get().value=RID(); //nullify, invalid texture +// rid=RID(); +// } +// } + +// glActiveTexture(GL_TEXTURE0+texcoord); +// glUniform1i(loc,texcoord); //TODO - this could happen automatically on compile... + texcoord++; + + } else if (E->get().value.get_type()==Variant::COLOR) {/* + Color c = E->get().value; + C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); + AttrInfo_Init(attrInfo); + // AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position + AttrInfo_AddFixed(attrInfo, 3); // v1=color + C3D_FixedAttribSet(3, c.r, c.g, c.b, c.a);*/ + // + // _set_uniform(scene_shader->location_material, c); + // C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0, (GPU_TEVSRC)0); + // C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + // C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + // C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + + // printf("a\n"); +// material_shader.set_custom_uniform(E->get().index,_convert_color(c)); + } else { +// material_shader.set_custom_uniform(E->get().index,E->get().value); + } + + } + + // _setup_fixed_material(p_geometry,p_material); + + print("texture count: %d\n", texcoord); + + if (texture) + { + print("binding material texture\n"); + C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, GPU_TEXTURE0); + C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); + } + else + { + print("unbinding material texture\n"); + C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS); + C3D_TexEnvOpRgb(env, GPU_TEVOP_RGB_SRC_COLOR); + C3D_TexEnvOpAlpha(env,GPU_TEVOP_A_SRC_ALPHA); + C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + } + + +// 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); +// C3D_TexBind(texcoord, NULL); + +// } +// if (p_material->shader_cache->has_screen_uv) { +// material_shader.set_uniform(MaterialShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height)); +// } +// DEBUG_TEST_ERROR("Material parameters"); + +// if (p_material->shader_cache->uses_time) { +// material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,shader_time_rollback)); +// draw_next_frame=true; +// } + //if uses TIME - draw_next_frame=true + + +// } else { + +// material_shader.set_custom_shader(0); +// rebind = material_shader.bind(); + +// DEBUG_TEST_ERROR("Shader bind2"); +// } + + +/* + if (shadow) { + + float zofs = shadow->base->vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]; + float zslope = shadow->base->vars[VS::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE]; + if (shadow_pass>=1 && shadow->base->type==VS::LIGHT_DIRECTIONAL) { + float m = Math::pow(shadow->base->directional_shadow_param[VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_ZOFFSET_SCALE],shadow_pass); + zofs*=m; + zslope*=m; + } + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_Z_OFFSET,zofs); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_Z_SLOPE_SCALE,zslope); + if (shadow->base->type==VS::LIGHT_OMNI) + material_shader.set_uniform(MaterialShaderGLES2::DUAL_PARABOLOID,shadow->dp); + DEBUG_TEST_ERROR("Shadow uniforms"); + + } + + + if (current_env && current_env->fx_enabled[VS::ENV_FX_FOG]) { + + Color col_begin = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]; + Color col_end = current_env->fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]; + col_begin=_convert_color(col_begin); + col_end=_convert_color(col_end); + float from = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]; + float zf = camera_z_far; + float curve = current_env->fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]; + material_shader.set_uniform(MaterialShaderGLES2::FOG_PARAMS,Vector3(from,zf,curve)); + material_shader.set_uniform(MaterialShaderGLES2::FOG_COLOR_BEGIN,Vector3(col_begin.r,col_begin.g,col_begin.b)); + material_shader.set_uniform(MaterialShaderGLES2::FOG_COLOR_END,Vector3(col_end.r,col_end.g,col_end.b)); + } +*/ + + + //material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,300.0)); + //if uses TIME - draw_next_frame=true + + return rebind; +} + +void Rasterizer3DS::_setup_light(uint16_t p_light) +{ + + LightInstance *li=lights[p_light]; + Light *l=li->base; + Color col_diffuse = (l->colors[VS::LIGHT_COLOR_DIFFUSE]); + Color col_specular=(l->colors[VS::LIGHT_COLOR_SPECULAR]); + // printf("col\n"); + + + // if (l->type!=VS::LIGHT_DIRECTIONAL) { + Vector3 pos = li->transform.get_origin(); + pos = camera_transform_inverse.xform(pos); + + // C3D_FVec lightVec = FVec4_New(pos.x, pos.y, pos.z, 0.0f); + + // C3D_LightPosition(&l->light, &lightVec); + // C3D_LightDiffuse(&l->light, col_diffuse.r, col_diffuse.g, col_diffuse.b); + // C3D_LightSpecular0(&l->light, col_specular.r, col_specular.g, col_specular.b); + // printf("light\n"); + C3D_FVUnifSet(GPU_VERTEX_SHADER, scene_shader->uLoc_lightVec, pos.x, pos.y, pos.z, 0.0f); + C3D_FVUnifSet(GPU_VERTEX_SHADER, scene_shader->uLoc_lightHalfVec,pos.x, pos.y, pos.z, 0.0f); + C3D_FVUnifSet(GPU_VERTEX_SHADER, scene_shader->uLoc_lightClr, col_diffuse.r, col_diffuse.g, col_diffuse.b, 1.0f); + // } + + // if(li->near_shadow_buffer) { + // C3D_LightShadowEnable(&l->light, true); + // } +} + +Error Rasterizer3DS::_setup_geometry(const Geometry *p_geometry, const Material* p_material, const Skeleton *p_skeleton,const float *p_morphs) +{ +} + +void Rasterizer3DS::_add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner,int p_material) +{ +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; + } + + + + + + 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=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;ilights[i]=lights[i]->sort_key; + } + + e->light_count=light_count; + int poslight_count=light_count; + if (poslight_count>1) { + SortArray light_sort; + light_sort.sort(&e->lights[0],poslight_count); //generate an equal sort key + } + } + + } + +} + +static const GPU_Primitive_t gl_primitive[]={ + GPU_TRIANGLES, + GPU_TRIANGLES, + GPU_TRIANGLES, + GPU_TRIANGLES, + GPU_TRIANGLES, + GPU_TRIANGLE_STRIP, + GPU_TRIANGLE_FAN +}; + +void Rasterizer3DS::_render(const Geometry *p_geometry,const Material *p_material, const Skeleton* p_skeleton, const GeometryOwner *p_owner,const Transform& p_xform) +{ + _rinfo.object_count++; + + C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); + AttrInfo_Init(attrInfo); + + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + + switch(p_geometry->type) { + + case Geometry::GEOMETRY_SURFACE: { + + Surface *s = (Surface*)p_geometry; + + bool has_tex = (s->stride > 24); +// bool has_tex = s->array[VS::ARRAY_TEX_UV].bind; + + print("stride:%d primitive:%d\n", s->stride, (int)gl_primitive[s->primitive]); + + AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=vertex + AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 3); // v1=normal + if (has_tex) + AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 2); // v2=tex_uv + else + { + /* + AttrInfo_AddFixed(attrInfo, 3); + C3D_FixedAttribSet(3, 1.f, 1.f, 1.f, 1.f);*/ + // AttrInfo_AddLoader(attrInfo, 3, GPU_FLOAT, 4); + // BufInfo_Add(bufInfo, s->array_local, s->stride, has_tex ? 3 : 2, has_tex ? 0x210 : 0x10); + + } + + BufInfo_Add(bufInfo, s->array_local, s->stride, has_tex ? 3 : 2, has_tex ? 0x210 : 0x10); + + _rinfo.vertex_count+=s->array_len; + + if (s->index_array_len>0) { + + if (s->index_array_local) + { + print("index len: %u\n", s->array[VS::ARRAY_INDEX].size); + + //print_line("LOCAL F: "+itos(s->format)+" C: "+itos(s->index_array_len)+" VC: "+itos(s->array_len)); +// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); +// glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT, s->index_array_local); + + C3D_DrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array[VS::ARRAY_INDEX].size == 2) ? C3D_UNSIGNED_SHORT : C3D_UNSIGNED_BYTE, s->index_array_local); + + } + + } else { + +// glDrawArrays(gl_primitive[s->primitive],0,s->array_len); + C3D_DrawArrays(gl_primitive[s->primitive], 0, s->array_len); + + }; + + _rinfo.draw_calls++; + } break; + + case Geometry::GEOMETRY_MULTISURFACE: { + +// material_shader.bind_uniforms(); + Surface *s = static_cast(p_geometry)->surface; + const MultiMesh *mm = static_cast(p_owner); + int element_count=mm->elements.size(); + + if (element_count==0) + return; + + if (mm->visible>=0) { + element_count=MIN(element_count,mm->visible); + } + + const MultiMesh::Element *elements=&mm->elements[0]; + + _rinfo.vertex_count+=s->array_len*element_count; + + _rinfo.draw_calls+=element_count; + +/* + if (use_texture_instancing) { + //this is probably the fastest all around way if vertex texture fetch is supported + + 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_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) { + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); + for(int i=0;itw>>2))*twd; + parm[1]=(i/(mm->tw>>2))*thd; + glVertexAttrib3fv(6,parm); + glDrawElements(gl_primitive[s->primitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0); + + } + + + } else { + + for(int i=0;itw>>2))*twd; + //parm[1]=(i/(mm->tw>>2))*thd; + glVertexAttrib3fv(6,parm); + glDrawArrays(gl_primitive[s->primitive],0,s->array_len); + } + }; + + } else if (use_attribute_instancing) { + //if not, using atributes instead of uniforms can be really fast in forward rendering architectures + if (s->index_array_len>0) { + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); + for(int i=0;iprimitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0); + } + + + } else { + + for(int i=0;iprimitive],0,s->array_len); + } + }; + + + } else { + + //nothing to do, slow path (hope no hardware has to use it... but you never know) + + if (s->index_array_len>0) { + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); + for(int i=0;iprimitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0); + } + + + } else { + + for(int i=0;iprimitive],0,s->array_len); + } + }; + } +*/ + } break; +/* + case Geometry::GEOMETRY_IMMEDIATE: { + + bool restore_tex=false; + const Immediate *im = static_cast( p_geometry ); + if (im->building) { + return; + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + for(const List::Element *E=im->chunks.front();E;E=E->next()) { + + const Immediate::Chunk &c=E->get(); + if (c.vertices.empty()) { + continue; + } + for(int i=0;itarget,t->tex_id); + restore_tex=true; + + + } else if (restore_tex) { + + glActiveTexture(GL_TEXTURE0+tc0_idx); + glBindTexture(GL_TEXTURE_2D,tc0_id_cache); + restore_tex=false; + } + + if (!c.normals.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_NORMAL); + glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false,sizeof(Vector3),c.normals.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_NORMAL); + } + + if (!c.tangents.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TANGENT); + glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false,sizeof(Plane),c.tangents.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TANGENT); + } + + if (!c.colors.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false,sizeof(Color),c.colors.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_COLOR); + _set_color_attrib(Color(1, 1, 1,1)); + } + + + if (!c.uvs.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + if (!c.uvs2.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); + glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs2.ptr()); + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); + } + + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false,sizeof(Vector3),c.vertices.ptr()); + glDrawArrays(gl_primitive[c.primitive],0,c.vertices.size()); + + + } + + + if (restore_tex) { + + glActiveTexture(GL_TEXTURE0+tc0_idx); + glBindTexture(GL_TEXTURE_2D,tc0_id_cache); + restore_tex=false; + } + + + } break; +`*/ + case Geometry::GEOMETRY_PARTICLES: { + + //print_line("particulinas"); + const Particles *particles = static_cast( 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); + + + Transform camera; +// if (shadow) +// camera=shadow->transform; +// else + camera=camera_transform; + + particle_draw_info.prepare(&particles->data,&pp,particles_instance->transform,camera); + _rinfo.draw_calls+=particles->data.amount; + + + _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) + }; + + for(int i=0;idata.amount;i++) { + + ParticleSystemDrawInfoSW::ParticleDrawInfo &pinfo=*particle_draw_info.draw_info_order[i]; + if (!pinfo.data->active) + continue; + +// material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, pinfo.transform); +// _set_color_attrib(pinfo.color); +// _draw_primitive(4,points,normals,NULL,uvs,tangents); + } + } + + } break; + default: break; + }; +} + +void Rasterizer3DS::_draw_quad(const Rect2& p_rect) +{ + VertexArray *varray = memnew(VertexArray(4)); + varray->vertices[0].position = Vector3( p_rect.pos.x,p_rect.pos.y, 0.5f ); + varray->vertices[1].position = Vector3( p_rect.pos.x+p_rect.size.width,p_rect.pos.y, 0.5f ); + varray->vertices[2].position = Vector3( p_rect.pos.x+p_rect.size.width,p_rect.pos.y+p_rect.size.height, 0.5f ); + varray->vertices[3].position = Vector3( p_rect.pos.x,p_rect.pos.y+p_rect.size.height, 0.5f ); + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, varray->vertices, sizeof(Vertex), 2, 0x10); + + C3D_DrawArrays(GPU_TRIANGLE_FAN, 0, 4); + + vertexArrays.push_back(varray); +// C3D_Flush(); +// _draw_gui_primitive(4,coords,0,0); +// _rinfo.ci_draw_commands++; +} + +void Rasterizer3DS::_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 ) +{ +// print("_draw_textured_quad\n"); + VertexArray *varray = memnew(VertexArray(4)); + + Vertex v[4] = { + { + Vector3( p_rect.pos.x, p_rect.pos.y, 0.5f), + Vector2( p_src_region.pos.x/p_tex_size.width, p_src_region.pos.y/p_tex_size.height) + },{ + Vector3( p_rect.pos.x+p_rect.size.width, p_rect.pos.y, 0.5f), + Vector2((p_src_region.pos.x+p_src_region.size.width)/p_tex_size.width, p_src_region.pos.y/p_tex_size.height) + },{ + Vector3( p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height, 0.5f), + Vector2( (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) + },{ + Vector3( p_rect.pos.x,p_rect.pos.y+p_rect.size.height, 0.5f), + Vector2( p_src_region.pos.x/p_tex_size.width, (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height) + }, + }; + + memcpy(varray->vertices, v, sizeof(v)); + + if (p_transpose) { + SWAP( varray->vertices[1].texcoord, varray->vertices[3].texcoord ); + } + if (p_h_flip) { + SWAP( varray->vertices[0].texcoord, varray->vertices[1].texcoord ); + SWAP( varray->vertices[2].texcoord, varray->vertices[3].texcoord ); + } + if (p_v_flip) { + SWAP( varray->vertices[1].texcoord, varray->vertices[2].texcoord ); + SWAP( varray->vertices[0].texcoord, varray->vertices[3].texcoord ); + } + + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, varray->vertices, sizeof(Vertex), 2, 0x10); + + C3D_DrawArrays(GPU_TRIANGLE_FAN, 0, 4); + + vertexArrays.push_back(varray); +// _draw_gui_primitive(4,coords,0,texcoords); +// _rinfo.ci_draw_commands++; +} + +static const C3D_Material material = + { + { 0.2f, 0.2f, 0.2f }, //ambient + { 0.4f, 0.4f, 0.4f }, //diffuse + { 0.8f, 0.8f, 0.8f }, //specular0 + { 0.0f, 0.0f, 0.0f }, //specular1 + { 0.0f, 0.0f, 0.0f }, //emission + }; + +int Rasterizer3DS::RenderList::max_elements; + +void Rasterizer3DS::init() +{ + print("citro init "); + C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); + draw_next_frame = false; + + canvas_shader = memnew(Shader); + canvas_shader->set_data(shader_builtin_2d, sizeof(shader_builtin_2d)); + + scene_shader = memnew(Shader); + scene_shader->set_data_3d(shader_builtin_3d, sizeof(shader_builtin_3d)); + + // Setup default render target (screen framebuffer) + base_framebuffer = memnew(RenderTarget); + Texture *texture = memnew(Texture); + + base_framebuffer->target = C3D_RenderTargetCreate(480, 800, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(base_framebuffer->target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + C3D_RenderTargetClear(base_framebuffer->target,C3D_CLEAR_ALL,CLEAR_COLOR,0); + base_framebuffer->texture_ptr = texture; + base_framebuffer->texture = texture_owner.make_rid( texture ); + + // Frag lighting + + C3D_LightEnvInit(&lightEnv); + C3D_LightEnvBind(&lightEnv); + C3D_LightEnvMaterial(&lightEnv, &material); + + LightLut_Phong(&lut_Phong, 30); + C3D_LightEnvLut(&lightEnv, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &lut_Phong); + + C3D_FVec lightVec = { { 1.0, -1.5, 0.0, 0.0 } }; + + + +// C3D_LightInit(&light, &lightEnv); +// C3D_LightColor(&light, 1.0, 1.0, 1.0); +// C3D_LightPosition(&light, &lightVec); + +// C3D_LightSpotEnable(&light, true); +// C3D_LightSpotDir(&light, 1.0, 1.0, 1.0); + /* + const C3D_Material material = + { + { 0.0f, 0.0f, 0.0f }, //ambient + { 1.0f, 0.0f, 0.4f }, //diffuse + { 0.8f, 0.8f, 0.8f }, //specular0 + { 0.0f, 0.0f, 0.0f }, //specular1 + { 0.0f, 0.0f, 0.0f }, //emission + }; + + C3D_LightEnvInit(&lightEnv); + C3D_LightEnvBind(&lightEnv); + C3D_LightEnvMaterial(&lightEnv, &material); + + LightLut_Phong(&lut_Phong, 30); + C3D_LightEnvLut(&lightEnv, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &lut_Phong); + + C3D_LightInit(&light, &lightEnv);*/ + + C3D_DepthTest(false, GPU_GEQUAL, GPU_WRITE_ALL); +// C3D_CullFace(GPU_CULL_FRONT_CCW); + C3D_CullFace(GPU_CULL_NONE); + + 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(); + C3D_SetFrameBuf(&base_framebuffer->target->frameBuf); + + + // render_target_create(); +} + +void Rasterizer3DS::finish() +{ + print("citro finish\n"); + + memdelete(canvas_shader); + memdelete(scene_shader); + memdelete(base_framebuffer->texture_ptr); + memdelete(base_framebuffer); + + C3D_Fini(); +} + +int Rasterizer3DS::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_DRAW_CALLS_IN_FRAME: { + + return _rinfo.draw_calls; + } break; + case VS::INFO_SURFACE_CHANGES_IN_FRAME: { + + return _rinfo.surface_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: { + + return _rinfo.texture_mem; + } break; + case VS::INFO_VERTEX_MEM_USED: { + + return 0; + } break; + } + + return 0; +} + +bool Rasterizer3DS::needs_to_draw_next_frame() const +{ + return false; + return draw_next_frame; +} + + +bool Rasterizer3DS::has_feature(VS::Features p_feature) const +{ + switch (p_feature) { + default: + case VS::FEATURE_MULTITHREADED: return false; + case VS::FEATURE_SHADERS: return true; + case VS::FEATURE_NEEDS_RELOAD_HOOK: return false; + } +} + +void Rasterizer3DS::restore_framebuffer() +{ + print("restore_framebuffer\n"); + current_rt = NULL; + C3D_SetFrameBuf(&base_framebuffer->target->frameBuf); +} + +Rasterizer3DS::Rasterizer3DS() +: current_rt (NULL) +{ + +}; + +Rasterizer3DS::~Rasterizer3DS() +{ + +}; + +// #endif diff --git a/platform/vita/rasterizer_vita.h b/platform/3ds/rasterizer_3ds.h similarity index 73% rename from platform/vita/rasterizer_vita.h rename to platform/3ds/rasterizer_3ds.h index 9fdcae74..49dfb6e5 100644 --- a/platform/vita/rasterizer_vita.h +++ b/platform/3ds/rasterizer_3ds.h @@ -1,11 +1,11 @@ /*************************************************************************/ -/* rasterizer_gles1.h */ +/* rasterizer_citro3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2016 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 */ @@ -26,13 +26,11 @@ /* 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 +#ifndef RASTERIZER_3DS_H +#define RASTERIZER_3DS_H #include "servers/visual/rasterizer.h" -#ifdef __psp2__ - #include "image.h" #include "rid.h" #include "servers/visual_server.h" @@ -40,96 +38,40 @@ #include "map.h" #include "camera_matrix.h" #include "sort.h" -// #include "tools/editor/scene_tree_editor.h" -#include "platform_config.h" -#ifndef GLES1_INCLUDE_H -#include -// #include "immvertex.h" -#else -#include GLES1_INCLUDE_H -#endif - #include "servers/visual/particle_system_sw.h" -/** - @author Juan Linietsky -*/ -class RasterizerGLES1 : public Rasterizer { - - enum { - - MAX_SCENE_LIGHTS=2048, - LIGHT_SPOT_BIT=0x80, - DEFAULT_SKINNED_BUFFER_SIZE = 1024 * 1024, // 10k vertices - MAX_HW_LIGHTS = 8, //yay! pvrpsp2 supports 8 hw lights - }; - #ifdef PSP - void glActiveTexture(int a1) { }; - void glClientActiveTexture(int a1) { }; - #endif - - GLuint BlurTexture; - - 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; - bool is_editor; - - - 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); +#ifdef __3DS__ +extern "C" { +#include <3ds/types.h> +#include <3ds/gpu/gpu.h> +#include <3ds/gfx.h> +#include <3ds/gpu/gx.h> +#include <3ds/gpu/shaderProgram.h> +#include <3ds/allocator/linear.h> +} +#undef __3DS__ +#include +#define __3DS__ +#endif +class Rasterizer3DS : public Rasterizer { struct Texture { uint32_t flags; int width,height; - int alloc_width, alloc_height; + C3D_Tex tex; 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() { - + tex.data = NULL; 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); - } } }; @@ -148,58 +90,99 @@ class RasterizerGLES1 : public Rasterizer { bool valid; bool has_alpha; bool use_world_transform; - + + DVLB_s* dvlb; + shaderProgram_s program; + + int location_projection; + int location_modelview; + int location_worldTransform; + int location_extra; + int location_material; + int uLoc_lightVec, uLoc_lightHalfVec, uLoc_lightClr; + + void set_data(void* data, u32 size) + { + dvlb = DVLB_ParseFile(reinterpret_cast(data), size); + shaderProgramSetVsh(&program, &dvlb->DVLE[0]); + location_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection"); + location_modelview = shaderInstanceGetUniformLocation(program.vertexShader, "modelView"); + location_worldTransform = shaderInstanceGetUniformLocation(program.vertexShader, "worldTransform"); + location_extra = shaderInstanceGetUniformLocation(program.vertexShader, "extra"); + } + + void set_data_3d(void* data, u32 size) + { + dvlb = DVLB_ParseFile(reinterpret_cast(data), size); + shaderProgramSetVsh(&program, &dvlb->DVLE[0]); + location_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection"); + location_modelview = shaderInstanceGetUniformLocation(program.vertexShader, "modelView"); + location_worldTransform = shaderInstanceGetUniformLocation(program.vertexShader, "worldTransform"); + location_extra = shaderInstanceGetUniformLocation(program.vertexShader, "extra"); + + uLoc_lightVec = shaderInstanceGetUniformLocation(program.vertexShader, "lightVec"); + uLoc_lightHalfVec = shaderInstanceGetUniformLocation(program.vertexShader, "lightHalfVec"); + uLoc_lightClr = shaderInstanceGetUniformLocation(program.vertexShader, "lightClr"); + location_material = shaderInstanceGetUniformLocation(program.vertexShader, "material"); + } + + Shader() + { + dvlb = NULL; + shaderProgramInit(&program); + } + ~Shader() + { + shaderProgramFree(&program); + if (dvlb) + DVLB_Free(dvlb); + } }; mutable RID_Owner shader_owner; + + Shader* canvas_shader; + Shader* scene_shader; + 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]; + bool fixed_flags[VS::FIXED_MATERIAL_FLAG_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; + Shader *shader_cache; - Map shader_params; - + struct UniformData { + bool inuse; + bool istexture; + Variant value; + int index; + }; + + Map shader_params; Material() { - for(int i=0;i skeleton_bone_aabb; + Vector skeleton_bone_used; - bool packed; + //bool packed; struct MorphTarget { uint32_t configured_format; @@ -278,6 +260,8 @@ class RasterizerGLES1 : public Rasterizer { float uv_scale; float uv2_scale; + bool alpha_sort; + VS::PrimitiveType primitive; uint32_t format; @@ -292,9 +276,8 @@ class RasterizerGLES1 : public Rasterizer { Point2 uv_min; Point2 uv_max; - Surface() { - - + Surface() + { array_len=0; local_stride=0; morph_format=0; @@ -305,16 +288,17 @@ class RasterizerGLES1 : public Rasterizer { uv_scale=1.0; uv2_scale=1.0; + alpha_sort=false; + format=0; stride=0; morph_targets_local=0; morph_target_count=0; - array_local = index_array_local = 0; - vertex_id = index_id = 0; + array_local = index_array_local = NULL; active=false; - packed=false; + //packed=false; } ~Surface() { @@ -341,8 +325,6 @@ class RasterizerGLES1 : public Rasterizer { }; mutable RID_Owner 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 { @@ -355,31 +337,8 @@ class RasterizerGLES1 : public Rasterizer { struct Element { - float matrix[16]; - uint8_t color[4]; - Element() { - matrix[0]=1; - matrix[1]=0; - matrix[2]=0; - matrix[3]=0; - - matrix[4]=0; - matrix[5]=1; - matrix[6]=0; - matrix[7]=0; - - matrix[8]=0; - matrix[9]=0; - matrix[10]=1; - matrix[11]=0; - - matrix[12]=0; - matrix[13]=0; - matrix[14]=0; - matrix[15]=1; - }; - - + Transform xform; + Color color; }; AABB aabb; @@ -388,29 +347,20 @@ class RasterizerGLES1 : public Rasterizer { //IDirect3DVertexBuffer9* instance_buffer; Vector elements; - Vector cache_surfaces; - mutable uint64_t last_pass; - GLuint tex_id; - int tw; - int th; - SelfList dirty_list; + MultiMesh() { + visible=-1; + } - MultiMesh() : dirty_list(this) { - tw=1; - th=1; - tex_id=0; - last_pass=0; - visible = -1; - } }; + mutable RID_Owner multimesh_owner; - mutable SelfList::List _multimesh_dirty_list; struct Immediate { + RID material; int empty; }; @@ -460,7 +410,8 @@ class RasterizerGLES1 : public Rasterizer { RID projector; bool volumetric_enabled; Color volumetric_color; - + + C3D_Light light; Light() { @@ -477,17 +428,20 @@ class RasterizerGLES1 : public Rasterizer { volumetric_enabled=false; } }; + + // C3D_Light light; + C3D_LightEnv lightEnv; + C3D_LightLut lut_Phong; struct Environment { - + Variant group[VS::ENV_GROUP_MAX]; 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]; - Variant group[VS::ENV_GROUP_MAX]; - + Environment() { bg_mode=VS::ENV_BG_DEFAULT_COLOR; @@ -521,19 +475,16 @@ class RasterizerGLES1 : public Rasterizer { fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0; fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0; + } }; mutable RID_Owner environment_owner; - Environment *current_env; - + struct SampledLight { int w,h; - GLuint texture; - float multiplier; - bool is_float; }; mutable RID_Owner sampled_light_owner; @@ -561,70 +512,121 @@ class RasterizerGLES1 : public Rasterizer { Vector3 light_vector; Vector3 spot_vector; float linear_att; - - uint64_t shadow_pass; uint64_t last_pass; uint16_t sort_key; - Vector shadow_buffers; + LightInstance() { linear_att=1.0; } + + }; - void clear_shadow_buffers() { + mutable RID_Owner light_owner; + mutable RID_Owner light_instance_owner; + + LightInstance *shadow; + uint64_t scene_pass; + /*********/ + /* FRAME */ + /*********/ - for (int i=0;iowner != this ); + int texture_mem; + int vertex_count; + int object_count; + int mat_change_count; + int surface_count; + int shader_change_count; + int ci_draw_commands; + int draw_calls; - sb->owner=NULL; - } + } _rinfo; + + + /*******************/ + /* CANVAS OCCLUDER */ + /*******************/ + struct CanvasOccluder { + + u32 vertex_id; // 0 means, unconfigured + u32 index_id; // 0 means, unconfigured + DVector lines; + int len; + }; - shadow_buffers.clear(); - } + RID_Owner canvas_occluder_owner; - LightInstance() { shadow_pass=0; last_pass=0; sort_key=0; } + /***********************/ + /* CANVAS LIGHT SHADOW */ + /***********************/ + struct CanvasLightShadow { - }; - mutable RID_Owner light_owner; - mutable RID_Owner light_instance_owner; + int size; + int height; + + C3D_RenderTarget *renderTarget; + C3D_Tex texture; + + u32 fbo; + u32 rbo; + u32 depth; + u32 rgba; //for older devices - 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; + u32 blur; + }; + RID_Owner canvas_light_shadow_owner; + RID canvas_shadow_blur; + + + struct RenderTarget + { + Texture *texture_ptr; + RID texture; + C3D_RenderTarget *target; + }; + mutable RID_Owner render_target_owner; + + struct RenderList { enum { - MAX_ELEMENTS=4096, - MAX_LIGHTS=8192 + DEFAULT_MAX_ELEMENTS=4096, + MAX_LIGHTS=8, + SORT_FLAG_SKELETON=1, + SORT_FLAG_INSTANCING=2, }; - struct Element { - + static int max_elements; + 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 Geometry *geometry_cmp; const Material *material; const GeometryOwner *owner; - uint16_t light_count; + bool *additive_ptr; + bool additive; + uint16_t lights[MAX_LIGHTS]; bool mirror; - - + uint16_t light_count; + union { + struct { + uint16_t light; + uint8_t light_type; + uint8_t sort_flags; + }; + + uint64_t light_key; + uint32_t sort_key; + }; }; - Element _elements[MAX_ELEMENTS]; - Element *elements[MAX_ELEMENTS]; + Element *_elements; + Element **elements; int element_count; void clear() { @@ -647,23 +649,28 @@ class RasterizerGLES1 : public Rasterizer { } - struct SortMat { + struct SortMatGeom { _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { // TODO move to a single uint64 (one comparison) - if (A->material == B->material) { + if (A->material->shader_cache == B->material->shader_cache) { + if (A->material == B->material) { - return A->light_key < B->light_key; + return A->geometry_cmp < B->geometry_cmp; + } else { + + return (A->material < B->material); + } } else { - return (A->material < B->material); + return A->material->shader_cache < B->material->shader_cache; } } }; - void sort_mat() { + void sort_mat_geom() { - SortArray sorter; + SortArray sorter; sorter.sort(elements,element_count); } @@ -671,22 +678,18 @@ class RasterizerGLES1 : public Rasterizer { _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->geometry_cmp == B->geometry_cmp) { if (A->material == B->material) { - if (A->geometry == B->geometry) { - - return A->light_keylight_key; - } else - return (A->geometry < B->geometry); + return A->lightlight; } else { return (A->material < B->material); } } else { - return (int(A->material->flags[VS::MATERIAL_FLAG_UNSHADED]) < int(B->material->flags[VS::MATERIAL_FLAG_UNSHADED])); + return (A->geometry_cmp < B->geometry_cmp); } } }; @@ -697,196 +700,189 @@ class RasterizerGLES1 : public Rasterizer { sorter.sort(elements,element_count); } - _FORCE_INLINE_ Element* add_element() { + struct SortMatLightType { - 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;ilight_type == B->light_type) { + if (A->material->shader_cache == B->material->shader_cache) { + if (A->material == B->material) { - bool glow_active; - int glow_passes; - float glow_attenuation; - float glow_bloom; + return (A->geometry_cmp < B->geometry_cmp); + } else { - bool ssao_active; - float ssao_attenuation; - float ssao_radius; - float ssao_max_distance; - float ssao_range_max; - float ssao_range_min; - bool ssao_only; + return (A->material < B->material); + } + } else { - bool fog_active; - float fog_near; - float fog_far; - float fog_attenuation; - Color fog_color_near; - Color fog_color_far; - bool fog_bg; + return (A->material->shader_cache < B->material->shader_cache); + } + } else { - bool toon_active; - float toon_treshold; - float toon_soft; + return A->light_type < B->light_type; + } + } + }; - bool edge_active; - Color edge_color; - float edge_size; + void sort_mat_light_type() { - FX(); + SortArray sorter; + sorter.sort(elements,element_count); + } - }; - mutable RID_Owner fx_owner; + struct SortMatLightTypeFlags { + _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { - 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; + if (A->sort_key == B->sort_key) { + if (A->material->shader_cache == B->material->shader_cache) { + if (A->material == B->material) { - Plane camera_plane; + return (A->geometry_cmp < B->geometry_cmp); + } else { - bool keep_copies; + return (A->material < B->material); + } + } else { - bool depth_write; - bool depth_test; - int blend_mode; - bool lighting; + return (A->material->shader_cache < B->material->shader_cache); + } + } else { - _FORCE_INLINE_ void _add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner); + return A->sort_key < B->sort_key; //one is null and one is not + } + } + }; - void _render_list_forward(RenderList *p_render_list,bool p_reverse_cull=false); + void sort_mat_light_type_flags() { - void _setup_light(LightInstance* p_instance, int p_idx); - void _setup_lights(const uint16_t * p_lights,int p_light_count); + SortArray sorter; + sorter.sort(elements,element_count); + } + _FORCE_INLINE_ Element* add_element() { - _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); + if (element_count>=max_elements) + return NULL; + elements[element_count]=&_elements[element_count]; + return elements[element_count++]; + } - 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); + void init() { + element_count = 0; + elements=memnew_arr(Element*,max_elements); + _elements=memnew_arr(Element,max_elements); + for (int i=0;i near_shadow_buffers; - Vector 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& p_buffers); - void _debug_draw_shadow(GLuint tex, const Rect2& p_rect); - void _debug_draw_shadows_type(Vector& 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 { + Environment *current_env; + + RenderList opaque_render_list; + RenderList alpha_render_list; - int texture_mem; - int vertex_count; - int object_count; - int mat_change_count; - int shader_change_count; - } _rinfo; + RID default_material; - GLuint white_tex; - RID canvas_tex; + + RenderTarget* base_framebuffer; + RenderTarget* current_rt; + bool current_rt_transparent; + bool current_rt_vflip; +// ViewportData *current_vd; + + bool fragment_lighting; + bool draw_next_frame; + + int last_light_id; + bool current_depth_test; + bool current_depth_mask; + + CameraMatrix camera_projection; + Transform camera_transform; + Transform camera_transform_inverse; + float camera_z_near; + float camera_z_far; + Size2 camera_vp_size; + bool camera_ortho; + Plane camera_plane; + + + LightInstance *lights[RenderList::MAX_LIGHTS]; + int light_count=0; + 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); + VS::MaterialBlendMode canvas_blend_mode; + Matrix32 canvas_transform; + + float last_time = 0.0; + float time_delta = 0.0; + float time_scale = 0.0; + float scaled_time = 0.0; + int frame = 0; + + struct Vertex { + Vector3 position; + Vector2 texcoord; + Color color; + }; + + struct VertexArray { + Vertex *vertices; +// int count; + VertexArray(int vertexCount) { +// count = vertexCount; + vertices = reinterpret_cast(linearAlloc(sizeof(Vertex) * vertexCount)); + } + ~VertexArray() { + linearFree(vertices); + } + }; + + Vector vertexArrays; + + // LightInstance *light_instances[MAX_SCENE_LIGHTS]; + // LightInstance *directional_lights[4]; + // int light_instance_count; + + Error _surface_set_arrays(Surface *p_surface, uint8_t *p_mem,uint8_t *p_index_mem,const Array& p_arrays,bool p_main); + + bool _setup_material(const Geometry *p_geometry, const Material *p_material, bool p_no_const_light, bool p_opaque_pass); +// void _setup_skeleton(const Skeleton *p_skeleton); + void _setup_light(uint16_t p_light); + + + 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,const Transform& p_xform); - Size2 window_size; - VS::ViewportRect viewport; - double last_time; - double time_delta; - uint64_t frame; - uint64_t scene_pass; + void _set_uniform(int uniform_location, const Matrix32& p_transform); + void _set_uniform(int uniform_location, const Transform& p_transform); + void _set_uniform(int uniform_location, const CameraMatrix& p_matrix); + void _set_uniform(int uniform_location, const Color& p_color); + + // void _set_canvas_scissor(CanvasItem* p_item); + Texture *_bind_texture(const RID& p_texture); + + void _add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner,int p_material=-1); + + void _render_list_forward(RenderList *p_render_list,const Transform& p_view_transform,const Transform& p_view_transform_inverse, const CameraMatrix& p_projection,bool p_reverse_cull=false,bool p_fragment_light=false,bool p_alpha_pass=false); + + void _draw_quad(const Rect2& p_rect); + 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); + + // template + // _FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip); - //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); - void _process_blur(int times, float inc); public: @@ -905,6 +901,12 @@ class RasterizerGLES1 : public Rasterizer { 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; + virtual void texture_set_path(RID p_texture,const String& p_path) {} + virtual String texture_get_path(RID p_texture) const { return String(); } + // virtual void texture_debug_usage(List *r_info) {} + + virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable) {} + /* SHADER API */ virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL); @@ -919,6 +921,12 @@ class RasterizerGLES1 : public Rasterizer { virtual void shader_get_param_list(RID p_shader, List *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 */ virtual RID material_create(); @@ -941,28 +949,6 @@ class RasterizerGLES1 : public Rasterizer { 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 */ @@ -995,6 +981,7 @@ class RasterizerGLES1 : public Rasterizer { 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(); @@ -1028,10 +1015,10 @@ class RasterizerGLES1 : public Rasterizer { 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; + virtual AABB immediate_get_aabb(RID p_mesh) const; /* PARTICLES API */ @@ -1176,6 +1163,7 @@ class RasterizerGLES1 : public Rasterizer { virtual void begin_frame(); virtual void set_viewport(const VS::ViewportRect& p_viewport); + virtual void set_time_scale(float p_scale); 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); @@ -1191,16 +1179,18 @@ class RasterizerGLES1 : public Rasterizer { 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_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(); + virtual void flush_frame(); /* CANVAS API */ + virtual void begin_canvas_bg(); virtual void canvas_begin(); virtual void canvas_disable_blending(); virtual void canvas_set_opacity(float p_opacity); @@ -1215,15 +1205,15 @@ class RasterizerGLES1 : public Rasterizer { 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 void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light); + + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector& p_lines); + + 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); - virtual RID fx_create(); - virtual void fx_get_effects(RID p_fx,List *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 *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); + // virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow); /* ENVIRONMENT */ @@ -1235,11 +1225,11 @@ class RasterizerGLES1 : public Rasterizer { 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_group(RID p_env,VS::Group p_group, const Variant& p_param); - virtual Variant environment_get_group(RID p_env, VS::Group 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_set_group(RID p_env,VS::Group p_group, const Variant& p_param); + virtual Variant environment_get_group(RID p_env, VS::Group p_param) 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; @@ -1254,8 +1244,8 @@ class RasterizerGLES1 : public Rasterizer { 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_multimesh(const RID& p_rid) const; virtual bool is_particles(const RID &p_beam) const; virtual bool is_light(const RID& p_rid) const; @@ -1263,7 +1253,8 @@ class RasterizerGLES1 : public Rasterizer { 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_canvas_light_occluder(const RID& p_rid) const; + virtual bool is_shader(const RID& p_rid) const; virtual void free(const RID& p_rid); @@ -1281,20 +1272,15 @@ class RasterizerGLES1 : public Rasterizer { 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; + virtual void restore_framebuffer(); -#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(); + Rasterizer3DS(); + virtual ~Rasterizer3DS(); }; -#endif -#endif + +#endif // RASTERIZER_CITRO3D_H diff --git a/platform/3ds/shaders/2d.h b/platform/3ds/shaders/2d.h new file mode 100644 index 00000000..447fb012 --- /dev/null +++ b/platform/3ds/shaders/2d.h @@ -0,0 +1,3 @@ +/* Auto-generated from platform/3ds/shaders/2d.shbin */ +static uint8_t shader_builtin_2d[] = +{68,86,76,66,1,0,0,0,176,0,0,0,68,86,76,80,0,0,0,0,40,0,0,0,17,0,0,0,108,0,0,0,7,0,0,0,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,1,240,7,78,2,136,34,10,3,152,34,10,4,168,34,10,5,184,34,10,130,72,66,10,131,88,66,10,132,104,66,10,133,120,66,10,2,9,2,8,3,25,2,8,4,41,2,8,5,57,2,8,6,16,32,76,6,32,64,76,0,0,0,136,110,3,0,0,0,0,0,0,161,10,0,0,0,0,0,0,104,195,6,0,0,0,0,0,100,195,6,0,0,0,0,0,98,195,6,0,0,0,0,0,97,195,6,0,0,0,0,0,111,3,0,0,0,0,0,0,68,86,76,69,2,16,0,0,0,0,0,0,17,0,0,0,0,0,7,0,0,0,0,0,64,0,0,0,1,0,0,0,84,0,0,0,0,0,0,0,84,0,0,0,3,0,0,0,108,0,0,0,3,0,0,0,132,0,0,0,27,0,0,0,2,0,95,0,0,0,0,0,0,0,63,0,0,0,191,0,0,0,190,0,0,0,0,0,15,0,0,0,3,0,1,0,15,0,0,0,2,0,2,0,15,0,0,0,0,0,0,0,16,0,19,0,11,0,0,0,20,0,23,0,21,0,0,0,24,0,27,0,112,114,111,106,101,99,116,105,111,110,0,109,111,100,101,108,86,105,101,119,0,101,120,116,114,97,0,0}; \ No newline at end of file diff --git a/platform/3ds/shaders/2d.pica b/platform/3ds/shaders/2d.pica new file mode 100644 index 00000000..c9d1c60f --- /dev/null +++ b/platform/3ds/shaders/2d.pica @@ -0,0 +1,48 @@ +; Uniforms +.fvec projection[4], modelView[4], extra[4] + +; Constants +.constf myconst(0.0, 1.0, -1.0, -0.5) +;.constf myconst2(0.3, 0.0, 0.0, 0.0) +.alias zeros myconst.xxxx ; Vector full of zeros +.alias ones myconst.yyyy ; Vector full of ones + +; Outputs +.out outpos position +.out outtc0 texcoord0 +.out outclr color + +; Inputs (defined as aliases for convenience) +.alias inpos v0 +.alias intex v1 +.alias incol v2 + +.proc main + ; Force the w component of inpos to be 1.0 + mov r0.xyz, inpos + mov r0.w, ones + + ; r1 = extra * inpos + dp4 r1.x, extra[0], r0 + dp4 r1.y, extra[1], r0 + dp4 r1.z, extra[2], r0 + dp4 r1.w, extra[3], r0 + + ; r2 = modelView * r1 + dp4 r2.x, modelView[0], r1 + dp4 r2.y, modelView[1], r1 + dp4 r2.z, modelView[2], r1 + dp4 r2.w, modelView[3], r1 + + ; outpos = projection * r2 + dp4 outpos.x, projection[0], r2 + dp4 outpos.y, projection[1], r2 + dp4 outpos.z, projection[2], r2 + dp4 outpos.w, projection[3], r2 + + mov outtc0, intex + + mov outclr, incol + + end +.end diff --git a/platform/3ds/shaders/2d.shbin b/platform/3ds/shaders/2d.shbin new file mode 100644 index 00000000..48e797c9 Binary files /dev/null and b/platform/3ds/shaders/2d.shbin differ diff --git a/platform/3ds/shaders/3d.h b/platform/3ds/shaders/3d.h new file mode 100644 index 00000000..af8af16b --- /dev/null +++ b/platform/3ds/shaders/3d.h @@ -0,0 +1,3 @@ +/* Auto-generated from platform/3ds/shaders/3d.shbin */ +static uint8_t shader_builtin_3d[] = +{68,86,76,66,1,0,0,0,36,1,0,0,68,86,76,80,0,0,0,0,40,0,0,0,32,0,0,0,168,0,0,0,14,0,0,0,24,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,1,240,7,78,2,136,34,10,3,152,34,10,4,168,34,10,5,184,34,10,130,72,2,10,131,88,2,10,132,104,2,10,133,120,2,10,6,0,97,76,2,8,2,8,3,24,2,8,4,40,2,8,5,56,2,8,7,32,32,76,130,8,3,6,8,248,7,2,137,24,3,6,10,248,7,50,3,8,1,34,7,96,35,78,7,40,67,34,43,214,36,241,12,40,67,34,43,210,36,241,7,32,67,78,43,206,36,241,141,248,71,52,7,0,129,76,13,240,71,76,0,0,0,136,110,3,0,0,0,0,0,0,161,10,0,0,0,0,0,0,104,195,6,0,0,0,0,0,100,195,6,0,0,0,0,0,98,195,6,0,0,0,0,0,97,195,6,0,0,0,0,0,127,3,0,0,0,0,0,0,111,67,21,0,0,0,0,0,8,224,6,0,0,0,0,0,116,195,6,0,0,0,0,0,15,192,6,0,0,0,0,0,111,195,134,13,0,0,0,0,111,3,0,0,0,0,0,0,175,202,6,0,0,0,0,0,68,86,76,69,2,16,0,0,0,0,0,0,32,0,0,0,0,0,31,0,0,0,0,0,64,0,0,0,1,0,0,0,84,0,0,0,0,0,0,0,84,0,0,0,5,0,0,0,124,0,0,0,8,0,0,0,188,0,0,0,82,0,0,0,2,0,95,0,0,0,0,0,0,0,63,0,0,0,191,0,0,0,62,0,0,0,0,0,15,0,0,0,3,0,1,0,15,0,0,0,2,0,2,0,15,0,0,0,8,0,3,0,15,0,0,0,1,0,4,0,15,0,0,0,0,0,0,0,16,0,19,0,11,0,0,0,20,0,23,0,26,0,0,0,24,0,27,0,36,0,0,0,28,0,31,0,42,0,0,0,32,0,32,0,51,0,0,0,33,0,33,0,64,0,0,0,34,0,34,0,73,0,0,0,35,0,38,0,112,114,111,106,101,99,116,105,111,110,0,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,111,100,101,108,86,105,101,119,0,101,120,116,114,97,0,108,105,103,104,116,86,101,99,0,108,105,103,104,116,72,97,108,102,86,101,99,0,108,105,103,104,116,67,108,114,0,109,97,116,101,114,105,97,108,0,0,0}; \ No newline at end of file diff --git a/platform/3ds/shaders/3d.pica b/platform/3ds/shaders/3d.pica new file mode 100644 index 00000000..70122533 --- /dev/null +++ b/platform/3ds/shaders/3d.pica @@ -0,0 +1,112 @@ +; Uniforms +.fvec projection[4], worldTransform[4], modelView[4], extra[4] + +.fvec lightVec, lightHalfVec, lightClr, material[4] + +.alias mat_amb material[0] +.alias mat_dif material[1] +.alias mat_spe material[2] +.alias mat_emi material[3] +; Constants +.constf myconst(0.0, 1.0, -1.0, 0.5) +.alias zeros myconst.xxxx ; Vector full of zeros +.alias ones myconst.yyyy ; Vector full of ones +.alias half myconst.wwww + +; Outputs +.out outpos position +.out outtc0 texcoord0 +.out outclr color +.out outview view +.out outnq normalquat + +; Inputs (defined as aliases for convenience) +.alias inpos v0 +.alias innrm v1 +.alias intex v2 +;.alias inclr v3 + +.proc main + ; Force the w component of inpos to be 1.0 + mov r0.xyz, inpos + mov r0.w, ones + + ; r1 = modelView * inpos + dp4 r1.x, modelView[0], r0 + dp4 r1.y, modelView[1], r0 + dp4 r1.z, modelView[2], r0 + dp4 r1.w, modelView[3], r0 + + ; r0 = worldTransform * r1 + dp4 r0.x, worldTransform[0], r1 + dp4 r0.y, worldTransform[1], r1 + dp4 r0.z, worldTransform[2], r1 + dp4 r0.w, worldTransform[3], r1 + + ; outview = -r0 + mov outview, -r0 + + ; outpos = projection * r0 + dp4 outpos.x, projection[0], r0 + dp4 outpos.y, projection[1], r0 + dp4 outpos.z, projection[2], r0 + dp4 outpos.w, projection[3], r0 + + ; outtex = intex + mov outtc0, intex +; +; ; Transform the normal vector with the modelView matrix +; ; TODO: use a separate normal matrix that is the transpose of the inverse of modelView +; dp3 r14.x, modelView[0], innrm +; dp3 r14.y, modelView[1], innrm +; dp3 r14.z, modelView[2], innrm +; dp3 r6.x, r14, r14 +; rsq r6.x, r6.x +; mul r14.xyz, r14.xyz, r6.x +; +; mov r0, myconst.yxxx +; add r4, ones, r14.z +; mul r4, half, r4 +; cmp zeros, ge, ge, r4.x +; rsq r4, r4.x +; mul r5, half, r14 +; jmpc cmp.x, degenerate +; +; rcp r0.z, r4.x +; mul r0.xy, r5, r4 + + ;mov outclr, mat_dif + + ; Calculate the diffuse level (r0.x) and the shininess level (r0.y) + ; r0.x = max(0, -(lightVec * r1)) + ; r0.y = max(0, (-lightHalfVec[i]) * r1) ^ 2 + dp3 r0.x, lightVec, r1 + add r0.x, zeros, -r0 + dp3 r0.y, -lightHalfVec, r1 + max r0, zeros, r0 + mul r0.y, r0, r0 + + + mov r1, mat_emi + + ; r1 += specularColor * lightClr * shininessLevel + mul r2, lightClr, r0.yyyy + mad r1, r2, mat_spe, r1 + + ; r1 += diffuseColor * lightClr * diffuseLevel + mul r2, lightClr, r0.xxxx + mad r1, r2, mat_dif, r1 + + ; r1 += ambientColor * lightClr + mov r2, lightClr + mad r1, r2, mat_amb, r1 + + ; outclr = clamp r1 to [0,1] + min outclr, ones, r1 +degenerate: + mov outnq, r0 + mov outclr, ones + + ; We're finished + end +.end diff --git a/platform/3ds/shaders/3d.shbin b/platform/3ds/shaders/3d.shbin new file mode 100644 index 00000000..0eee239e Binary files /dev/null and b/platform/3ds/shaders/3d.shbin differ diff --git a/platform/3ds/shaders/SCsub b/platform/3ds/shaders/SCsub new file mode 100644 index 00000000..9bdfd1e0 --- /dev/null +++ b/platform/3ds/shaders/SCsub @@ -0,0 +1,13 @@ +Import('env') + +shaders = [ + 'simple_3d', + 'simple_2d', + '2d', + '3d' +] + +if 'PICA' in env['BUILDERS']: + for shader in shaders: + env.PICA(shader) + env.PICA_HEADER(shader) diff --git a/platform/3ds/shaders/simple_2d.h b/platform/3ds/shaders/simple_2d.h new file mode 100644 index 00000000..4622fad0 --- /dev/null +++ b/platform/3ds/shaders/simple_2d.h @@ -0,0 +1,3 @@ +/* Auto-generated from platform/3ds/shaders/simple_2d.shbin */ +static uint8_t shader_builtin_simple_2d[] = +{68,86,76,66,1,0,0,0,140,0,0,0,68,86,76,80,0,0,0,0,40,0,0,0,8,0,0,0,72,0,0,0,7,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,1,240,7,78,2,8,2,8,3,24,2,8,4,40,2,8,5,56,2,8,6,16,32,76,0,0,0,136,110,3,0,0,0,0,0,0,161,10,0,0,0,0,0,0,104,195,6,0,0,0,0,0,100,195,6,0,0,0,0,0,98,195,6,0,0,0,0,0,97,195,6,0,0,0,0,0,111,3,0,0,0,0,0,0,68,86,76,69,2,16,0,0,0,0,0,0,8,0,0,0,0,0,3,0,0,0,0,0,64,0,0,0,2,0,0,0,104,0,0,0,0,0,0,0,104,0,0,0,2,0,0,0,120,0,0,0,1,0,0,0,128,0,0,0,11,0,0,0,2,0,95,0,0,0,0,0,0,0,63,0,0,0,191,0,153,153,59,0,2,0,94,0,51,51,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,2,0,1,0,15,0,0,0,0,0,0,0,16,0,19,0,112,114,111,106,101,99,116,105,111,110,0,0}; \ No newline at end of file diff --git a/platform/3ds/shaders/simple_2d.pica b/platform/3ds/shaders/simple_2d.pica new file mode 100644 index 00000000..79077d12 --- /dev/null +++ b/platform/3ds/shaders/simple_2d.pica @@ -0,0 +1,36 @@ +; Example PICA200 vertex shader + +; Uniforms +.fvec projection[4] + +; Constants +.constf myconst(0.0, 1.0, -1.0, 0.1) +.constf myconst2(0.3, 0.0, 0.0, 0.0) +.alias zeros myconst.xxxx ; Vector full of zeros +.alias ones myconst.yyyy ; Vector full of ones + +; Outputs +.out outpos position +.out outclr color + +; Inputs (defined as aliases for convenience) +.alias inpos v0 +.alias inclr v1 + +.proc main + ; Force the w component of inpos to be 1.0 + mov r0.xyz, inpos + mov r0.w, ones + + ; outpos = projectionMatrix * inpos + dp4 outpos.x, projection[0], r0 + dp4 outpos.y, projection[1], r0 + dp4 outpos.z, projection[2], r0 + dp4 outpos.w, projection[3], r0 + + ; outclr = inclr + mov outclr, inclr + + ; We're finished + end +.end diff --git a/platform/3ds/shaders/simple_2d.pica Kopie b/platform/3ds/shaders/simple_2d.pica Kopie new file mode 100644 index 00000000..876c1ef3 --- /dev/null +++ b/platform/3ds/shaders/simple_2d.pica Kopie @@ -0,0 +1,50 @@ +; Example PICA200 vertex shader + +; Uniforms +.fvec projection[4], modelView[4] + +; Constants +.constf myconst(0.0, 1.0, -1.0, 0.1) +.constf myconst2(0.3, 0.0, 0.0, 0.0) +.alias zeros myconst.xxxx ; Vector full of zeros +.alias ones myconst.yyyy ; Vector full of ones + +; Outputs +.out outpos position +; .out outclr color +.out outtc0 texcoord0 + +; Inputs (defined as aliases for convenience) +.alias inpos v0 +.alias intex v1 + +.bool test + +.proc main + ; Force the w component of inpos to be 1.0 + mov r0.xyz, inpos + mov r0.w, ones + + ; outpos = projectionMatrix * inpos + ; dp4 outpos.x, projection[0], r0 + ; dp4 outpos.y, projection[1], r0 + ; dp4 outpos.z, projection[2], r0 + ; dp4 outpos.w, projection[3], r0 + + dp4 r2.x, modelView[0], r0 + dp4 r2.y, modelView[1], r0 + dp4 r2.z, modelView[2], r0 + dp4 r2.w, modelView[3], r0 + + ; outpos = projection * r2 + dp4 outpos.x, projection[0], r2 + dp4 outpos.y, projection[1], r2 + dp4 outpos.z, projection[2], r2 + dp4 outpos.w, projection[3], r2 + + ; outclr = inclr + mov outtc0, intex + + ; We're finished + end +.end diff --git a/platform/3ds/shaders/simple_2d.shbin b/platform/3ds/shaders/simple_2d.shbin new file mode 100644 index 00000000..317f8370 Binary files /dev/null and b/platform/3ds/shaders/simple_2d.shbin differ diff --git a/platform/3ds/shaders/simple_3d.h b/platform/3ds/shaders/simple_3d.h new file mode 100644 index 00000000..a61a23ae --- /dev/null +++ b/platform/3ds/shaders/simple_3d.h @@ -0,0 +1,3 @@ +/* Auto-generated from platform/3ds/shaders/simple_3d.shbin */ +static uint8_t shader_builtin_simple_3d[] = +{68,86,76,66,1,0,0,0,44,1,0,0,68,86,76,80,0,0,0,0,40,0,0,0,34,0,0,0,176,0,0,0,14,0,0,0,32,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,1,240,7,78,2,72,34,10,3,88,34,10,4,104,34,10,5,120,34,10,130,8,2,8,131,24,2,8,132,40,2,8,133,56,2,8,6,16,32,76,0,32,0,78,7,240,7,78,2,72,34,10,3,88,34,10,4,104,34,10,7,240,39,78,134,24,65,6,6,32,65,62,134,40,33,34,130,136,2,6,8,248,7,2,137,152,2,6,10,248,7,50,3,8,1,34,6,224,34,78,11,168,66,34,38,182,36,241,12,168,66,34,38,178,36,241,6,160,66,78,38,174,36,241,141,248,71,52,0,0,0,136,110,3,0,0,0,0,0,0,161,10,0,0,0,0,0,0,104,195,6,0,0,0,0,0,100,195,6,0,0,0,0,0,98,195,6,0,0,0,0,0,97,195,6,0,0,0,0,0,111,195,134,13,0,0,0,0,1,0,0,0,0,0,0,0,8,224,6,0,0,0,0,0,116,195,6,0,0,0,0,0,15,192,6,0,0,0,0,0,111,67,21,0,0,0,0,0,111,3,0,0,0,0,0,0,175,202,6,0,0,0,0,0,68,86,76,69,2,16,0,0,0,0,0,0,34,0,0,0,0,0,7,0,0,0,0,0,64,0,0,0,1,0,0,0,84,0,0,0,0,0,0,0,84,0,0,0,3,0,0,0,108,0,0,0,6,0,0,0,156,0,0,0,61,0,0,0,2,0,95,0,0,0,0,0,0,0,63,0,0,0,191,0,0,0,190,0,0,0,0,0,15,0,0,0,3,0,1,0,15,0,0,0,2,0,2,0,15,0,0,0,0,0,0,0,16,0,19,0,11,0,0,0,20,0,23,0,21,0,0,0,24,0,24,0,30,0,0,0,25,0,25,0,43,0,0,0,26,0,26,0,52,0,0,0,27,0,30,0,112,114,111,106,101,99,116,105,111,110,0,109,111,100,101,108,86,105,101,119,0,108,105,103,104,116,86,101,99,0,108,105,103,104,116,72,97,108,102,86,101,99,0,108,105,103,104,116,67,108,114,0,109,97,116,101,114,105,97,108,0,0,0,0}; \ No newline at end of file diff --git a/platform/3ds/shaders/simple_3d.pica b/platform/3ds/shaders/simple_3d.pica new file mode 100644 index 00000000..42219f9f --- /dev/null +++ b/platform/3ds/shaders/simple_3d.pica @@ -0,0 +1,89 @@ +; Example PICA200 vertex shader + +; Uniforms +.fvec projection[4], modelView[4] +.fvec lightVec, lightHalfVec, lightClr, material[4] +.alias mat_amb material[0] +.alias mat_dif material[1] +.alias mat_spe material[2] +.alias mat_emi material[3] + +; Constants +.constf myconst(0.0, 1.0, -1.0, -0.5) +.alias zeros myconst.xxxx ; Vector full of zeros +.alias ones myconst.yyyy ; Vector full of ones + +; Outputs +.out outpos position +.out outtc0 texcoord0 +.out outclr color + +; Inputs (defined as aliases for convenience) +.alias inpos v0 +.alias intex v1 +.alias innrm v2 +; .alias inclr v3 + +.proc main + ; Force the w component of inpos to be 1.0 + mov r0.xyz, inpos + mov r0.w, ones + + ; r1 = modelView * inpos + dp4 r1.x, modelView[0], r0 + dp4 r1.y, modelView[1], r0 + dp4 r1.z, modelView[2], r0 + dp4 r1.w, modelView[3], r0 + + ; outpos = projection * r1 + dp4 outpos.x, projection[0], r1 + dp4 outpos.y, projection[1], r1 + dp4 outpos.z, projection[2], r1 + dp4 outpos.w, projection[3], r1 + + ; outtex = intex + mov outtc0, intex + + ; Transform the normal vector with the modelView matrix + ; r1 = normalize(modelView * innrm) + mov r0.xyz, innrm + mov r0.w, zeros + dp4 r1.x, modelView[0], r0 + dp4 r1.y, modelView[1], r0 + dp4 r1.z, modelView[2], r0 + mov r1.w, zeros + dp3 r2, r1, r1 ; r2 = x^2+y^2+z^2 for each component + rsq r2, r2 ; r2 = 1/sqrt(r2) '' + mul r1, r2, r1 ; r1 = r1*r2 + + ; Calculate the diffuse level (r0.x) and the shininess level (r0.y) + ; r0.x = max(0, -(lightVec * r1)) + ; r0.y = max(0, (-lightHalfVec[i]) * r1) ^ 2 + dp3 r0.x, lightVec, r1 + add r0.x, zeros, -r0 + dp3 r0.y, -lightHalfVec, r1 + max r0, zeros, r0 + mul r0.y, r0, r0 + + ; Accumulate the vertex color in r1, initializing it to the emission color + mov r1, mat_emi + + ; r1 += specularColor * lightClr * shininessLevel + mul r2, lightClr, r0.yyyy + mad r1, r2, mat_spe, r1 + + ; r1 += diffuseColor * lightClr * diffuseLevel + mul r2, lightClr, r0.xxxx + mad r1, r2, mat_dif, r1 + + ; r1 += ambientColor * lightClr + mov r2, lightClr + mad r1, r2, mat_amb, r1 + + ; outclr = clamp r1 to [0,1] + min outclr, ones, r1 + ;mov outclr, r1 + + ; We're finished + end +.end diff --git a/platform/3ds/shaders/simple_3d.shbin b/platform/3ds/shaders/simple_3d.shbin new file mode 100644 index 00000000..b3865186 Binary files /dev/null and b/platform/3ds/shaders/simple_3d.shbin differ diff --git a/platform/3ds/thread_3ds.cpp b/platform/3ds/thread_3ds.cpp new file mode 100644 index 00000000..d2ebd5a6 --- /dev/null +++ b/platform/3ds/thread_3ds.cpp @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* thread_3ds.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 __3DS__ +#include "thread_3ds.h" +#include "platform/3ds/os_3ds.h" +#include "memory.h" + + +Thread* Thread3ds::create_func_3ds(ThreadCreateCallback p_callback,void * p_user,const Thread::Settings& p_settings) { + // Get base thread priority for relative priority setting + int32_t priority; + svcGetThreadPriority(&priority, (Thread::_main_thread_id == 0) ? CUR_THREAD_HANDLE : Thread::_main_thread_id); + + if (p_settings.priority == PRIORITY_LOW) + priority++; + else if (p_settings.priority == PRIORITY_HIGH) + priority--; + + ThreadCtrWrapper* thread_wrapper = memnew(ThreadCtrWrapper(p_callback, p_user, priority)); + return memnew(Thread3ds(thread_wrapper)); +} + +void Thread3ds::make_default() { + create_func = create_func_3ds; + get_thread_ID_func = ThreadCtrWrapper::get_thread_ID_func_3ds; + wait_to_finish_func = wait_to_finish_func_3ds; +} + +Thread::ID Thread3ds::get_ID() const { + return id; +} + +void Thread3ds::wait_to_finish_func_3ds(Thread* p_thread) { + Thread3ds *t = static_cast(p_thread); + t->thread->wait(); +} + +Thread3ds::Thread3ds(ThreadCtrWrapper* p_thread) { + thread = p_thread; +} + +Thread3ds::~Thread3ds() { + memdelete(thread); +} +#endif diff --git a/platform/3ds/thread_3ds.h b/platform/3ds/thread_3ds.h new file mode 100644 index 00000000..b5ccebf5 --- /dev/null +++ b/platform/3ds/thread_3ds.h @@ -0,0 +1,99 @@ +/*************************************************************************/ +/* thread_3ds.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 THREAD_3DS_H +#define THREAD_3DS_H + +#include "core/os/thread.h" +// #include "core/os/mutex.h" +#include "thread_wrap.h" +// #include "thread_ctr_wrapper.h" + +extern "C" { +#include <3ds/types.h> +#include <3ds/svc.h> +#include <3ds/synchronization.h> +} + +/* +t + +extern "C" { +#include +#include <3ds/types.h> + + +} +struct Thread_tag +{ + Handle handle; + ThreadFunc ep; + void* arg; + int rc; + bool detached, finished; + struct _reent reent; + void* stacktop; +}; +Thread threadGetCurrent(void); +Thread threadCreate(ThreadFunc entrypoint, void* arg, size_t stack_size, int prio, int core_id, bool detached); +int threadGetExitCode(Thread thread); +Handle threadGetHandle(Thread thread); +void threadFree(Thread thread); +Result threadJoin(Thread thread, u64 timeout_ns); + + +class ThreadCtrWrapper +{ + Thread_tag* thread; + +public: + ThreadCtrWrapper(ThreadCreateCallback p_callback, void* p_userdata, int32_t p_priority); + + void wait(); + + static uint64_t get_thread_ID_func_3ds(); +};*/ + +class Thread3ds : public Thread { + + static Thread* create_func_3ds(ThreadCreateCallback p_callback,void * p_user,const Settings& p_settings=Settings()); + static void wait_to_finish_func_3ds(Thread* p_thread); + + ThreadCtrWrapper* thread; + ID id; + +public: + Thread3ds(ThreadCtrWrapper* p_thread); + ~Thread3ds(); + + virtual ID get_ID() const; + + static void make_default(); +}; + +#endif diff --git a/platform/3ds/thread_wrap.cpp b/platform/3ds/thread_wrap.cpp new file mode 100644 index 00000000..e248b865 --- /dev/null +++ b/platform/3ds/thread_wrap.cpp @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* thread_ctr_wrapper.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 __3DS__ +#include "thread_wrap.h" +#include <3ds.h> + +ThreadCtrWrapper::ThreadCtrWrapper(ThreadCreateCallback p_callback, void* p_userdata, int32_t p_priority) { + thread = threadCreate(p_callback, p_userdata, 64 * 1024, p_priority, -1, false); +} + +uint64_t ThreadCtrWrapper::get_thread_ID_func_3ds() { + if (!threadGetCurrent()) + return CUR_THREAD_HANDLE; + return threadGetHandle(threadGetCurrent()); +} + +void ThreadCtrWrapper::wait() { + threadJoin(thread, U64_MAX); + threadFree(thread); +} + +#endif diff --git a/platform/3ds/thread_wrap.h b/platform/3ds/thread_wrap.h new file mode 100644 index 00000000..555641d5 --- /dev/null +++ b/platform/3ds/thread_wrap.h @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* thread_ctr_wrapper.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 THREAD_CTR_WRAPPER_H +#define THREAD_CTR_WRAPPER_H + +typedef void (*ThreadCreateCallback)(void *p_userdata); + +extern "C" { +#include +#include <3ds/types.h> + +// Needs to be same as definition in 3ds/thread.h +// Which cannot itself be included due to Thread struct naming conflict +struct Thread_tag +{ + Handle handle; + ThreadFunc ep; + void* arg; + int rc; + bool detached, finished; + struct _reent reent; + void* stacktop; +}; +} + +class ThreadCtrWrapper +{ + Thread_tag* thread; + +public: + ThreadCtrWrapper(ThreadCreateCallback p_callback, void* p_userdata, int32_t p_priority); + + void wait(); + + static uint64_t get_thread_ID_func_3ds(); +}; + +#endif diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 765a8135..42533c5c 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -23,10 +23,10 @@ def get_flags(): ('lua', 'no'), ('tools', 'no'), ('nedmalloc', 'no'), - ('theora', 'no'), + ('theora', 'yes'), ('tools', 'no'), ('nedmalloc', 'no'), - ('vorbis', 'no'), + ('vorbis', 'yes'), ('musepack', 'no'), ('squirrel', 'no'), ('squish', 'no'), @@ -44,14 +44,14 @@ def configure(env): env.Append(CPPPATH=['#platform/javascript']) - em_path=os.environ["EMSCRIPTEN_ROOT"] + #em_path=os.environ["EMSCRIPTEN_ROOT"] - env['ENV']['PATH'] = em_path+":"+env['ENV']['PATH'] + #env['ENV']['PATH'] = em_path+":"+env['ENV']['PATH'] - env['CC'] = em_path+'/emcc' - env['CXX'] = em_path+'/emcc' - env['AR'] = em_path+"/emar" - env['RANLIB'] = em_path+"/emranlib" + env['CC'] = 'emcc' + env['CXX'] = 'emcc' + env['AR'] = "emar" + env['RANLIB'] = "emranlib" # env.Append(LIBS=['c','m','stdc++','log','GLESv1_CM','GLESv2']) @@ -69,12 +69,13 @@ def configure(env): env.Append(CCFLAGS=['-D_DEBUG', '-Wall', '-O2', '-DDEBUG_ENABLED']) env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC']) - env.Append(CPPFLAGS=["-fno-exceptions",'-DNO_SAFE_CAST','-fno-rtti']) + env.Append(CPPFLAGS=['-DNO_SAFE_CAST','-fno-rtti']) env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL','-DMPC_FIXED_POINT','-DTYPED_METHOD_BIND','-DNO_THREADS']) env.Append(CPPFLAGS=['-DGLES2_ENABLED']) env.Append(CPPFLAGS=['-DGLES_NO_CLIENT_ARRAYS']) - env.Append(CPPFLAGS=['-s','ASM_JS=1']) + env.Append(CPPFLAGS=['-s','FORCE_FILESYSTEM=1']) env.Append(CPPFLAGS=['-s','FULL_ES2=1']) + env.Append(CXXFLAGS=['-std=gnu++03']) # env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED','-DMPC_FIXED_POINT']) if (env["compress"]=="yes"): lzma_binpath = em_path+"/third_party/lzma.js/lzma-native" diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 8924f38d..70c9ae79 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -330,7 +330,7 @@ bool EditorExportPlatformJavaScript::can_export(String *r_error) const { String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/"; if (!FileAccess::exists(exe_path+"javascript_debug.zip") || !FileAccess::exists(exe_path+"javascript_release.zip")) { - valid=false; + // valid=false; err+="No export templates found.\nDownload and install export templates.\n"; } diff --git a/platform/psp/audio_driver_psp.cpp b/platform/psp/audio_driver_psp.cpp index 70ee12fd..4b50777e 100644 --- a/platform/psp/audio_driver_psp.cpp +++ b/platform/psp/audio_driver_psp.cpp @@ -43,13 +43,16 @@ Error AudioDriverPSP::init() { exit_thread=false; pcm_open = false; samples_in = NULL; + samples_out = NULL; + mix_rate = 44100; output_format = OUTPUT_STEREO; channels = 2; int latency = GLOBAL_DEF("audio/output_latency",50); + buffer_size = nearest_power_of_2( latency * mix_rate / 1000 ); samples_in = memnew_arr(int32_t, buffer_size*channels); @@ -60,11 +63,13 @@ Error AudioDriverPSP::init() { mutex = Mutex::create(); thread = Thread::create(AudioDriverPSP::thread_func, this); + return OK; }; void AudioDriverPSP::thread_func(void *p_udata) { int buffer_index = 0; + AudioDriverPSP *ad = (AudioDriverPSP *)p_udata; int sample_count = ad->buffer_size; @@ -72,10 +77,12 @@ void AudioDriverPSP::thread_func(void *p_udata) { while (!ad->exit_thread) { + if (ad->exit_thread) break; if (ad->active) { + ad->audio_server_process(ad->buffer_size, ad->samples_in); for(int i = 0; i < sample_count*2; ++i) { @@ -83,6 +90,7 @@ void AudioDriverPSP::thread_func(void *p_udata) { } } else + { for (int i = 0; i < sample_count*2; i++) { @@ -90,7 +98,8 @@ void AudioDriverPSP::thread_func(void *p_udata) { } } - sceAudioOutput2OutputBlocking(0x8000, ad->samples_out); + sceAudioOutput2OutputBlocking(0x8000*3, ad->samples_out); + } @@ -125,11 +134,13 @@ void AudioDriverPSP::unlock() { void AudioDriverPSP::finish() { exit_thread = true; + if (thread) { Thread::wait_to_finish(thread); } - //sceAudioOutput2Release(); + sceAudioOutput2Release(); + if (samples_in) { memdelete_arr(samples_in); @@ -147,9 +158,11 @@ void AudioDriverPSP::finish() { AudioDriverPSP::AudioDriverPSP() { mutex = NULL; + samples_in = NULL; samples_out = NULL; thread = NULL; + active = false; }; diff --git a/platform/psp/detect.py b/platform/psp/detect.py index 5a6adbce..ae3c36c2 100644 --- a/platform/psp/detect.py +++ b/platform/psp/detect.py @@ -54,9 +54,11 @@ def configure(env): elif env["target"]=="debug": env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED']) - env.Append(CPPFLAGS=['-DNEED_LONG_INT', '-DPSP_ENABLED', '-fno-exceptions', '-DNO_SAFE_CAST', '-fno-rtti']) + + env.Append(CPPFLAGS=['-DNEED_LONG_INT', '-DPSP_ENABLED', '-fno-exceptions', '-DNO_SAFE_CAST', '-fno-rtti', '-Wno-incompatible-pointer-types']) env.Append(LIBS=['pthread', 'z', 'pspdisplay', 'pspge', 'pspgu', 'pspgum_vfpu', 'pspvfpu', 'pspctrl', 'psppower', 'pspaudio', 'pspnet', 'pspnet_apctl']) + if (env["CXX"]=="clang++"): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) env["CC"]="clang" diff --git a/platform/psp/godot_psp.cpp b/platform/psp/godot_psp.cpp index f5bca517..df51192f 100644 --- a/platform/psp/godot_psp.cpp +++ b/platform/psp/godot_psp.cpp @@ -125,6 +125,7 @@ int netDialog() } int main(int argc, char* argv[]) { + // SetupCallbacks(); pspSdkDisableFPUExceptions(); scePowerSetClockFrequency(333, 333, 166); diff --git a/platform/psp/os_psp.cpp b/platform/psp/os_psp.cpp index 407c9e21..e0c9d7fa 100644 --- a/platform/psp/os_psp.cpp +++ b/platform/psp/os_psp.cpp @@ -60,7 +60,9 @@ const char * OS_PSP::get_video_driver_name(int p_driver) const { } OS::VideoMode OS_PSP::get_default_video_mode() const { + return OS::VideoMode(480,272,true); + } static MemoryPoolStaticMalloc *mempool_static=NULL; diff --git a/platform/psp/os_psp.h b/platform/psp/os_psp.h index 808a1734..5c6e630d 100644 --- a/platform/psp/os_psp.h +++ b/platform/psp/os_psp.h @@ -29,7 +29,7 @@ #ifndef OS_PSP_H #define OS_PSP_H - +#include "audio_driver_psp.h" #include "os/input.h" #include "drivers/unix/os_unix.h" #include "servers/visual_server.h" @@ -56,6 +56,7 @@ class OS_PSP : public OS { MainLoop *main_loop; AudioDriverPSP driver_dummy; + bool grab; uint64_t ticks_start; diff --git a/platform/psp/rasterizer_psp.cpp b/platform/psp/rasterizer_psp.cpp index e47cf509..1cb06270 100644 --- a/platform/psp/rasterizer_psp.cpp +++ b/platform/psp/rasterizer_psp.cpp @@ -567,9 +567,10 @@ void RasterizerPSP::texture_set_data(RID p_texture,const Image& p_image,VS::Cube texture->alloc_width = nearest_power_of_2(img.get_width()); texture->alloc_height = nearest_power_of_2(img.get_height()); - if (texture->alloc_width < 16) { + if (texture->alloc_width > 16) { texture->alloc_width = 16; } + if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) { img.resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); @@ -3018,8 +3019,6 @@ void RasterizerPSP::set_render_target(RID p_render_target, bool p_transparent_bg void RasterizerPSP::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; @@ -3814,7 +3813,6 @@ void RasterizerPSP::_render(const Geometry *p_geometry,const Material *p_materia switch(p_geometry->type) { case Geometry::GEOMETRY_SURFACE: { - Surface *s = (Surface*)p_geometry; _rinfo.vertex_count+=s->array_len; @@ -3944,7 +3942,6 @@ void RasterizerPSP::_setup_shader_params(const Material *p_material) { } void RasterizerPSP::_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; @@ -3959,7 +3956,7 @@ void RasterizerPSP::_render_list_forward(RenderList *p_render_list,bool p_revers 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++; @@ -4036,7 +4033,6 @@ void RasterizerPSP::_render_list_forward(RenderList *p_render_list,bool p_revers void RasterizerPSP::end_scene() { - sceGuEnable(GU_BLEND); sceGuDepthMask(GU_FALSE); // sceGuDepthRange(0,20000); diff --git a/platform/vita/SCsub b/platform/vita/SCsub index d3e18697..94e76759 100644 --- a/platform/vita/SCsub +++ b/platform/vita/SCsub @@ -6,8 +6,9 @@ Import('env') common_vita=[\ "os_vita.cpp",\ - "rasterizer_vita.cpp",\ "audio_driver_vita.cpp",\ + #"rasterizer_vita.cpp",\ + #"immvertex.c",\ # ] diff --git a/platform/vita/detect.py b/platform/vita/detect.py index fe4c0087..254adf80 100644 --- a/platform/vita/detect.py +++ b/platform/vita/detect.py @@ -25,7 +25,7 @@ def get_opts(): def get_flags(): return [ ('builtin_zlib', 'no'), - ('theora','no'), + ('theora','yes'), ('module_pspmath_enabled', 'yes'), ] @@ -57,8 +57,8 @@ def configure(env): elif env["target"]=="debug": env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED']) - env.Append(CPPFLAGS=['-DNEED_LONG_INT', '-D__psp2__', '-DVITA_ENABLED', '-fno-exceptions', '-DNO_SAFE_CAST', '-fno-rtti']) #'-DGLES2_ENABLED' - env.Append(LIBS=['z', "SceCtrl_stub", "SceAudio_stub","SceMotion_stub","SceCamera_stub","liblibIMGEGL_stub", "liblibgpu_es4_ext_stub","liblibGLESv1_CM_stub"]) + env.Append(CPPFLAGS=['-DNEED_LONG_INT', '-D__psp2__', '-DVITA_ENABLED', '', '-DNO_SAFE_CAST', '-fno-rtti']) #'-DGLES2_ENABLED' + env.Append(LIBS=['z', "SceCtrl_stub", "SceAudio_stub","SceMotion_stub","SceCamera_stub","SceAppMgr_stub","taihen_stub","liblibIMGEGL_stub", "liblibgpu_es4_ext_stub","liblibGLESv1_CM_stub"]) # env.Append(LIBS=['z', "SceCtrl_stub", "SceAudio_stub","liblibGLESv2_stub","liblibIMGEGL_stub", "liblibgpu_es4_ext_stub"]) env.Append(LINKFLAGS=["-Wl,-q,-whole-archive", "-lpthread", "-Wl,-q,-no-whole-archive"]) diff --git a/platform/vita/os_vita.cpp b/platform/vita/os_vita.cpp index 49b8a69b..90613c6f 100644 --- a/platform/vita/os_vita.cpp +++ b/platform/vita/os_vita.cpp @@ -31,7 +31,7 @@ #endif #include "servers/visual/visual_server_raster.h" -#include "servers/visual/rasterizer_dummy.h" +// #include "servers/visual/rasterizer_dummy.h" #ifdef PSP2_GLES2 extern "C" { @@ -40,7 +40,7 @@ extern "C" { #include "drivers/gles2/rasterizer_gles2.h" #else -#include "rasterizer_vita.h" +#include "drivers/gles1/rasterizer_gles1.h" #endif #include "os_vita.h" #include @@ -59,6 +59,8 @@ extern "C" { #include #include +#include +#include #include #include @@ -118,6 +120,21 @@ void OS_VITA::initialize_core() { sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL); sceKernelLoadStartModule("vs0:sys/external/libc.suprx", 0, NULL, 0, NULL, NULL); + + char title_id[0xA]; + char app_dir_path[0x100]; + char app_kernel_module_path[0x100]; + SceUID pid = -1; + pid = sceKernelGetProcessId(); + sceAppMgrAppParamGetString(pid, 12, title_id, sizeof(title_id)); + snprintf(app_dir_path, sizeof(app_dir_path), "ux0:app/%s", title_id); + snprintf(app_kernel_module_path, sizeof(app_kernel_module_path), "%s/module/libgpu_es4_kernel_ext.skprx", app_dir_path); + + SceUID res = taiLoadStartKernelModule(app_kernel_module_path, 0, NULL, 0); + if (res < 0) { + printf("Failed to load kernel module: %08x\n", res); + } + sceKernelLoadStartModule("app0:module/libgpu_es4_ext.suprx", 0, NULL, 0, NULL, NULL); sceKernelLoadStartModule("app0:module/libIMGEGL.suprx", 0, NULL, 0, NULL, NULL); diff --git a/platform/vita/rasterizer_vita.cpp b/platform/vita/rasterizer_vita.cpp deleted file mode 100644 index 3b09848f..00000000 --- a/platform/vita/rasterizer_vita.cpp +++ /dev/null @@ -1,6470 +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 __psp2__ - -#include "rasterizer_vita.h" -#include "os/os.h" -#include "globals.h" -#include -#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 - -_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) { -#ifndef PSP - glClientActiveTexture(GL_TEXTURE0); -#endif - 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::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;icompressed) { - 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 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::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;imipmaps+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::Write(); - - Image img(texture->alloc_width,texture->alloc_height,texture->mipmaps,fmt,data); - - if (texture->formatalloc_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 *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 order; - - - for(Map::Element *E=shader->uniforms.front();E;E=E->next()) { - - - order[E->get().order]=E->key(); - } - - - for(Map::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;imorph_target_count>0) { - - use_VBO=false; - } - - surface->packed=pack_arrays && use_VBO; - - int total_elem_size=0; - - for (int i=0;iarray[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<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<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 array_pre_vbo; - DVector::Write vaw; - DVector index_array_pre_vbo; - DVector::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=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 array = p_arrays[ai]; - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector::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;iarray_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 array = p_arrays[ai]; - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector::Read read = array.read(); - const Vector3* src=read.ptr(); - - // setting vertices means regenerating the AABB - - for (int i=0;iarray_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 array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len*4, ERR_INVALID_PARAMETER ); - - - DVector::Read read = array.read(); - const real_t* src = read.ptr(); - - for (int i=0;iarray_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 array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector::Read read = array.read(); - const Color* src = read.ptr(); - bool alpha=false; - - for (int i=0;iarray_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 array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len , ERR_INVALID_PARAMETER); - - DVector::Read read = array.read(); - - const Vector2 * src=read.ptr(); - float scale=1.0; - - - for (int i=0;iarray_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 array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); - - - DVector::Read read = array.read(); - - const real_t * src = read.ptr(); - - p_surface->max_bone=0; - - for (int i=0;iarray_len;i++) { - - GLfloat data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j=0;jmax_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 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::Read read = indices.read(); - const int *src=read.ptr(); - - for (int i=0;iindex_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<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;imorph_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;isurfaces.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); - - if (nearest_power_of_2(p_count)!=nearest_power_of_2(multimesh->elements.size())) { - if (multimesh->tex_id) { - glDeleteTextures(1,&multimesh->tex_id); - multimesh->tex_id=0; - } - - if (p_count) { - - uint32_t po2 = nearest_power_of_2(p_count); - if (po2&0xAAAAAAAA) { - //half width - - multimesh->tw=Math::sqrt(po2*2); - multimesh->th=multimesh->tw/2; - } else { - - multimesh->tw=Math::sqrt(po2); - multimesh->th=multimesh->tw; - - } - multimesh->tw*=4; - if (multimesh->th==0) - multimesh->th=1; - - - - glGenTextures(1, &multimesh->tex_id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,multimesh->tex_id); - -#ifdef GLEW_ENABLED - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, multimesh->tw, multimesh->th, 0, GL_RGBA, GL_FLOAT,NULL); -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, multimesh->tw, multimesh->th, 0, GL_RGBA, GL_FLOAT,NULL); -#endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); - //multimesh->pixel_size=1.0/ps; - - glBindTexture(GL_TEXTURE_2D,0); - } - - } - 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& p_points) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_points=p_points; -} - -DVector RasterizerGLES1::particles_get_emission_points(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,DVector()); - - 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;idata.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)); - is_editor = VS::get_singleton()->get_editor(); - 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; - current_env = environment_owner.get(p_env); - - //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_countbase->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=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;ilights[i]=lights[i]->sort_key; - } - - e->light_count=light_count; - int poslight_count=light_count; - if (poslight_count>1) { - SortArray 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;isurfaces[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;icache_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;icache_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; - if(current_env) { - switch((int)current_env->group[0]) { - case VS::ENV_GROUP_SAME: { - glMaterialfv(side,GL_AMBIENT, diffuse_rgba); - break; - } - case VS::ENV_GROUP_NONE: { - break; - } - case VS::ENV_GROUP_HALF: { - float ambient_rgba[4]={ - diffuse_color.r / 2, - diffuse_color.g / 2, - diffuse_color.b / 2, - 1.0 - }; - glMaterialfv(side,GL_AMBIENT, ambient_rgba); - break; - } - case VS::ENV_GROUP_COLOR: { - Color c = current_env->group[VS::ENV_GROUP_COLOR]; - float ambient_rgba2[4] = { - c.r, - c.g, - c.b, - c.a - }; - glMaterialfv(side,GL_AMBIENT, ambient_rgba2); - break; - } - case 0: { - glMaterialfv(side,GL_AMBIENT, diffuse_rgba); - break; - } - default: { - break; - } - } - } else { - glMaterialfv(side,GL_AMBIENT, diffuse_rgba); - } - glMaterialfv(side,GL_DIFFUSE,diffuse_rgba); - // | GU_SPECULARspecular - - 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; itype) { - - case Geometry::GEOMETRY_MULTISURFACE: - case Geometry::GEOMETRY_SURFACE: { - - - - const Surface *surf=NULL; - if (p_geometry->type==Geometry::GEOMETRY_SURFACE) - surf=static_cast(p_geometry); - else if (p_geometry->type==Geometry::GEOMETRY_MULTISURFACE) - surf=static_cast(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;imorph_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;iarray[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;karray_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;karray_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;jmorph_target_count;j++) { - - for(int i=0;iarray[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;karray_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;iarray_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;iarray[i]; - if (ad.size==0) - continue; - - int ofs = ad.ofs; - - - switch(i) { - - case VS::ARRAY_VERTEX: { - for(int k=0;k(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;j(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;jvertex_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(p_geometry)->surface; - const MultiMesh *mm = static_cast(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) { - - // glLoadMatrixf(elements[0].matrix); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); - for(int i=0;iprimitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_SHORT:GL_UNSIGNED_SHORT,0); - // glLoadIdentity(); - // glPopMatrix(); - } - - - } else { - - for(int i=0;iprimitive],0,s->array_len); - // glLoadIdentity(); - // glPopMatrix(); - } - - - }; - } break; - case Geometry::GEOMETRY_PARTICLES: { - - - //print_line("particulinas"); - const Particles *particles = static_cast( 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;idata.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::Element *E=p_material->shader_cache->params.front();E;E=E->next(),idx++) { - - Variant v; // - v = E->get(); - const Map::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 - -} -_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::_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; - const BakedLightData *prev_baked_light=NULL; - RID prev_baked_light_texture; - - Geometry::Type prev_geometry_type=Geometry::GEOMETRY_INVALID; - - for (int i=0;ielement_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; - const BakedLightData *baked_light = e->instance->baked_light; - - bool bind_baked_light_octree=false; - bool bind_baked_lightmap=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); - glBindTexture(GL_TEXTURE_2D,sl->texture); //bind the texture - } - } - if (baked_light) { - - if (baked_light->mode==VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) { - // material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,true); - bind_baked_light_octree=true; - if (prev_baked_light!=baked_light) { - Texture *tex=texture_owner.get(baked_light->octree_texture); - if (tex) { - - glActiveTexture(GL_TEXTURE0); - 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); - glBindTexture(texl->target,texl->tex_id); //bind the light texture - } - } - - } - - } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { - - - int lightmap_idx = e->instance->baked_lightmap_id; - - // material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false); - bind_baked_lightmap=false; - - - if (baked_light->lightmaps.has(lightmap_idx)) { - - - RID texid = baked_light->lightmaps[lightmap_idx]; - - if (prev_baked_light!=baked_light || texid!=prev_baked_light_texture) { - - - Texture *tex = texture_owner.get(texid); - if (tex) { - - glActiveTexture(GL_TEXTURE0); - glBindTexture(tex->target,tex->tex_id); //bind the texture - } - - prev_baked_light_texture=texid; - } - - if (texid.is_valid()) { - bind_baked_lightmap=true; - } - - } - } - } - - 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_baked_light=baked_light; - prev_geometry_type=geometry->type; - } - - - -}; - -void RasterizerGLES1::_process_blur(int times, float inc) { - - float spost = 0.0f; - float alphainc = 0.9f / times; - float alpha = 0.2f; - int num; - - // glDisable(GL_TEXTURE_GEN_S); - // glDisable(GL_TEXTURE_GEN_T); - - glEnable(GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - glEnable(GL_BLEND); - - - glBindTexture(GL_TEXTURE_2D, BlurTexture); - - glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrthof(0, viewport.width, viewport.height, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - alphainc = alpha / times; - /* - glBegin(GL_QUADS); - for (num = 0;num < times;num++) - { - glColor4f(1.0f, 1.0f, 1.0f, alpha); - glTexCoord2f(0+spost,1-spost); - glVertex2f(0,0); - - glTexCoord2f(0+spost,0+spost); - glVertex2f(0, viewport.height); - - glTexCoord2f(1-spost,0+spost); - glVertex2f(viewport.width, viewport.height); - - glTexCoord2f(1-spost,1-spost); - glVertex2f(viewport.width,0); - - - spost += inc; - alpha = alpha - alphainc; - } - glEnd(); - */ - //attempt at porting - - GLfloat vertices[] = { - 0, 0, - 0, (GLfloat)viewport.height, - (GLfloat)viewport.width, (GLfloat)viewport.height, - (GLfloat)viewport.width, 0 - }; - - GLubyte indices[] = {0, 1, 2, 0, 2, 3}; - // GLubyte indices[] = {0, 1, 2, 3}; - - - - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - // glEnableClientState(GL_COLOR_ARRAY); - - for (num = 0; num < times; num++) { - glColor4f(1.0f, 1.0f, 1.0f, alpha); - GLfloat texCoords[] = { - 0+spost, 1-spost, - 0+spost, 0+spost, - 1-spost, 0+spost, - 1-spost, 1-spost - }; -/* - GLfloat colors[] = { - 1.0f, 1.0f, 1.0f, alpha, - 1.0f, 1.0f, 1.0f, alpha, - 1.0f, 1.0f, 1.0f, alpha, - 1.0f, 1.0f, 1.0f, alpha - };*/ - - glVertexPointer(2, GL_FLOAT, 0, vertices); - glTexCoordPointer(2, GL_FLOAT, 0, texCoords); - // glColorPointer(4, GL_FLOAT, 0, colors); - - // glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - spost += inc; - alpha = alpha - alphainc; - } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glBindTexture(GL_TEXTURE_2D,0); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -} - - -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 (current_env) { - - switch(current_env->bg_mode) { - - case VS::ENV_BG_KEEP: { - //copy from framebuffer if framebuffer - glClear(GL_DEPTH_BUFFER_BIT); - } break; - case VS::ENV_BG_DEFAULT_COLOR: - case VS::ENV_BG_COLOR: { - //only in the runner - if(is_editor != true) { - Color bgcolor; - if (current_env->bg_mode==VS::ENV_BG_COLOR) - bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR]; - else - bgcolor = Globals::get_singleton()->get("render/default_clear_color"); - // bgcolor = _convert_color(bgcolor); - float a = 1.0; - glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a); - glClearDepthf(1.0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - } else { - glClear(GL_DEPTH_BUFFER_BIT); - } - } break; - case VS::ENV_BG_TEXTURE: - case VS::ENV_BG_CUBEMAP: - case VS::ENV_BG_TEXTURE_RGBE: - case VS::ENV_BG_CUBEMAP_RGBE: { - //a bit broken for now - - glClear(GL_DEPTH_BUFFER_BIT); - } break; - - } - } else { - - Color c = Color(0.3,0.3,0.3); - glClearColor(c.r,c.g,c.b,0.0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - } -#ifdef GLES_OVER_GL - //glClearDepth(1.0); -#else - // glClearDepthf(1.0); -#endif - - // glClear(GL_DEPTH_BUFFER_BIT); - if(current_env->fx_enabled[VS::ENV_FX_FOG]) { - - Color col_begin = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]; - Color col_end = current_env->fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]; - - GLfloat begin[4]={ - col_begin.r, - col_begin.g, - col_begin.b, - 1.0 - }; - GLfloat end[4]={ - col_end.r, - col_end.g, - col_end.b, - 1.0 - }; - glEnable(GL_FOG); - glFogf(GL_FOG_MODE,GL_LINEAR); - glFogf(GL_FOG_DENSITY, current_env->fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]); - glFogf(GL_FOG_START,current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]); - glFogf(GL_FOG_END, camera_z_far); - glFogfv(GL_FOG_COLOR, end); - glLightfv(GL_LIGHT5,GL_DIFFUSE, begin); - - // material_shader.set_conditional( MaterialShaderGLES1::USE_FOG,true); - } - - - - for(int i=0;ifx_enabled[VS::ENV_FX_ES1_BLUR] && !is_editor) { - glViewport(0,0,256,256); - - _render_list_forward(&opaque_render_list); - - glBindTexture(GL_TEXTURE_2D, BlurTexture); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 256, 256, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); - } - - _render_list_forward(&opaque_render_list); - - alpha_render_list.sort_z(); - glEnable(GL_BLEND); - - _render_list_forward(&alpha_render_list); - - glPopMatrix(); - // canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32,false); - /* - canvas_begin(); - glDisable(GL_BLEND); - _set_glcoloro(Color(1,1,1), 1); - // canvas_shader.bind(); - - - List samplers; - sampled_light_owner.get_owned_list(&samplers); - - Size2 debug_size(128,128); - Size2 ofs; - - - for (List::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; - } - }*/ - -// material_shader.set_conditional( MaterialShaderGLES1::USE_FOG,false); - if(current_env->fx_enabled[VS::ENV_FX_ES1_BLUR] && !is_editor) - _process_blur(current_env->fx_param[VS::ENV_FX_PARAM_ES1_BLUR_TIMES], current_env->fx_param[VS::ENV_FX_PARAM_ES1_BLUR_ALPHA]); - - - - // _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(GLuint tex, 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); - _gl_load_transform(modelview); - 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);*/ - Matrix32 modelview; - modelview.translate(p_rect.pos.x, p_rect.pos.y); - // canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, modelview); - _gl_mult_transform(modelview); - glBindTexture(GL_TEXTURE_2D,tex); - - 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); - -} - -void RasterizerGLES1::_debug_draw_shadows_type(Vector& p_shadows,Point2& ofs) { - - -// Size2 debug_size(128,128); - Size2 debug_size(512,512); - - for (int i=0;iowner) - 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); - -} - - - - -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& p_points, const Vector& p_colors,const Vector& 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;itex_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_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 *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; - -} - -void RasterizerGLES1::environment_set_group(RID p_env,VS::Group p_param, const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_GROUP_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->group[p_param]=p_value; - -} -Variant RasterizerGLES1::environment_get_group(RID p_env,VS::Group p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_GROUP_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->group[p_param]; - -} - -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]; - -} - -/* SAMPLED LIGHT */ - -RID RasterizerGLES1::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=false; - - 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) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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_UNSIGNED_BYTE, NULL); - - } - - return sampled_light_owner.make_rid(slight); -}/* -#include "io/resource_saver.h" -#include "scene/resources/texture.h"*/ -void RasterizerGLES1::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) { - - - glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); - - - } else { - //convert to bytes - uint8_t *tex8 = (uint8_t*)alloca(slight->w*slight->h*4); - // DVector tex; - const float* src=(const float*)p_data; - - for(int i=0;iw*slight->h*4;i++) { - - tex8[i]=Math::fast_ftoi(CLAMP(src[i]*255.0,0.0,255.0)); - // tex.push_back(Math::fast_ftoi(CLAMP(src[i]*255.0,0.0,255.0))); - } - /* - Image img(slight->w,slight->h,0,Image::FORMAT_RGBA,tex); - Ref it = memnew( ImageTexture ); - it->create_from_image(img); - ResourceSaver::save("baked.png",it);*/ - glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_UNSIGNED_BYTE,p_data); - } - - slight->multiplier=p_multiplier; - -} - -/*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;isurfaces.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;imorph_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 ); - } else if (sampled_light_owner.owns(p_rid)) { - - SampledLight *sampled_light = sampled_light_owner.get( p_rid ); - ERR_FAIL_COND(!sampled_light); - - sampled_light_owner.free(p_rid); - memdelete( sampled_light ); - }; -} - - -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& p_info) { - -}; - -void RasterizerGLES1::custom_shade_model_get_param_info(int p_model, List* 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;imake_current(); - - - - Set extensions; - Vector strings = String((const char*)glGetString( GL_EXTENSIONS )).split(" ",false); - for(int i=0;i textures; - texture_owner.get_owned_list(&textures); - keep_copies=false; - for(List::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) { - skinned_buffer = NULL; - - keep_copies=p_keep_copies; - pack_arrays=false; - use_reload_hooks=p_use_reload_hooks; - - frame = 0; -}; - -RasterizerGLES1::~RasterizerGLES1() { - -}; - - -#endif diff --git a/platform/wiiu/SCsub b/platform/wiiu/SCsub new file mode 100644 index 00000000..d7fd720e --- /dev/null +++ b/platform/wiiu/SCsub @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +Import('env') + + +common_server = [ + "os_wiiu.cpp", + # "audio_driver_psp.cpp", + "rasterizer_wiiu.cpp", + "mutex_wiiu.cpp", + "thread_wiiu.cpp" +] + +prog = env.Program('#bin/fe_wiiu', ['godot_wiiu.cpp'] + common_server) + +env.Command( + "#FusionEngine.rpx", prog ,"elf2rpl bin/fe_wiiu.wiiu.opt.32 FusionEngine.rpx" +) +# +# env.Command( +# "#bin/strip.elf", "#bin/godot.elf" ,"psp-strip bin/godot.elf -o bin/strip.elf" +# ) +# +# env.Command( +# "#bin/EBOOT.PBP", "#bin/strip.elf" ,"pack-pbp bin/EBOOT.PBP bin/PARAM.SFO NULL NULL NULL NULL NULL bin/strip.elf NULL" +# ) diff --git a/platform/wiiu/audio_driver_3ds.cpp b/platform/wiiu/audio_driver_3ds.cpp new file mode 100644 index 00000000..bbb7fbef --- /dev/null +++ b/platform/wiiu/audio_driver_3ds.cpp @@ -0,0 +1,171 @@ +/*************************************************************************/ +/* audio_driver_psp.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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_psp.h" +#include "core/os/thread.h" +#include "globals.h" +#include "os/os.h" +#include + +#define PPSSPP + +static int channel_num = 1; + +int32_t* buffer; + +Error AudioDriverPSP::init() { + thread_exited=false; + exit_thread=false; + pcm_open = false; + samples_in = NULL; + + mix_rate = 44100; + output_format = OUTPUT_STEREO; + channels = 2; + + int latency = GLOBAL_DEF("audio/output_latency",25); + buffer_size = next_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); + + // channel_num = sceAudioChReserve(1, PSP_AUDIO_SAMPLE_ALIGN(buffer_size*channels), PSP_AUDIO_FORMAT_MONO); + sceAudioOutput2Reserve(buffer_size); + + mutex = Mutex::create(); + thread = Thread::create(AudioDriverPSP::thread_func, this); + + + return OK; +}; + +void AudioDriverPSP::thread_func(void *p_udata) { + + int buffer_index = 0; + printf("out\n"); + AudioDriverPSP* ad = (AudioDriverPSP*)p_udata; + + int sample_count = ad->buffer_size ; + uint64_t usdelay = (ad->buffer_size / float(ad->mix_rate)) * 1000000; + + while (!ad->exit_thread) { + + + if (ad->exit_thread) + break; +#ifndef PPSSPP + while(sceAudioWaitInputEnd()) { + OS::get_singleton()->delay_usec(usdelay); + } +#endif + if (ad->active) { + ad->lock(); + + ad->audio_server_process(ad->buffer_size, ad->samples_in); + + ad->unlock(); + + for(int i = 0; i < sample_count*2; ++i) { + ad->samples_out[i] = ad->samples_in[i] >> 16; + } + + + } else + { + for (int i = 0; i < sample_count*2; i++) { + + ad->samples_out[i] = 0; + } + } +// #ifdef PPSSPP +// OS::get_singleton()->delay_usec(usdelay); +// #endif + sceAudioOutput2OutputBlocking(0x8000, ad->samples_out); + } + + + ad->thread_exited=true; +}; + +void AudioDriverPSP::start() { + printf("psp audio start\n"); + active = true; +}; + +int AudioDriverPSP::get_mix_rate() const { + + return mix_rate; +}; + +AudioDriverSW::OutputFormat AudioDriverPSP::get_output_format() const { + + return output_format; +}; +void AudioDriverPSP::lock() { + + if (!thread || !mutex) + return; + mutex->lock(); +}; +void AudioDriverPSP::unlock() { + + if (!thread || !mutex) + return; + mutex->unlock(); +}; + +void AudioDriverPSP::finish() { + exit_thread = true; + Thread::wait_to_finish(thread); + + sceAudioOutput2Release(); + + if (samples_in) { + memdelete_arr(samples_in); + }; + if (samples_out) { + memdelete_arr(samples_out); + }; + + + if (mutex) + memdelete(mutex); + +}; + +AudioDriverPSP::AudioDriverPSP() { + + mutex = NULL; + active = false; + id = NULL; +}; + +AudioDriverPSP::~AudioDriverPSP() { + +}; diff --git a/platform/wiiu/audio_driver_3ds.h b/platform/wiiu/audio_driver_3ds.h new file mode 100644 index 00000000..d1387c0d --- /dev/null +++ b/platform/wiiu/audio_driver_3ds.h @@ -0,0 +1,84 @@ +/*************************************************************************/ +/* audio_driver_3ds.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 AUDIO_DRIVER_PSP_H +#define AUDIO_DRIVER_PSP_H + +#include "servers/audio/audio_server_sw.h" + +#include "core/os/thread.h" +#include "core/os/mutex.h" + +#include +#include +#include +#include + +class AudioDriverPSP : public AudioDriverSW { + + Thread *thread; + Mutex *mutex; + int32_t* samples_in; + int16_t* samples_out; + int id; + + static void thread_func(void *p_udata); + + + int buffer_size; + + unsigned int mix_rate; + OutputFormat output_format; + + int channels; + + bool active; + bool thread_exited; + bool exit_thread; + bool pcm_open; + +public: + + const char* get_name() const { + return "PSP Audio"; + }; + + 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(); + + AudioDriverPSP(); + ~AudioDriverPSP(); +}; + +#endif diff --git a/platform/wiiu/detect.py b/platform/wiiu/detect.py new file mode 100644 index 00000000..4b10fb22 --- /dev/null +++ b/platform/wiiu/detect.py @@ -0,0 +1,81 @@ + +import os +import sys + + +def is_active(): + return True + + +def get_name(): + return "wiiu" + + +def can_build(): + + if (os.name != "posix"): + return False + + return True # enabled + + +def get_opts(): + return [] + + + +def get_flags(): + + return [ + ('builtin_zlib', 'no'), + ('tools', 'no'), + ('theora','no'), + ('module_pspmath_enabled', 'no'), + ] + +def configure(env): + env.disabled_modules = ['openssl','webp'] + + env["bits"] = "32" + devkitpro_path = os.environ["DEVKITPRO"] + devkitarm_path = devkitpro_path + "/devkitPPC" + wut_path = devkitpro_path + "/wut" + + env.Append(CPPPATH=['#platform/wiiu']) + env["CC"] = devkitarm_path + "/bin/powerpc-eabi-gcc" + env["CXX"] = devkitarm_path + "/bin/powerpc-eabi-g++" + env["LD"] = devkitarm_path + "/bin/powerpc-eabi-g++" + env["AR"] = devkitarm_path + "/bin/powerpc-eabi-ar" + env["RANLIB"] = devkitarm_path + "/bin/powerpc-eabi-ranlib" + env["AS"] = devkitarm_path + "/bin/powerpc-eabi-as" + + arch = ['-isystem', '-mcpu=750' '-meabi', '-mhard-float', '-ffunction-sections', '-fdata-sections'] + env.Append(CCFLAGS=['-g','-Wall', '-std=gnu++11'] + arch) + env.Append(CCFLAGS=[ '-DESPRESSO', '-D__WIIU__', '-D__WUT__','-DNEED_LONG_INT', '-DLIBC_FILEIO_ENABLED','-DNO_SAFE_CAST', '-DPTHREAD_NO_RENAME']) + + env.Append(CPPPATH=[wut_path+"/include", devkitpro_path +"/portlibs/wiiu/include/", devkitpro_path +"/portlibs/ppc/include/"]) + env.Append(LIBPATH=[wut_path+"/lib", devkitpro_path+"/portlibs/wiiu/lib/", devkitpro_path+"/portlibs/ppc/lib/"]) + # env.Append(DEVKITPRO=devkitpro_path) + env.Append(ENV={"DEVKITPRO": devkitpro_path}) + env.Append(LINKFLAGS=["-specs="+wut_path+"/share/wut.specs"]) + # env.Append(LIBPATH=[devkitpro_path+"/portlibs/armv6k/lib", devkitpro_path + + # "/portlibs/3ds/lib", ctrulib_path + "/lib", devkitarm_path + "/arm-none-eabi/lib/armv6k/fpu"]) + + # env.Append(LINKFLAGS=['-specs=3dsx.specs', '-g'] + arch) + env.Append(LIBS=["SDL2","m",'OSMesa32', 'GLU', "wut"]) + env.Append(LIBS=["png", "z"]) + + + + if (env["target"] == "release"): + #if (env["debug_release"] == "yes"): + # env.Append(CCFLAGS=['-g2']) + #else: + env.Append(CCFLAGS=['-Ofast']) + elif (env["target"] == "release_debug"): + env.Append(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED']) + #if (env["debug_release"] == "yes"): + env.Append(CCFLAGS=['-g2']) + elif (env["target"] == "debug"): + env.Append(CCFLAGS=['-O3','-g2','-Wall', + '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) diff --git a/platform/wiiu/export/export.cpp b/platform/wiiu/export/export.cpp new file mode 100644 index 00000000..a47f0335 --- /dev/null +++ b/platform/wiiu/export/export.cpp @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* export.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "export.h" +#include "editor/editor_import_export.h" +#include "platform/wiiu/logo.gen.h" +#include "scene/resources/texture.h" + +void register_wiiu_exporter() { + + Image img(_wiiu_logo); + Ref logo = memnew(ImageTexture); + logo->create_from_image(img); + + { + Ref exporter = Ref(memnew(EditorExportPlatformPC)); + exporter->set_binary_extension("rpx"); + exporter->set_release_binary32("FusionEngine.rpx"); + exporter->set_name("Wii U"); + exporter->set_logo(logo); + // exporter->set_chmod_flags(0755); + EditorImportExport::get_singleton()->add_export_platform(exporter); + } +} diff --git a/platform/wiiu/export/export.h b/platform/wiiu/export/export.h new file mode 100644 index 00000000..8323af7a --- /dev/null +++ b/platform/wiiu/export/export.h @@ -0,0 +1,31 @@ +/*************************************************************************/ +/* export.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +void register_wiiu_exporter(); diff --git a/platform/wiiu/godot_wiiu.cpp b/platform/wiiu/godot_wiiu.cpp new file mode 100644 index 00000000..a0a6b988 --- /dev/null +++ b/platform/wiiu/godot_wiiu.cpp @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* godot_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include +#include + +#include "main/main.h" + +#include +#include + +#include +#include +#include "os_wiiu.h" +// #include "CafeGLSLCompiler.h" +#include +int main(int argc, char *argv[]) { + WHBProcInit(); + // WHBGfxInit(); + WHBLogConsoleInit(); + WHBMountSdCard(); + AXInit(); + // GLSL_Init(); + // ramfsInit(); + if (SDL_Init(SDL_INIT_VIDEO) < 0) + OSReport("ERROR: cannot initialize SDL video.%s\n", SDL_GetError()); + OSReport("Fusion wiiu\n"); + OS_WIIU os; + + OSReport("Fusion wiiu OS init\n"); + char* args[] = {"-path", WHBGetSdCardMountPath()}; + OSReport("setup\n"); + + Error err = Main::setup("wiiu", 2, args, true); + OSReport("setup\n"); + + + if (err!=OK) + return 0; + + if (Main::start()) { + OSReport("game running\n"); + os.run(); // it is actually the OS that decides how to run + } + Main::cleanup(); + //GLSL_Shutdown(); + + AXQuit(); + WHBLogConsoleFree(); + WHBProcShutdown(); + SYSLaunchMenu(); + return 0; +} diff --git a/platform/wiiu/logo.gen.h b/platform/wiiu/logo.gen.h new file mode 100644 index 00000000..71faf20f --- /dev/null +++ b/platform/wiiu/logo.gen.h @@ -0,0 +1,2 @@ + /* AUTOGENERATED FILE, DO NOT EDIT */ + static const unsigned char _wiiu_logo[]={0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0x73,0x7a,0x7a,0xf4,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x5,0x69,0x49,0x44,0x41,0x54,0x58,0x47,0xad,0x57,0x5d,0x48,0x55,0x59,0x14,0x5e,0x5e,0xef,0xcd,0xfc,0xcd,0x30,0x8c,0x82,0x4a,0x25,0x25,0x2d,0xed,0x32,0xca,0x48,0xa3,0x10,0xe9,0x43,0x8a,0xca,0x20,0xa2,0x70,0xd,0x54,0x4,0x5f,0x84,0xe9,0xc1,0x1e,0x2,0x71,0x20,0x98,0x97,0x31,0x7a,0x11,0x9,0x1f,0x64,0x34,0xe8,0xa1,0x3f,0x2a,0xd,0x25,0x46,0x99,0x1e,0x14,0x46,0x18,0x68,0xfc,0x21,0x7d,0x68,0xa2,0x84,0x34,0x13,0xcc,0xb4,0xc2,0xb0,0x6b,0x9d,0xf9,0xbe,0xed,0xd9,0xb7,0x73,0x8f,0xe7,0xea,0xa5,0x99,0xf,0xd6,0xdd,0xfb,0xec,0xb5,0xf6,0xfe,0xd6,0x5e,0x7b,0xed,0x9f,0x1b,0x21,0x61,0x22,0x37,0x37,0x77,0x8f,0x61,0x18,0x65,0x2e,0x97,0xab,0x8,0x9f,0x5e,0xd4,0x53,0x22,0x22,0x22,0x12,0xa9,0x43,0x7d,0x5,0xf5,0x59,0x54,0x27,0xbe,0x7c,0xf9,0xf2,0x8,0xf5,0xc1,0xc7,0x8f,0x1f,0xaf,0x52,0xb7,0x13,0x76,0x74,0x20,0x27,0x27,0x27,0x23,0x2a,0x2a,0xea,0x22,0x48,0x7c,0x20,0x8f,0x86,0x8,0x8,0x94,0x58,0x1,0xbd,0x12,0x38,0x40,0xf9,0x8,0xfd,0x8d,0xf5,0xf5,0xf5,0xf6,0xa9,0xa9,0xa9,0xa7,0xa6,0x89,0x23,0x42,0x3a,0x80,0x19,0xc7,0x60,0xc0,0x5f,0x22,0x23,0x23,0x7f,0x2,0xa9,0x87,0xc4,0x9a,0x9c,0x70,0x72,0x40,0x97,0xa6,0x13,0x14,0xff,0xe7,0xcf,0x9f,0x3b,0x61,0xfb,0x33,0x22,0xb2,0xa6,0xc,0x6c,0x70,0x74,0xc0,0xeb,0xf5,0xa6,0xbb,0xdd,0xee,0xfb,0x20,0x3c,0xe,0x7,0x2,0xc4,0x5a,0xb6,0x83,0x8e,0x84,0x76,0x4,0xe,0xb0,0x9c,0xde,0xd8,0xd8,0xa8,0x9c,0x98,0x98,0xf8,0xc7,0x34,0xb,0x60,0xcb,0x68,0xdf,0x1,0x20,0xfc,0x1d,0xb2,0xf,0x4e,0x84,0x4d,0x6c,0x87,0xd5,0x11,0x90,0xd3,0x89,0x25,0xc8,0xd9,0xbf,0x1,0xd3,0x44,0x21,0x68,0x54,0xce,0x1c,0xc4,0x7f,0x82,0x38,0x88,0xfc,0xbf,0xc0,0xea,0x4,0x84,0x4e,0xfc,0x60,0x8d,0x44,0xa4,0x59,0xaa,0x35,0x7,0xd9,0x1f,0x8,0x79,0xa,0xc9,0x75,0xd8,0xed,0x48,0x4a,0x4a,0x92,0xc6,0xc6,0x46,0xd9,0xbd,0x7b,0xb7,0x2c,0x2f,0x2f,0xcb,0xa7,0x4f,0x9f,0x4c,0x8d,0x33,0xf4,0x18,0x66,0x19,0x3,0x29,0x3a,0x78,0xf0,0xe0,0xb5,0x85,0x85,0x5,0x3f,0x1b,0x2,0xe,0xec,0xdf,0xbf,0xff,0x57,0x90,0xfe,0xb8,0x1d,0x39,0x41,0x7,0x2e,0x5d,0xba,0x24,0xc5,0xc5,0xc5,0xe2,0xf3,0xf9,0x24,0x2f,0x2f,0x4f,0x12,0x12,0x12,0x64,0x69,0x69,0x49,0xde,0xbf,0x7f,0x6f,0x5a,0x39,0x83,0x63,0x22,0x2,0xc9,0xc8,0x8b,0xe8,0xd7,0xaf,0x5f,0xf,0xa9,0x36,0xfe,0x70,0xab,0x61,0xe6,0x4f,0x40,0xee,0xd1,0xa1,0xf,0x85,0x43,0x87,0xe,0xc9,0xcd,0x9b,0x37,0xcd,0xaf,0xaf,0x60,0x98,0xc7,0xc7,0xc7,0xa5,0xb7,0xb7,0x57,0x6c,0xcb,0x1c,0x80,0x65,0x29,0xb8,0x3b,0x4e,0x70,0x8b,0xba,0xa8,0x0,0xe1,0x45,0x88,0x47,0x13,0xeb,0x75,0xb,0x25,0x76,0xd0,0xa1,0xb7,0x6f,0xdf,0x32,0x81,0xa5,0xb3,0xb3,0x53,0x9a,0x9b,0x9b,0x43,0xf6,0x23,0x87,0xc9,0x75,0x91,0xdf,0xae,0xb4,0xb4,0xb4,0x3d,0x28,0x7d,0xdf,0x4a,0xfe,0xee,0xdd,0x3b,0xe9,0xe8,0xe8,0x90,0xbb,0x77,0xef,0x9a,0x2d,0x22,0xe7,0xce,0x9d,0x93,0x92,0x92,0x92,0x90,0xfd,0x4d,0x2e,0x1f,0xb9,0x5d,0x48,0xa6,0x32,0x34,0x44,0x87,0xeb,0x0,0xd6,0x50,0xd9,0x69,0xf0,0x9b,0xed,0x1f,0x3e,0x7c,0x30,0x5b,0x36,0x51,0x53,0x53,0xb3,0xa5,0x2f,0x85,0x20,0x17,0x39,0xc9,0x8d,0x7c,0x53,0x67,0xbb,0x2,0xd,0x38,0xe0,0x76,0xa2,0x7,0xb1,0x82,0xed,0x76,0x64,0x64,0x64,0x8,0xf,0xb1,0xed,0xfa,0x93,0xdb,0x85,0x6,0xaf,0xf9,0x1d,0xf0,0x72,0x27,0xb1,0xc3,0xa9,0x9d,0x3b,0x29,0x36,0x36,0x36,0xa8,0x9f,0xdd,0xe,0x75,0x2f,0x93,0x30,0xc5,0xfc,0x8,0x5b,0xec,0x70,0x6a,0x23,0x78,0x46,0xd8,0xfb,0x6a,0x31,0x91,0xc2,0x8,0x24,0xda,0x95,0xdb,0x89,0x13,0x9c,0x74,0xaf,0x5e,0xbd,0x52,0xe7,0x82,0xb5,0xaf,0x83,0x24,0xd2,0x1,0xd5,0x41,0x97,0x3b,0xc1,0x6e,0x17,0xaa,0x5f,0x4f,0x4f,0x8f,0x59,0xdb,0xa,0x2b,0x27,0x97,0x60,0xc5,0xda,0x10,0x4a,0xb2,0xb2,0xb2,0xe4,0xc2,0x85,0xb,0xe2,0xf1,0x78,0x94,0xad,0x15,0xd4,0x3f,0x7c,0xf8,0x50,0xae,0x5c,0xb9,0x22,0xd7,0xaf,0x5f,0x97,0xf3,0xe7,0xcf,0xcb,0xbd,0x7b,0xf7,0xb6,0x8c,0xa1,0x45,0xf7,0x1,0x56,0xdc,0xa8,0xcc,0x42,0x92,0xb4,0xc2,0x8a,0xc3,0x87,0xf,0x4b,0x69,0x69,0xa9,0x92,0x23,0x47,0x8e,0xa8,0xb6,0x7,0xf,0x1e,0xa8,0xd2,0x8e,0xbd,0x7b,0xf7,0x8a,0xdf,0xef,0x57,0x77,0x44,0x55,0x55,0x95,0x3a,0xa6,0xb9,0x35,0x71,0xe6,0xcb,0xcc,0xcc,0x8c,0x8c,0x8d,0x8d,0xa9,0x33,0x43,0x83,0x7c,0xe4,0xa6,0x3,0x13,0x90,0x5c,0x36,0x70,0x7f,0x72,0x80,0x8a,0x8a,0xa,0x25,0xd9,0xd9,0xd9,0xa6,0xf9,0x26,0x38,0x10,0xef,0x77,0x3b,0x4e,0x9d,0x3a,0x25,0x57,0xaf,0x5e,0x35,0xbf,0x36,0x31,0x37,0x37,0xa7,0xf2,0xe0,0xd8,0xb1,0x63,0x52,0x57,0x57,0xa7,0x9c,0x1b,0x1a,0x1a,0x92,0xcb,0x97,0x2f,0xcb,0xea,0xea,0xaa,0x76,0x60,0xc2,0x85,0x1,0x1f,0xe9,0x3d,0x4a,0xe3,0xfe,0xfe,0x7e,0x69,0x6d,0x6d,0xd,0x90,0xcf,0xcf,0xcf,0x4b,0x77,0x77,0xb7,0x54,0x56,0x56,0x4a,0x6d,0x6d,0xad,0xe3,0xed,0xa7,0xf,0x31,0x12,0x72,0xed,0xab,0xab,0xab,0xa5,0xbc,0xbc,0x5c,0x5a,0x5a,0x5a,0xe4,0xce,0x9d,0x3b,0x4a,0xc7,0xa5,0x2b,0x2b,0x2b,0x53,0x7,0x94,0xe6,0x23,0xb7,0x1b,0x95,0x41,0x54,0x3e,0x62,0xdf,0x46,0xf3,0x2c,0x4f,0x4e,0x4e,0x56,0x1d,0x88,0xf6,0xf6,0x76,0x75,0xce,0xef,0xda,0xb5,0x4b,0xa,0xb,0xb,0xd5,0xda,0x76,0x75,0x75,0x99,0xda,0xaf,0x98,0x9d,0x9d,0x95,0x86,0x86,0x6,0x99,0x9c,0x9c,0x14,0x5e,0x66,0x5,0x5,0x5,0xd2,0xd4,0xd4,0x24,0xa7,0x4f,0x9f,0x16,0xbc,0x27,0x4d,0x2b,0x51,0x97,0x55,0x5f,0x5f,0x9f,0x9a,0x3d,0x39,0xc9,0xad,0x14,0xe9,0xe9,0xe9,0xbf,0x21,0xc9,0xc,0x3c,0x48,0xc,0x24,0x92,0xf1,0xec,0xd9,0x33,0xd8,0x18,0x6,0x6e,0x2d,0xe3,0xcd,0x9b,0x37,0x6,0xc2,0xa7,0xbe,0x9,0xcc,0xce,0xac,0x6d,0x2,0x6f,0x2,0xe3,0xe4,0xc9,0x93,0x46,0x7d,0x7d,0xbd,0x71,0xfb,0xf6,0x6d,0x63,0x65,0x85,0x39,0xfd,0x15,0x8,0xb7,0x81,0x28,0x28,0x3d,0x6e,0x5d,0x3,0x91,0x35,0xc8,0x45,0x4e,0x72,0xab,0xd8,0xa5,0xa6,0xa6,0x66,0x60,0x96,0xea,0x3a,0xe6,0x9,0xc6,0x90,0x32,0x12,0x99,0x99,0x99,0x72,0xe0,0xc0,0x1,0x35,0xb,0x86,0x1e,0x77,0xb8,0x9a,0x2d,0x67,0xa1,0xc1,0x5b,0xb0,0xad,0xad,0x2d,0x28,0x7,0x68,0x3b,0x32,0x32,0x22,0x83,0x83,0x83,0x32,0x3a,0x3a,0xaa,0xd6,0x9f,0x80,0x3f,0x2a,0xf4,0xbc,0x8e,0x61,0x73,0xe2,0xc5,0x8b,0x17,0x4f,0xdd,0x54,0xb0,0x72,0xf4,0xe8,0xd1,0x4e,0x90,0xb7,0xe8,0xf5,0x5c,0x5c,0x5c,0x54,0x62,0x47,0x7c,0x7c,0xbc,0xdc,0xba,0x75,0x4b,0xce,0x9c,0x39,0x13,0xb4,0x5c,0x1c,0x9c,0xef,0x80,0x81,0x81,0x1,0x19,0x1e,0x1e,0xe,0xca,0x78,0xd,0xed,0x0,0xc2,0xdf,0x49,0x4e,0xb6,0x6d,0xb2,0x1,0x98,0x69,0x4c,0x5c,0x5c,0xdc,0x5f,0x88,0xc2,0x71,0x1d,0x5,0xed,0x8c,0x13,0xa8,0x63,0xa2,0xe6,0xe7,0xe7,0xab,0x88,0x70,0xed,0xb9,0xe5,0x9c,0x40,0x62,0xcb,0xec,0xa7,0xb1,0x3d,0xbf,0x87,0xad,0x7a,0xa6,0x7,0x31,0xe0,0x7e,0x56,0x8f,0x52,0x64,0xec,0x3e,0xed,0xc4,0xff,0x1,0x4d,0x8e,0xa5,0x50,0x8f,0xd2,0xe7,0xcf,0x9f,0x7,0x1e,0xa5,0xea,0x45,0xa4,0x41,0x5,0x8c,0xcf,0x9a,0x86,0xaa,0x13,0x3b,0x7f,0x2b,0x34,0xb1,0x26,0xe7,0xd8,0x56,0x72,0xc2,0x71,0x8a,0x66,0x24,0xee,0xe3,0x3e,0xf,0x6b,0x39,0x9c,0x40,0x72,0xed,0x0,0xd6,0x7c,0x1a,0x65,0xa5,0x9d,0x9c,0x8,0xbc,0x8a,0xad,0x40,0x66,0x2f,0x23,0xf3,0xaf,0x81,0x3c,0x1a,0x9f,0x79,0x20,0xf,0xb2,0xb,0xe5,0x8c,0x8e,0x96,0x26,0x7,0xb1,0x1f,0x6b,0xde,0xb1,0xb6,0xb6,0x56,0xfb,0xf2,0xe5,0xcb,0xad,0x19,0xd,0xec,0x38,0x2d,0x6e,0x51,0x38,0xc2,0x47,0xab,0xf,0x11,0x9,0x3c,0xdd,0xec,0x4e,0x58,0xc9,0x79,0xc8,0xa0,0xbc,0x81,0x59,0xb7,0xeb,0x6c,0xf,0x85,0xb0,0xe3,0xca,0x7,0x24,0x6,0xe5,0xfb,0xb1,0x8,0xc2,0x57,0x54,0xd0,0xdf,0x73,0x14,0xbc,0xd4,0x78,0xaf,0xa8,0xbf,0xe7,0x8,0x77,0x18,0x7f,0xcf,0x45,0xfe,0x5,0xd3,0xc1,0xab,0x57,0x1d,0x1d,0x1e,0x96,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82}; diff --git a/platform/wiiu/logo.png b/platform/wiiu/logo.png new file mode 100644 index 00000000..d11c887a Binary files /dev/null and b/platform/wiiu/logo.png differ diff --git a/platform/wiiu/mutex_wiiu.cpp b/platform/wiiu/mutex_wiiu.cpp new file mode 100644 index 00000000..96f6c449 --- /dev/null +++ b/platform/wiiu/mutex_wiiu.cpp @@ -0,0 +1,74 @@ +/*************************************************************************/ +/* mutex_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "mutex_wiiu.h" +#include "os/memory.h" + +#if defined(__WIIU__) + +void MutexWiiu::lock() { + + mutex.lock(); +} +void MutexWiiu::unlock() { + + mutex.unlock(); +} +Error MutexWiiu::try_lock() { + + return mutex.try_lock() ? OK : ERR_BUSY; +} + +Mutex *MutexWiiu::create_func_wiiu(bool p_recursive) { + + return memnew(MutexWiiu(p_recursive)); +} + +void MutexWiiu::make_default() { + + create_func = create_func_wiiu; +} + +MutexWiiu::MutexWiiu(bool p_recursive) { + + // pthread_mutexattr_init(&attr); + // if (p_recursive) + // pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + // pthread_mutex_init(&mutex, &attr); + if(!p_recursive) + printf("non recursive thread!\n"); +} + +MutexWiiu::~MutexWiiu() { + + // pthread_mutex_destroy(&mutex); +} + +#endif diff --git a/platform/wiiu/mutex_wiiu.h b/platform/wiiu/mutex_wiiu.h new file mode 100644 index 00000000..2e8005bc --- /dev/null +++ b/platform/wiiu/mutex_wiiu.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* mutex_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MUTEX_WIIU_H +#define MUTEX_WIIU_H + +#if defined(__WIIU__) + +#include "os/mutex.h" +#include +#include + +class MutexWiiu : public Mutex { + + // pthread_mutexattr_t attr; + std::recursive_mutex mutex; + + static Mutex *create_func_wiiu(bool p_recursive); + +public: + virtual void lock(); + virtual void unlock(); + virtual Error try_lock(); + + static void make_default(); + + MutexWiiu(bool p_recursive); + + ~MutexWiiu(); +}; + +#endif + +#endif diff --git a/platform/wiiu/os_wiiu.cpp b/platform/wiiu/os_wiiu.cpp new file mode 100644 index 00000000..bf4166a4 --- /dev/null +++ b/platform/wiiu/os_wiiu.cpp @@ -0,0 +1,442 @@ +/*************************************************************************/ +/* OS_WIIU.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "os_wiiu.h" +#include "print_string.h" +#include "servers/physics/physics_server_sw.h" +#include "servers/visual/rasterizer_dummy.h" + +#include "servers/visual/visual_server_raster.h" +#include +#include +// #include "drivers/unix/mutex_posix.h" +// #include "drivers/unix/thread_posix.h" +#include "thread_wiiu.h" +#include "mutex_wiiu.h" +#include "drivers/unix/file_access_unix.h" +#include "drivers/unix/dir_access_unix.h" +#include "core/os/thread_dummy.h" +#include "drivers/unix/memory_pool_static_malloc.h" +#include "os/memory_pool_dynamic_static.h" + +#include "main/main.h" +#include +#include + +#include +#include +#include +int OS_WIIU::get_video_driver_count() const { + + return 1; +} +const char *OS_WIIU::get_video_driver_name(int p_driver) const { + + return "GLES1"; +} +OS::VideoMode OS_WIIU::get_default_video_mode() const { + + return OS::VideoMode(1920, 1080, false); +} + +static MemoryPoolStaticMalloc *mempool_static=NULL; +static MemoryPoolDynamicStatic *mempool_dynamic=NULL; + +void OS_WIIU::initialize_core() { + + printf("init core\n"); + ThreadDummy::make_default(); //TODO: Implement a thread handler for the wiiu + SemaphoreDummy::make_default(); + MutexWiiu::make_default(); + printf("init fs\n"); + + ticks_start = 0; + ticks_start = get_ticks_usec(); + + mempool_static = new MemoryPoolStaticMalloc; + mempool_dynamic = memnew( MemoryPoolDynamicStatic ); + + FileAccess::make_default(FileAccess::ACCESS_RESOURCES); + FileAccess::make_default(FileAccess::ACCESS_USERDATA); + FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); + //FileAccessBufferedFA::make_default(); + DirAccess::make_default(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default(DirAccess::ACCESS_USERDATA); + DirAccess::make_default(DirAccess::ACCESS_FILESYSTEM); +} + +void OS_WIIU::finalize_core() { + if (mempool_dynamic) + memdelete( mempool_dynamic ); + delete mempool_static; +} + + +void OS_WIIU::alert(const String &p_alert, const String &p_title) { + OSReport(p_alert.utf8().get_data()); +} +String OS_WIIU::get_stdin_string(bool p_block) { + return ""; +} + +Error OS_WIIU::execute(const String& p_path, const List& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) { + return FAILED; +} + +Error OS_WIIU::kill(const ProcessID &p_pid) { + return FAILED; +} +bool OS_WIIU::has_environment(const String &p_var) const { + return false; +} +String OS_WIIU::get_environment(const String &p_var) const { + return ""; +} + +OS::Date OS_WIIU::get_date() const { + Date ret; + return ret; +} + +OS::Time OS_WIIU::get_time() const { + Time ret; + return ret; +} + +void OS_WIIU::delay_usec(uint32_t p_usec) const{ +// printf("delay_usec: %lu\n", p_usec); + usleep(p_usec); +} + +uint64_t OS_WIIU::get_ticks_usec() const{ + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + + uint64_t longtime = (uint64_t)tv_now.tv_usec + (uint64_t)tv_now.tv_sec * 1000000L; + longtime -= ticks_start; + + return longtime; +} + +void OS_WIIU::vprint(const char* p_format, va_list p_list,bool p_stder) +{ + if (p_stder) { + vfprintf(stderr,p_format,p_list); + fflush(stderr); + } else { + vprintf(p_format,p_list); + fflush(stdout); + } +} + +void OS_WIIU::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { + + args = OS::get_singleton()->get_cmdline_args(); + current_videomode = p_desired; + main_loop = NULL; + + + + window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1920, 1080, 0); + screen = SDL_CreateRGBSurface(SDL_WINDOW_SHOWN, 1920, 1080, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + + ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL ); + if (!ctx) + OSReport("OSMesaCreateContext failed!\n"); + + + frameBuffer = calloc(1920 * 1080 * 4, sizeof(GLfloat)); + if (!OSMesaMakeCurrent(ctx, frameBuffer, GL_FLOAT, 1920, 1080)) + OSReport("OSMesaMakeCurrent failed!\n"); + + OSMesaPixelStore(OSMESA_Y_UP, 0); + OSReport("mesa\n"); + mesa = true; + + rasterizer = memnew(RasterizerGLES1); + + + visual_server = memnew(VisualServerRaster(rasterizer)); + + // AudioDriverManagerSW::add_driver(&audio_driver); + // AudioDriverManagerSW::initialize(p_audio_driver); + AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); + + if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) { + + ERR_PRINT("Initializing audio failed."); + } + + sample_manager = memnew(SampleManagerMallocSW); + audio_server = memnew(AudioServerSW(sample_manager)); + audio_server->init(); + spatial_sound_server = memnew(SpatialSoundServerSW); + spatial_sound_server->init(); + spatial_sound_2d_server = memnew(SpatialSound2DServerSW); + spatial_sound_2d_server->init(); + + ERR_FAIL_COND(!visual_server); + + visual_server->init(); + + // + physics_server = memnew( PhysicsServerSW ); + physics_server->init(); + physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server->init(); + + input = memnew(InputDefault); + +} +void OS_WIIU::finalize() { + + if (main_loop) + memdelete(main_loop); + main_loop = NULL; + + spatial_sound_server->finish(); + memdelete(spatial_sound_server); + spatial_sound_2d_server->finish(); + memdelete(spatial_sound_2d_server); + + //if (debugger_connection_console) { + // memdelete(debugger_connection_console); + //} + + memdelete(sample_manager); + + audio_server->finish(); + memdelete(audio_server); + + visual_server->finish(); + memdelete(visual_server); + memdelete(rasterizer); + + physics_server->finish(); + memdelete(physics_server); + + physics_2d_server->finish(); + memdelete(physics_2d_server); + + memdelete(input); + + args.clear(); +} + +void OS_WIIU::set_mouse_show(bool p_show) { +} +void OS_WIIU::set_mouse_grab(bool p_grab) { + + grab = p_grab; +} +bool OS_WIIU::is_mouse_grab_enabled() const { + + return grab; +} + +int OS_WIIU::get_mouse_button_state() const { + + return 0; +} + +Point2 OS_WIIU::get_mouse_pos() const { + + return Point2(); +} + +void OS_WIIU::set_window_title(const String &p_title) { +} + +void OS_WIIU::set_video_mode(const VideoMode &p_video_mode, int p_screen) { +} +OS::VideoMode OS_WIIU::get_video_mode(int p_screen) const { + + return current_videomode; +} + +Size2 OS_WIIU::get_window_size() const { + + return Vector2(current_videomode.width, current_videomode.height); +} + +void OS_WIIU::get_fullscreen_mode_list(List *p_list, int p_screen) const { +} + +const char *OS_WIIU::get_audio_driver_name(int p_driver) const{ + return "dummy"; +} +int OS_WIIU::get_audio_driver_count() const{ + return 1; +} + +MainLoop *OS_WIIU::get_main_loop() const { + + return main_loop; +} + +void OS_WIIU::init_keys() { + // sceCtrlSetSamplingCycle(0); + // sceCtrlSetSamplingMode(3DS_CTRL_MODE_ANALOG); +} + +// 3DSCtrlButtons buttons[16] = { +// 3DS_CTRL_CROSS, +// 3DS_CTRL_CIRCLE, +// 3DS_CTRL_SQUARE, +// 3DS_CTRL_TRIANGLE, +// (3DSCtrlButtons)0, +// (3DSCtrlButtons)0, +// 3DS_CTRL_LTRIGGER, +// 3DS_CTRL_RTRIGGER, +// (3DSCtrlButtons)0, +// (3DSCtrlButtons)0, +// 3DS_CTRL_SELECT, +// 3DS_CTRL_START, +// 3DS_CTRL_UP, +// 3DS_CTRL_DOWN, +// 3DS_CTRL_LEFT, +// 3DS_CTRL_RIGHT +// }; +/* +void OS_WIIU::process_keys() { + // sceCtrlReadBufferPositive(&pad, 1); + + last++; + + for(int i = 0; i < 16; i++) { + if (pad.Buttons & buttons[i]) { + last = input->joy_button(last, 0, i, true); + } else { + last = input->joy_button(last, 0, i, false); + } + } + + InputDefault::JoyAxis ly, lx; + + lx.value = (pad.Lx - 128); + ly.value = (pad.Ly - 128); + + // printf("%d %d\n", lx.value, pad.Lx); + // printf("%d\n", ly.value); + + input->joy_axis(0, 0, 0, lx); + input->joy_axis(0, 0, 1, ly); + + // if(pad.Buttons & 3DS_CTRL_HOME) + // sceKernelExitGame(); +}*/ + +void OS_WIIU::delete_main_loop() { + + if (main_loop) + memdelete(main_loop); + main_loop = NULL; +} + +void OS_WIIU::set_main_loop(MainLoop *p_main_loop) { + + main_loop = p_main_loop; + input->set_main_loop(p_main_loop); +} + +bool OS_WIIU::can_draw() const { + + return true; //can draw +}; + +String OS_WIIU::get_name() { + + return "Nintendo WiiU"; +} + +void OS_WIIU::move_window_to_foreground() { +} + +void OS_WIIU::set_cursor_shape(CursorShape p_shape) { +} + +void OS_WIIU::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +} + +void OS_WIIU::run() { + + force_quit = false; + + if (!main_loop) + return; + + main_loop->init(); + + while (WHBProcIsRunning()) { + + // process_keys(); +// visual_server->draw(); + + if (Main::iteration() == true) + break; + + }; + + main_loop->finish(); +} + +void OS_WIIU::swap_buffers() { + // if(mesa) { + SDL_LockSurface(screen); + + // glReadPixels(0, 0, 1920, 1080, GL_RGBA, GL_UNSIGNED_BYTE, screen->pixels); + + std::transform((RGBA *)frameBuffer, + (RGBA *)frameBuffer + (1920 * 1080), + (RGBA *)screen->pixels, + [](RGBA v) { return RGBA{ v.r * 255, v.g * 255, v.b * 255,v.a * 255}; }); + // memcpy(screen->pixels, frameBuffer, (1920 * 1080)); + if (SDL_MUSTLOCK(screen)) { + SDL_UnlockSurface(screen); + } + SDL_LockSurface(screen); + SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, screen); + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); + SDL_DestroyTexture(texture); + // } +} + +OS_WIIU::OS_WIIU() { + // osSetSpeedupEnable(true); + AudioDriverManagerSW::add_driver(&driver_dummy); + //adriver here + // _render_thread_mode=RENDER_THREAD_UNSAFE;; + grab = false; + + // set_low_processor_usage_mode(true); +}; diff --git a/platform/wiiu/os_wiiu.h b/platform/wiiu/os_wiiu.h new file mode 100644 index 00000000..fee5d2ff --- /dev/null +++ b/platform/wiiu/os_wiiu.h @@ -0,0 +1,169 @@ +/*************************************************************************/ +/* os_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef OS_WIIU_H +#define OS_WIIU_H + + + +#include "servers/audio/audio_driver_dummy.h" +#include "os/input.h" +#include "drivers/unix/os_unix.h" +#include "servers/audio/audio_server_sw.h" +// #include "servers/physics_2d/physics_2d_server_wrap_mt.h" +#include "rasterizer_wiiu.h" +#include "servers/audio/sample_manager_sw.h" +#include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_server.h" +#include "servers/spatial_sound/spatial_sound_server_sw.h" +#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" +#include "servers/visual/rasterizer.h" +#include "servers/visual_server.h" +#include +#include + +#include +#include +#include + +class OS_WIIU : public OS { + + Rasterizer *rasterizer; + VisualServer *visual_server; + VideoMode current_videomode; + List args; + MainLoop *main_loop; + + SDL_Window* window; + SDL_Surface* screen; + SDL_Renderer* renderer; + void* frameBuffer; + template + struct RGBA { + T r; + T g; + T b; + T a; + }; + OSMesaContext ctx; + bool grab; + bool mesa = false; + uint64_t ticks_start; + + PhysicsServer *physics_server; + Physics2DServer *physics_2d_server; + + virtual void delete_main_loop(); +// IP_Unix *ip_unix; + + AudioServerSW *audio_server; + SampleManagerMallocSW *sample_manager; + SpatialSoundServerSW *spatial_sound_server; + SpatialSound2DServerSW *spatial_sound_2d_server; + + AudioDriverDummy driver_dummy; + + bool force_quit; + +// JoyPadPSP *joy; + // SceCtrlData pad; + int last; + + InputDefault *input; + +protected: + virtual int get_video_driver_count() const; + virtual const char *get_video_driver_name(int p_driver) const; + virtual VideoMode get_default_video_mode() const; + + virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual void finalize(); + + virtual void finalize_core(); + virtual void initialize_core(); + + virtual void set_main_loop(MainLoop *p_main_loop); + + virtual void init_keys(); + // virtual void process_keys(); + +public: + virtual String get_name(); +// virtual void print(const char *p_format, ...); +// virtual void vprint(const char* p_format, va_list p_list, bool p_stderr=false); + virtual void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); + + virtual void set_mouse_show(bool p_show); + virtual void set_mouse_grab(bool p_grab); + virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false); + virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); + virtual String get_stdin_string(bool p_block = true); + virtual Error execute(const String& p_path, const List& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL); + virtual Error kill(const ProcessID &p_pid); + virtual bool has_environment(const String &p_var) const; + virtual String get_environment(const String &p_var) const; + virtual Date get_date() const; + virtual Time get_time() const; + + virtual void delay_usec(uint32_t p_usec) const; + virtual uint64_t get_ticks_usec() const; + virtual bool is_mouse_grab_enabled() const; + virtual Point2 get_mouse_pos() const; + virtual int get_mouse_button_state() const; + virtual void set_window_title(const String &p_title); + virtual int get_audio_driver_count() const; + virtual const char *get_audio_driver_name(int p_driver) const; + virtual void swap_buffers(); + + virtual MainLoop *get_main_loop() const; + + virtual bool can_draw() const; + + virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0); + virtual VideoMode get_video_mode(int p_screen = 0) const; + virtual void get_fullscreen_mode_list(List *p_list, int p_screen = 0) const; + + virtual Size2 get_window_size() const; + + virtual void move_window_to_foreground(); + + void run(); + + OS_WIIU(); + ~OS_WIIU() { + OSMesaDestroyContext( ctx ); + free(frameBuffer); + SDL_DestroyWindow(window); + SDL_DestroyRenderer(renderer); + } +}; + +#endif diff --git a/platform/wiiu/platform_config.h b/platform/wiiu/platform_config.h new file mode 100644 index 00000000..e2200376 --- /dev/null +++ b/platform/wiiu/platform_config.h @@ -0,0 +1,31 @@ +/*************************************************************************/ +/* platform_config.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include diff --git a/platform/wiiu/thread_wiiu.cpp b/platform/wiiu/thread_wiiu.cpp new file mode 100644 index 00000000..03c47901 --- /dev/null +++ b/platform/wiiu/thread_wiiu.cpp @@ -0,0 +1,137 @@ +/*************************************************************************/ +/* thread_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "thread_wiiu.h" +#include "script_language.h" + +#if !defined(__WIIU__) + +#include + +#include "os/memory.h" + +Thread::ID ThreadWiiu::get_ID() const { + + return id; +} + +Thread *ThreadWiiu::create_thread_posix() { + + return memnew(ThreadWiiu); +} + +void *ThreadWiiu::thread_callback(void *userdata) { + + ThreadWiiu *t = reinterpret_cast(userdata); + t->id = (ID)pthread_self(); + + ScriptServer::thread_enter(); //scripts may need to attach a stack + + t->callback(t->user); + + ScriptServer::thread_exit(); + + return NULL; +} + +Thread *ThreadWiiu::create_func_posix(ThreadCreateCallback p_callback, void *p_user, const Settings &) { + + ThreadWiiu *tr = memnew(ThreadWiiu); + tr->callback = p_callback; + tr->user = p_user; + pthread_attr_init(&tr->pthread_attr); + pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setstacksize(&tr->pthread_attr, 256 * 1024); + + pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr); + + return tr; +} +Thread::ID ThreadWiiu::get_thread_ID_func_posix() { + + return (ID)pthread_self(); +} +void ThreadWiiu::wait_to_finish_func_posix(Thread *p_thread) { + + ThreadWiiu *tp = static_cast(p_thread); + ERR_FAIL_COND(!tp); + ERR_FAIL_COND(tp->pthread == 0); + + pthread_join(tp->pthread, NULL); + tp->pthread = 0; +} + +Error ThreadWiiu::set_name_func_posix(const String &p_name) { + + pthread_t running_thread = pthread_self(); + +#ifdef PTHREAD_NO_RENAME + return ERR_UNAVAILABLE; + +#else + +#ifdef PTHREAD_RENAME_SELF + + // check if thread is the same as caller + int err = pthread_setname_np(p_name.utf8().get_data()); + +#else + +#ifdef PTHREAD_BSD_SET_NAME + pthread_set_name_np(running_thread, p_name.utf8().get_data()); + int err = 0; // Open/FreeBSD ignore errors in this function +#else + int err = pthread_setname_np(running_thread, p_name.utf8().get_data()); +#endif // PTHREAD_BSD_SET_NAME + +#endif // PTHREAD_RENAME_SELF + + return err == 0 ? OK : ERR_INVALID_PARAMETER; + +#endif // PTHREAD_NO_RENAME +}; + +void ThreadWiiu::make_default() { + + create_func = create_func_posix; + get_thread_ID_func = get_thread_ID_func_posix; + wait_to_finish_func = wait_to_finish_func_posix; + set_name_func = set_name_func_posix; +} + +ThreadWiiu::ThreadWiiu() { + + pthread = 0; +} + +ThreadWiiu::~ThreadWiiu() { +} + +#endif diff --git a/platform/wiiu/thread_wiiu.h b/platform/wiiu/thread_wiiu.h new file mode 100644 index 00000000..09899fb0 --- /dev/null +++ b/platform/wiiu/thread_wiiu.h @@ -0,0 +1,74 @@ +/*************************************************************************/ +/* thread_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef THREAD_POSIX_H +#define THREAD_WIIU_H + +/** + @author Juan Linietsky +*/ + +#if !defined(__WIIU__) + +#include "os/thread.h" +#include +#include + +class ThreadWiiu : public Thread { + + pthread_t pthread; + pthread_attr_t pthread_attr; + ThreadCreateCallback callback; + void *user; + ID id; + + static Thread *create_thread_posix(); + + static void *thread_callback(void *userdata); + + static Thread *create_func_posix(ThreadCreateCallback p_callback, void *, const Settings &); + static ID get_thread_ID_func_posix(); + static void wait_to_finish_func_posix(Thread *p_thread); + + static Error set_name_func_posix(const String &p_name); + + ThreadWiiu(); + +public: + virtual ID get_ID() const; + + static void make_default(); + + ~ThreadWiiu(); +}; + +#endif + +#endif diff --git a/platform/x11/detect.py b/platform/x11/detect.py index fd656364..281771c1 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -54,7 +54,7 @@ def get_flags(): return [ ('builtin_zlib', 'no'), ("builtin_openssl", "yes"), - ("theora","no"), + ("theora","yes"), ] diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 3d7dcba0..4e44fef3 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -154,11 +154,11 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi context_gl = memnew( ContextGL_X11( x11_display, x11_window,current_videomode, false ) ); context_gl->initialize(); - if (p_video_driver == 0) { - rasterizer = memnew( RasterizerGLES2 ); - } else { + // if (p_video_driver == 0) { rasterizer = memnew( RasterizerGLES1 ); - }; + // } else { + // rasterizer = memnew( RasterizerGLES2 ); + // }; #endif visual_server = memnew( VisualServerRaster(rasterizer) ); diff --git a/scene/animation/tween_interpolaters.cpp b/scene/animation/tween_interpolaters.cpp index 7d0f2cd4..01fe88db 100644 --- a/scene/animation/tween_interpolaters.cpp +++ b/scene/animation/tween_interpolaters.cpp @@ -142,6 +142,10 @@ namespace quart { /////////////////////////////////////////////////////////////////////////// // quad /////////////////////////////////////////////////////////////////////////// +#ifdef JAVASCRIPT_ENABLED +#undef quad +#endif + namespace quad { static real_t in(real_t t, real_t b, real_t c, real_t d) { diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp index 73025fb5..4752c5ff 100644 --- a/scene/audio/stream_player.cpp +++ b/scene/audio/stream_player.cpp @@ -74,7 +74,7 @@ Ref StreamPlayer::get_stream() const { void StreamPlayer::play() { - + ERR_FAIL_COND(!is_inside_tree()); if (stream.is_null()) return; @@ -82,6 +82,7 @@ void StreamPlayer::play() { stop(); stream->play(); + AudioServer::get_singleton()->stream_set_active(stream_rid,true); AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); // if (stream->get_update_mode()!=AudioStream::UPDATE_NONE) diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 68c99003..1aa15045 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -272,7 +272,7 @@ void LineEdit::_input_event(InputEvent p_event) { if (editable) { selection_delete(); - CharType ucodestr[2]={k.unicode,0}; + CharType ucodestr[2]={(wchar_t)k.unicode,(wchar_t)0}; append_at_cursor(ucodestr); emit_signal("text_changed",text); _change_notify("text"); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ba68948e..11dad873 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1156,7 +1156,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } else { //different char, go back - const CharType chr[2] = {k.unicode, 0}; + const CharType chr[2] = {(wchar_t)k.unicode, (wchar_t)0}; if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); } else { @@ -1778,7 +1778,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (readonly) break; - const CharType chr[2] = {k.unicode, 0}; + const CharType chr[2] = {(wchar_t)k.unicode, (wchar_t)0}; if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index fded780f..e68de284 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -375,7 +375,7 @@ void FixedMaterial::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_point_size","size"),&FixedMaterial::set_point_size); ObjectTypeDB::bind_method(_MD("get_point_size"),&FixedMaterial::get_point_size); - + ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_reflection" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_REFLECTION); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_ALPHA); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_color_array" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_COLOR_ARRAY); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_point_size" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_POINT_SIZE); @@ -416,6 +416,7 @@ void FixedMaterial::_bind_methods() { BIND_CONSTANT( TEXCOORD_UV_TRANSFORM ); BIND_CONSTANT( TEXCOORD_UV2 ); + BIND_CONSTANT( FLAG_USE_REFLECTION ); BIND_CONSTANT( FLAG_USE_ALPHA ); BIND_CONSTANT( FLAG_USE_COLOR_ARRAY ); BIND_CONSTANT( FLAG_USE_POINT_SIZE ); @@ -439,6 +440,7 @@ FixedMaterial::FixedMaterial() : Material(VS::get_singleton()->fixed_material_cr set_flag(FLAG_COLOR_ARRAY_SRGB,true); + fixed_flags[FLAG_USE_REFLECTION]=false; fixed_flags[FLAG_USE_ALPHA]=false; fixed_flags[FLAG_USE_COLOR_ARRAY]=false; fixed_flags[FLAG_USE_POINT_SIZE]=false; diff --git a/scene/resources/material.h b/scene/resources/material.h index e5c56d99..aab8b959 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -140,6 +140,7 @@ class FixedMaterial : public Material { }; enum FixedFlag { + FLAG_USE_REFLECTION=VS::FIXED_MATERIAL_FLAG_USE_REFLECTION, FLAG_USE_ALPHA=VS::FIXED_MATERIAL_FLAG_USE_ALPHA, FLAG_USE_COLOR_ARRAY=VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, FLAG_USE_POINT_SIZE=VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE, diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 9ab1a804..9866f1df 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -6478,7 +6478,19 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ } /* Camera should always be BEFORE any other 3D */ +#ifdef __3DS__ + if (!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario)) { + + Camera *camera = camera_owner.get( p_viewport->camera ); + Scenario *scenario = scenario_owner.get( p_viewport->scenario ); + + _update_instances(); // check dirty instances before rendering + _render_camera(p_viewport, camera,scenario ); + + } + rasterizer->clear_viewport(clear_color); +#else if (!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario)) { Camera *camera = camera_owner.get( p_viewport->camera ); @@ -6493,7 +6505,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ //clear the viewport black because of no camera? i seriously should.. rasterizer->clear_viewport(clear_color); } - +#endif if (!p_viewport->hide_canvas) { int i=0; diff --git a/servers/visual_server.h b/servers/visual_server.h index 87b139ba..aca7db4d 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -231,7 +231,7 @@ class VisualServer : public Object { }; enum FixedMaterialFlags { - + FIXED_MATERIAL_FLAG_USE_REFLECTION, FIXED_MATERIAL_FLAG_USE_ALPHA, FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, FIXED_MATERIAL_FLAG_USE_POINT_SIZE, diff --git a/tools/docdump/doc_dump.cpp b/tools/docdump/doc_dump.cpp index 9fece389..f10ba7f0 100644 --- a/tools/docdump/doc_dump.cpp +++ b/tools/docdump/doc_dump.cpp @@ -67,7 +67,7 @@ static String _escape_string(const String& p_str) { ret=ret.replace("\"","""); for (int i=1;i<32;i++) { - char chr[2]={i,0}; + char chr[2]={(char)i,(char)0}; ret=ret.replace(chr,"&#"+String::num(i)+";"); } ret=ret.utf8(); diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index b855b15b..5de647bf 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -766,10 +766,18 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref te; + te = ResourceLoader::load(path); + ERR_FAIL_COND_V(te.is_null(), ERR_CANT_OPEN); + src = te->get_data(); + + } else { + Error err = ImageLoader::load_image(path,&src); + if (err) { + EditorNode::add_io_error("Couldn't load image: "+path); + return err; + } } if (src.detect_alpha()) @@ -799,7 +807,9 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref1) { - + int orig_w=image.get_width(); int orig_h=image.get_height(); image.resize(orig_w/shrink,orig_h/shrink); @@ -1038,7 +1048,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref1 || (format!=IMAGE_FORMAT_UNCOMPRESSED && (image.get_width()!=orig_w || image.get_height()!=orig_h))) { - texture->set_size_override(Size2(orig_w,orig_h)); + // texture->set_size_override(Size2(orig_w,orig_h)); } uint32_t save_flags=ResourceSaver::FLAG_COMPRESS; diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp index 9589ad67..ffa2f00b 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.cpp +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -120,7 +120,7 @@ void BakedLightEditor::_notification(int p_option) { Image img(baker->baked_octree_texture_w,baker->baked_octree_texture_h,0,Image::FORMAT_RGBA,light_texture); Ref it = memnew( ImageTexture ); it->create_from_image(img); - ResourceSaver::save("baked_octree.png",it); + ResourceSaver::save("res://baked_octree.png",it); #endif diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index 79513225..fb6f43ca 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -696,7 +696,7 @@ void ProjectExportDialog::_update_group_tree() { extensions.insert(E->get()); } - + extensions.insert("tex"); List grouplist; EditorImportExport::get_singleton()->image_export_get_groups(&grouplist); grouplist.sort_custom();