summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp1
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp9
-rw-r--r--drivers/gles3/rasterizer_gles3.h3
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp808
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h178
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp720
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h200
-rw-r--r--drivers/gles3/shader_gles3.cpp12
-rw-r--r--drivers/gles3/shaders/SCsub1
-rw-r--r--drivers/gles3/shaders/scene.glsl351
10 files changed, 2258 insertions, 25 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index b2228a6cfa..237b3ec3fc 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -117,6 +117,7 @@ void RasterizerCanvasGLES3::canvas_begin(){
glClearColor( storage->frame.clear_request_color.r, storage->frame.clear_request_color.g, storage->frame.clear_request_color.b, storage->frame.clear_request_color.a );
glClear(GL_COLOR_BUFFER_BIT);
storage->frame.clear_request=false;
+ print_line("canvas clear?");
}
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index eaa9825605..83c40edc1d 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -15,7 +15,7 @@ RasterizerCanvas *RasterizerGLES3::get_canvas() {
RasterizerScene *RasterizerGLES3::get_scene() {
- return NULL;
+ return scene;
}
@@ -111,6 +111,7 @@ void RasterizerGLES3::initialize() {
*/
storage->initialize();
canvas->initialize();
+ scene->initialize();
}
void RasterizerGLES3::begin_frame(){
@@ -124,6 +125,7 @@ void RasterizerGLES3::begin_frame(){
storage->update_dirty_shaders();
storage->update_dirty_materials();
+
}
void RasterizerGLES3::set_current_render_target(RID p_render_target){
@@ -131,6 +133,7 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target){
if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
//handle pending clear request, if the framebuffer was not cleared
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
+ print_line("unbind clear of: "+storage->frame.clear_request_color);
glClearColor(
storage->frame.clear_request_color.r,
storage->frame.clear_request_color.g,
@@ -265,8 +268,12 @@ RasterizerGLES3::RasterizerGLES3()
storage = memnew( RasterizerStorageGLES3 );
canvas = memnew( RasterizerCanvasGLES3 );
+ scene = memnew( RasterizerSceneGLES3 );
canvas->storage=storage;
storage->canvas=canvas;
+ scene->storage=storage;
+ storage->scene=scene;
+
}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index d461664ea2..f70dac506d 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -4,6 +4,7 @@
#include "servers/visual/rasterizer.h"
#include "rasterizer_storage_gles3.h"
#include "rasterizer_canvas_gles3.h"
+#include "rasterizer_scene_gles3.h"
class RasterizerGLES3 : public Rasterizer {
@@ -12,6 +13,8 @@ class RasterizerGLES3 : public Rasterizer {
RasterizerStorageGLES3 *storage;
RasterizerCanvasGLES3 *canvas;
+ RasterizerSceneGLES3 *scene;
+
public:
virtual RasterizerStorage *get_storage();
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
new file mode 100644
index 0000000000..121620594d
--- /dev/null
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -0,0 +1,808 @@
+#include "rasterizer_scene_gles3.h"
+#include "globals.h"
+static _FORCE_INLINE_ void store_matrix32(const Matrix32& p_mtx, float* p_array) {
+
+ p_array[ 0]=p_mtx.elements[0][0];
+ p_array[ 1]=p_mtx.elements[0][1];
+ p_array[ 2]=0;
+ p_array[ 3]=0;
+ p_array[ 4]=p_mtx.elements[1][0];
+ p_array[ 5]=p_mtx.elements[1][1];
+ p_array[ 6]=0;
+ p_array[ 7]=0;
+ p_array[ 8]=0;
+ p_array[ 9]=0;
+ p_array[10]=1;
+ p_array[11]=0;
+ p_array[12]=p_mtx.elements[2][0];
+ p_array[13]=p_mtx.elements[2][1];
+ p_array[14]=0;
+ p_array[15]=1;
+}
+
+
+static _FORCE_INLINE_ void store_transform(const Transform& p_mtx, float* p_array) {
+ p_array[ 0]=p_mtx.basis.elements[0][0];
+ p_array[ 1]=p_mtx.basis.elements[1][0];
+ p_array[ 2]=p_mtx.basis.elements[2][0];
+ p_array[ 3]=0;
+ p_array[ 4]=p_mtx.basis.elements[0][1];
+ p_array[ 5]=p_mtx.basis.elements[1][1];
+ p_array[ 6]=p_mtx.basis.elements[2][1];
+ p_array[ 7]=0;
+ p_array[ 8]=p_mtx.basis.elements[0][2];
+ p_array[ 9]=p_mtx.basis.elements[1][2];
+ p_array[10]=p_mtx.basis.elements[2][2];
+ p_array[11]=0;
+ p_array[12]=p_mtx.origin.x;
+ p_array[13]=p_mtx.origin.y;
+ p_array[14]=p_mtx.origin.z;
+ p_array[15]=1;
+}
+
+static _FORCE_INLINE_ void store_camera(const CameraMatrix& p_mtx, float* p_array) {
+
+ for (int i=0;i<4;i++) {
+ for (int j=0;j<4;j++) {
+
+ p_array[i*4+j]=p_mtx.matrix[i][j];
+ }
+ }
+}
+
+
+
+RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
+
+
+ return RID();
+}
+
+void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,const Transform& p_transform){
+
+
+}
+
+
+bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass) {
+
+ if (p_material->shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_DISABLED) {
+ glDisable(GL_CULL_FACE);
+ } else {
+ glEnable(GL_CULL_FACE);
+ }
+
+ //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+
+ /*
+ 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)
+ // glLineWidth(p_material->line_width);
+
+
+ //blend mode
+ if (state.current_blend_mode!=p_material->shader->spatial.blend_mode) {
+
+ switch(p_material->shader->spatial.blend_mode) {
+
+ case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_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 RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: {
+
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE);
+
+ } break;
+ case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: {
+
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ } break;
+ case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_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;
+ }
+
+ state.current_blend_mode=p_material->shader->spatial.blend_mode;
+
+ }
+
+ //material parameters
+
+ state.scene_shader.set_custom_shader(p_material->shader->custom_code_id);
+ bool rebind = state.scene_shader.bind();
+
+
+ if (p_material->ubo_id) {
+ glBindBufferBase(GL_UNIFORM_BUFFER,1,p_material->ubo_id);
+ }
+
+
+
+ int tc = p_material->textures.size();
+ RID* textures = p_material->textures.ptr();
+
+ for(int i=0;i<tc;i++) {
+
+ glActiveTexture(GL_TEXTURE0+i);
+
+ RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull( textures[i] );
+ if (!t) {
+ //check hints
+ glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex);
+ continue;
+ }
+
+ glBindTexture(t->target,t->tex_id);
+ }
+
+
+ return rebind;
+
+}
+
+
+void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) {
+
+ switch(e->instance->base_type) {
+
+ case VS::INSTANCE_MESH: {
+
+ RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface*>(e->geometry);
+ glBindVertexArray(s->array_id); // everything is so easy nowadays
+ } break;
+ }
+
+}
+
+static const GLenum gl_primitive[]={
+ GL_POINTS,
+ GL_LINES,
+ GL_LINE_STRIP,
+ GL_LINE_LOOP,
+ GL_TRIANGLES,
+ GL_TRIANGLE_STRIP,
+ GL_TRIANGLE_FAN
+};
+
+
+
+void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
+
+ switch(e->instance->base_type) {
+
+ case VS::INSTANCE_MESH: {
+
+ RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface*>(e->geometry);
+
+ if (s->index_array_len>0) {
+
+ glDrawElements(gl_primitive[s->primitive],s->index_array_len, (s->array_len>=(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0);
+
+ } else {
+
+ glDrawArrays(gl_primitive[s->primitive],0,s->array_len);
+
+ }
+
+ } break;
+ }
+
+}
+
+void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,bool p_reverse_cull,bool p_alpha_pass) {
+
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) {
+ //p_reverse_cull=!p_reverse_cull;
+ glFrontFace(GL_CCW);
+ } else {
+ glFrontFace(GL_CW);
+ }
+
+ glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo
+
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false);
+
+ state.current_blend_mode=-1;
+
+ glDisable(GL_BLEND);
+
+ RasterizerStorageGLES3::Material* prev_material=NULL;
+ RasterizerStorageGLES3::Geometry* prev_geometry=NULL;
+ VS::InstanceType prev_base_type = VS::INSTANCE_MAX;
+
+ for (int i=0;i<p_element_count;i++) {
+
+ RenderList::Element *e = p_elements[i];
+ RasterizerStorageGLES3::Material* material= e->material;
+
+ bool rebind=i==0;
+
+ if (material!=prev_material || rebind) {
+
+ rebind = _setup_material(material,p_alpha_pass);
+// _rinfo.mat_change_count++;
+ }
+
+
+ if (prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) {
+
+ _setup_geometry(e);
+ }
+
+// _set_cull(e->mirror,p_reverse_cull);
+
+ state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror?-1.0:1.0);
+ state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform);
+
+
+// _render(e->geometry, material, skeleton,e->owner,e->instance->transform);
+
+ _render_geometry(e);
+
+ prev_material=material;
+ prev_base_type=e->instance->base_type;
+ prev_geometry=e->geometry;
+ }
+
+ //print_line("shaderchanges: "+itos(p_alpha_pass)+": "+itos(_rinfo.shader_change_count));
+
+
+ glFrontFace(GL_CW);
+ glBindVertexArray(0);
+
+}
+
+void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material) {
+
+ RasterizerStorageGLES3::Material *m=NULL;
+ RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override :(p_material>=0?p_instance->materials[p_material]:p_geometry->material);
+
+/*
+#ifdef DEBUG_ENABLED
+ if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) {
+ m_src=overdraw_material;
+ }
+
+#endif
+*/
+ if (m_src.is_valid()) {
+ m=storage->material_owner.getornull( m_src );
+ if (!m->shader) {
+ m=NULL;
+ }
+ }
+
+ if (!m) {
+ m=storage->material_owner.getptr( default_material );
+ }
+
+ ERR_FAIL_COND(!m);
+
+
+
+ //bool has_base_alpha=(m->shader_cache && m->shader_cache->has_alpha);
+ //bool has_blend_alpha=m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || m->flags[VS::MATERIAL_FLAG_ONTOP];
+ bool has_alpha = false; //has_base_alpha || has_blend_alpha;
+
+#if 0
+ if (shadow) {
+
+ if (has_blend_alpha || (has_base_alpha && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA))
+ return; //bye
+
+ if (!m->shader_cache || (!m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) {
+ //shader does not use discard and does not write a vertex position, use generic material
+ if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)
+ m = shadow_mat_double_sided_ptr;
+ else
+ m = shadow_mat_ptr;
+ if (m->last_pass!=frame) {
+
+ if (m->shader.is_valid()) {
+
+ m->shader_cache=shader_owner.get(m->shader);
+ if (m->shader_cache) {
+
+
+ if (!m->shader_cache->valid)
+ m->shader_cache=NULL;
+ } else {
+ m->shader=RID();
+ }
+
+ } else {
+ m->shader_cache=NULL;
+ }
+
+ m->last_pass=frame;
+ }
+ }
+
+ render_list = &opaque_render_list;
+ /* notyet
+ if (!m->shader_cache || m->shader_cache->can_zpass)
+ render_list = &alpha_render_list;
+ } else {
+ render_list = &opaque_render_list;
+ }*/
+
+ } else {
+ if (has_alpha) {
+ render_list = &alpha_render_list;
+ } else {
+ render_list = &opaque_render_list;
+
+ }
+ }
+#endif
+
+ RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
+
+ if (!e)
+ return;
+
+ e->geometry=p_geometry;
+ e->material=m;
+ e->instance=p_instance;
+ e->owner=p_owner;
+ e->additive=false;
+ e->additive_ptr=&e->additive;
+ e->sort_key=0;
+
+ if (e->geometry->last_pass!=render_pass) {
+ e->geometry->last_pass=render_pass;
+ e->geometry->index=current_geometry_index++;
+ }
+
+ e->sort_key|=uint64_t(e->instance->base_type)<<RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
+ e->sort_key|=uint64_t(e->instance->base_type)<<RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
+
+ if (e->material->last_pass!=render_pass) {
+ e->material->last_pass=render_pass;
+ e->material->index=current_material_index++;
+ }
+
+ e->sort_key|=uint64_t(e->material->index)<<RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
+
+ e->sort_key|=uint64_t(e->instance->depth_layer)<<RenderList::SORT_KEY_DEPTH_LAYER_SHIFT;
+
+ //if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE)
+ // e->sort_flags|=RenderList::SORT_FLAG_INSTANCING;
+
+ bool mirror = e->instance->mirror;
+
+// if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES])
+// e->mirror=!e->mirror;
+
+ if (mirror) {
+ e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG;
+ }
+
+ //e->light_type=0xFF; // no lights!
+ e->sort_key|=uint64_t(0xF)<<RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; //light type 0xF is no light?
+ e->sort_key|=uint64_t(0xFFFF)<<RenderList::SORT_KEY_LIGHT_INDEX_SHIFT;
+/* prepass
+ if (!shadow && !has_blend_alpha && has_alpha && m->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA) {
+
+ //if nothing exists, add this element as opaque too
+ RenderList::Element *oe = opaque_render_list.add_element();
+
+ if (!oe)
+ return;
+
+ memcpy(oe,e,sizeof(RenderList::Element));
+ oe->additive_ptr=&oe->additive;
+ }
+*/
+
+#if 0
+ if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED] || current_debug==VS::SCENARIO_DEBUG_SHADELESS) {
+
+ e->light_type=0x7F; //unshaded is zero
+ } else {
+
+ bool duplicate=false;
+
+
+ for(int i=0;i<directional_light_count;i++) {
+ uint16_t sort_key = directional_lights[i]->sort_key;
+ uint8_t light_type = VS::LIGHT_DIRECTIONAL;
+ if (directional_lights[i]->base->shadow_enabled) {
+ light_type|=0x8;
+ if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS)
+ light_type|=0x10;
+ else if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS)
+ light_type|=0x30;
+
+ }
+
+ RenderList::Element *ec;
+ if (duplicate) {
+
+ ec = render_list->add_element();
+ memcpy(ec,e,sizeof(RenderList::Element));
+ } else {
+
+ ec=e;
+ duplicate=true;
+ }
+
+ ec->light_type=light_type;
+ ec->light=sort_key;
+ ec->additive_ptr=&e->additive;
+
+ }
+
+
+ const RID *liptr = p_instance->light_instances.ptr();
+ int ilc=p_instance->light_instances.size();
+
+
+
+ for(int i=0;i<ilc;i++) {
+
+ LightInstance *li=light_instance_owner.get( liptr[i] );
+ if (!li || li->last_pass!=scene_pass) //lit by light not in visible scene
+ continue;
+ uint8_t light_type=li->base->type|0x40; //penalty to ensure directionals always go first
+ if (li->base->shadow_enabled) {
+ light_type|=0x8;
+ }
+ uint16_t sort_key =li->sort_key;
+
+ RenderList::Element *ec;
+ if (duplicate) {
+
+ ec = render_list->add_element();
+ memcpy(ec,e,sizeof(RenderList::Element));
+ } else {
+
+ duplicate=true;
+ ec=e;
+ }
+
+ ec->light_type=light_type;
+ ec->light=sort_key;
+ ec->additive_ptr=&e->additive;
+
+ }
+
+
+
+ }
+
+#endif
+}
+
+void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment){
+
+
+ //fill up ubo
+
+ store_camera(p_cam_projection,state.ubo_data.projection_matrix);
+ store_transform(p_cam_transform,state.ubo_data.camera_matrix);
+ store_transform(p_cam_transform.affine_inverse(),state.ubo_data.camera_inverse_matrix);
+ for(int i=0;i<4;i++) {
+ state.ubo_data.time[i]=storage->frame.time[i];
+ }
+
+
+ glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(State::SceneDataUBO), &state.ubo_data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+
+ render_list.clear();
+
+ render_pass++;
+ current_material_index=0;
+
+ //fill list
+
+ for(int i=0;i<p_cull_count;i++) {
+
+ InstanceBase *inst = p_cull_result[i];
+ switch(inst->base_type) {
+
+ case VS::INSTANCE_MESH: {
+
+ RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getptr(inst->base);
+ ERR_CONTINUE(!mesh);
+
+ int ssize = mesh->surfaces.size();
+
+ for (int i=0;i<ssize;i++) {
+
+ int mat_idx = inst->materials[i].is_valid() ? i : -1;
+ RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
+ _add_geometry(s,inst,NULL,mat_idx);
+ }
+
+ //mesh->last_pass=frame;
+
+ } break;
+ case VS::INSTANCE_MULTIMESH: {
+
+ } break;
+ case VS::INSTANCE_IMMEDIATE: {
+
+ } break;
+
+ }
+ }
+
+ //
+
+
+ glEnable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glClearDepth(1.0);
+ glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
+
+
+ if (true) {
+
+ if (storage->frame.clear_request) {
+
+ glClearColor( storage->frame.clear_request_color.r, storage->frame.clear_request_color.g, storage->frame.clear_request_color.b, storage->frame.clear_request_color.a );
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+ storage->frame.clear_request=false;
+
+ }
+ }
+
+ state.current_depth_test=true;
+ state.current_depth_mask=true;
+ state.texscreen_copied=false;
+
+ glBlendEquation(GL_FUNC_ADD);
+
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ glDisable(GL_BLEND);
+ //current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
+
+
+ render_list.sort_by_key(false);
+
+ //_render_list_forward(&opaque_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting);
+/*
+ if (draw_tex_background) {
+
+ //most 3D vendors recommend drawing a texture bg or skybox here,
+ //after opaque geometry has been drawn
+ //so the zbuffer can get rid of most pixels
+ _draw_tex_bg();
+ }
+*/
+ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+// glDisable(GL_BLEND);
+// current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
+// state.scene_shader.set_conditional(SceneShaderGLES3::USE_GLOW,false);
+// if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) {
+// glColorMask(1,1,1,0); //don't touch alpha
+// }
+
+
+ _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,false,false);
+
+ //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
+ //glColorMask(1,1,1,1);
+
+// state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false);
+
+ glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+#if 0
+ if (use_fb) {
+
+
+
+ for(int i=0;i<VS::ARRAY_MAX;i++) {
+ glDisableVertexAttribArray(i);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER,0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_SCISSOR_TEST);
+ glDepthMask(false);
+
+ if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR]) {
+
+ int hdr_tm = current_env->fx_param[VS::ENV_FX_PARAM_HDR_TONEMAPPER];
+ switch(hdr_tm) {
+ case VS::ENV_FX_HDR_TONE_MAPPER_LINEAR: {
+
+
+ } break;
+ case VS::ENV_FX_HDR_TONE_MAPPER_LOG: {
+ copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER,true);
+
+ } break;
+ case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT: {
+ copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,true);
+ } break;
+ case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE: {
+
+ copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,true);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE,true);
+ } break;
+ }
+
+
+ _process_hdr();
+ }
+ if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) {
+ _process_glow_bloom();
+ int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE];
+ if (glow_transfer_mode==1)
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true);
+ if (glow_transfer_mode==2)
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,true);
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
+
+ Size2 size;
+ if (current_rt) {
+ glBindFramebuffer(GL_FRAMEBUFFER, current_rt->fbo);
+ glViewport( 0,0,viewport.width,viewport.height);
+ size=Size2(viewport.width,viewport.height);
+ } else {
+ glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
+ glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height );
+ size=Size2(viewport.width,viewport.height);
+ }
+
+ //time to copy!!!
+ copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,current_env && current_env->fx_enabled[VS::ENV_FX_BCS]);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,true);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]);
+
+ copy_shader.bind();
+ //copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0);
+
+ if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) {
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, framebuffer.blur[0].color );
+ glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::GLOW_SOURCE),1);
+
+ }
+
+ if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR]) {
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, current_vd->lum_color );
+ glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::HDR_SOURCE),2);
+ copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_EXPOSURE,float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE]));
+ copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_WHITE,float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_WHITE]));
+
+ }
+
+ if (current_env && current_env->fx_enabled[VS::ENV_FX_FXAA])
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Size2(1.0/size.x,1.0/size.y));
+
+
+ if (current_env && current_env->fx_enabled[VS::ENV_FX_BCS]) {
+
+ Vector3 bcs;
+ bcs.x=current_env->fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS];
+ bcs.y=current_env->fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST];
+ bcs.z=current_env->fx_param[VS::ENV_FX_PARAM_BCS_SATURATION];
+ copy_shader.set_uniform(CopyShaderGLES2::BCS,bcs);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, framebuffer.color );
+ glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
+
+ _copy_screen_quad();
+
+ copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER,false);
+
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_8BIT_HDR,false);
+
+
+ if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR] && GLOBAL_DEF("rasterizer/debug_hdr",false)) {
+ _debug_luminances();
+ }
+ }
+
+ current_env=NULL;
+ current_debug=VS::SCENARIO_DEBUG_DISABLED;
+ if (GLOBAL_DEF("rasterizer/debug_shadow_maps",false)) {
+ _debug_shadows();
+ }
+// _debug_luminances();
+// _debug_samplers();
+
+ if (using_canvas_bg) {
+ using_canvas_bg=false;
+ glColorMask(1,1,1,1); //don't touch alpha
+ }
+#endif
+}
+
+bool RasterizerSceneGLES3::free(RID p_rid) {
+
+ return false;
+
+}
+
+void RasterizerSceneGLES3::initialize() {
+
+ state.scene_shader.init();
+
+ default_shader = storage->shader_create(VS::SHADER_SPATIAL);
+ default_material = storage->material_create();
+ storage->material_set_shader(default_material,default_shader);
+
+ glGenBuffers(1, &state.scene_ubo);
+ glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ render_list.max_elements=GLOBAL_DEF("rendering/gles3/max_renderable_elements",(int)RenderList::DEFAULT_MAX_ELEMENTS);
+ if (render_list.max_elements>1000000)
+ render_list.max_elements=1000000;
+ if (render_list.max_elements<1024)
+ render_list.max_elements=1024;
+
+ render_list.init();
+}
+
+void RasterizerSceneGLES3::finalize(){
+
+
+}
+
+
+RasterizerSceneGLES3::RasterizerSceneGLES3()
+{
+
+}
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
new file mode 100644
index 0000000000..6fba777fc8
--- /dev/null
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -0,0 +1,178 @@
+#ifndef RASTERIZERSCENEGLES3_H
+#define RASTERIZERSCENEGLES3_H
+
+#include "rasterizer_storage_gles3.h"
+#include "drivers/gles3/shaders/scene.glsl.h"
+
+class RasterizerSceneGLES3 : public RasterizerScene {
+public:
+
+ uint64_t render_pass;
+ uint32_t current_material_index;
+ uint32_t current_geometry_index;
+
+ RID default_material;
+ RID default_shader;
+
+ RasterizerStorageGLES3 *storage;
+
+
+
+ struct State {
+
+ bool current_depth_test;
+ bool current_depth_mask;
+ bool texscreen_copied;
+ int current_blend_mode;
+
+ SceneShaderGLES3 scene_shader;
+
+
+ struct SceneDataUBO {
+
+ float projection_matrix[16];
+ float camera_inverse_matrix[16];
+ float camera_matrix[16];
+ float time[4];
+ float ambient_light[4];
+
+ } ubo_data;
+
+ GLuint scene_ubo;
+
+
+
+ } state;
+
+ struct RenderList {
+
+ enum {
+ DEFAULT_MAX_ELEMENTS=65536,
+ MAX_LIGHTS=4,
+ SORT_FLAG_SKELETON=1,
+ SORT_FLAG_INSTANCING=2,
+
+ SORT_KEY_DEPTH_LAYER_SHIFT=58,
+ SORT_KEY_LIGHT_TYPE_SHIFT=54, //type is most important
+ SORT_KEY_LIGHT_INDEX_SHIFT=38, //type is most important
+ SORT_KEY_MATERIAL_INDEX_SHIFT=22,
+ SORT_KEY_GEOMETRY_INDEX_SHIFT=6,
+ SORT_KEY_GEOMETRY_TYPE_SHIFT=2,
+ SORT_KEY_SKELETON_FLAG=2,
+ SORT_KEY_MIRROR_FLAG=1
+
+ };
+
+ int max_elements;
+
+ struct Element {
+
+ RasterizerScene::InstanceBase *instance;
+ RasterizerStorageGLES3::Geometry *geometry;
+ RasterizerStorageGLES3::Material *material;
+ RasterizerStorageGLES3::GeometryOwner *owner;
+ uint64_t sort_key;
+ bool *additive_ptr;
+ bool additive;
+
+ };
+
+
+ Element *_elements;
+ Element **elements;
+
+ int element_count;
+ int alpha_element_count;
+
+ void clear() {
+
+ element_count=0;
+ alpha_element_count=0;
+ }
+
+ //should eventually be replaced by radix
+
+ struct SortByKey {
+
+ _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const {
+ return A->sort_key < B->sort_key;
+ }
+ };
+
+ void sort_by_key(bool p_alpha) {
+
+ SortArray<Element*,SortByKey> sorter;
+ if (p_alpha) {
+ sorter.sort(&elements[max_elements-alpha_element_count-1],alpha_element_count);
+ } else {
+ sorter.sort(elements,element_count);
+ }
+ }
+
+
+ _FORCE_INLINE_ Element* add_element() {
+
+ if (element_count+alpha_element_count>=max_elements)
+ return NULL;
+ elements[element_count]=&_elements[element_count];
+ return elements[element_count++];
+ }
+
+ _FORCE_INLINE_ Element* add_alpha_element() {
+
+ if (element_count+alpha_element_count>=max_elements)
+ return NULL;
+ int idx = max_elements-alpha_element_count-1;
+ elements[idx]=&_elements[idx];
+ alpha_element_count++;
+ return elements[idx];
+ }
+
+ void init() {
+
+ element_count = 0;
+ alpha_element_count =0;
+ elements=memnew_arr(Element*,max_elements);
+ _elements=memnew_arr(Element,max_elements);
+ for (int i=0;i<max_elements;i++)
+ elements[i]=&_elements[i]; // assign elements
+
+ }
+
+ RenderList() {
+
+ max_elements=DEFAULT_MAX_ELEMENTS;
+ }
+
+ ~RenderList() {
+ memdelete_arr(elements);
+ memdelete_arr(_elements);
+ }
+ };
+
+
+
+ RenderList render_list;
+
+ _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass);
+ _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e);
+ _FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
+
+
+ void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, bool p_reverse_cull, bool p_alpha_pass);
+
+ virtual RID light_instance_create(RID p_light);
+ virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform);
+
+ _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material);
+
+ virtual void render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment);
+
+ virtual bool free(RID p_rid);
+
+ void initialize();
+ void finalize();
+ RasterizerSceneGLES3();
+};
+
+#endif // RASTERIZERSCENEGLES3_H
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 74b7d72652..f633ef21cc 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1,5 +1,6 @@
#include "rasterizer_storage_gles3.h"
#include "rasterizer_canvas_gles3.h"
+#include "rasterizer_scene_gles3.h"
#include "globals.h"
/* TEXTURE API */
@@ -1039,7 +1040,7 @@ void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode)
ShaderGLES3* shaders[VS::SHADER_MAX]={
&canvas->state.canvas_shader,
- &canvas->state.canvas_shader,
+ &scene->state.scene_shader,
&canvas->state.canvas_shader,
};
@@ -1108,6 +1109,37 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
actions->uniforms=&p_shader->uniforms;
} break;
+
+ case VS::SHADER_SPATIAL: {
+
+ p_shader->spatial.blend_mode=Shader::Spatial::BLEND_MODE_MIX;
+ p_shader->spatial.depth_draw_mode=Shader::Spatial::DEPTH_DRAW_OPAQUE;
+ p_shader->spatial.cull_mode=Shader::Spatial::CULL_MODE_BACK;
+ p_shader->spatial.uses_alpha=false;
+ p_shader->spatial.unshaded=false;
+ p_shader->spatial.ontop=false;
+
+ shaders.actions_scene.render_mode_values["blend_add"]=Pair<int*,int>(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_ADD);
+ shaders.actions_scene.render_mode_values["blend_mix"]=Pair<int*,int>(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_MIX);
+ shaders.actions_scene.render_mode_values["blend_sub"]=Pair<int*,int>(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_SUB);
+ shaders.actions_scene.render_mode_values["blend_mul"]=Pair<int*,int>(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_MUL);
+
+ shaders.actions_scene.render_mode_values["depth_draw_opaque"]=Pair<int*,int>(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_OPAQUE);
+ shaders.actions_scene.render_mode_values["depth_draw_always"]=Pair<int*,int>(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_ALWAYS);
+ shaders.actions_scene.render_mode_values["depth_draw_never"]=Pair<int*,int>(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_NEVER);
+ shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"]=Pair<int*,int>(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
+
+ shaders.actions_scene.render_mode_values["cull_front"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_FRONT);
+ shaders.actions_scene.render_mode_values["cull_back"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_BACK);
+ shaders.actions_scene.render_mode_values["cull_disable"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED);
+
+ shaders.actions_canvas.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded;
+ shaders.actions_canvas.render_mode_flags["ontop"]=&p_shader->spatial.ontop;
+
+ shaders.actions_canvas.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha;
+
+ }
+
}
@@ -1905,97 +1937,685 @@ void RasterizerStorageGLES3::update_dirty_materials() {
RID RasterizerStorageGLES3::mesh_create(){
- return RID();
+ Mesh * mesh = memnew( Mesh );
+
+ return mesh_owner.make_rid(mesh);
}
-void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const Vector<DVector<uint8_t> >& p_blend_shapes){
+void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes,const Vector<AABB>& p_bone_aabbs){
+
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ ERR_FAIL_COND(!(p_format&VS::ARRAY_FORMAT_VERTEX));
+
+ //must have index and bones, both.
+ {
+ uint32_t bones_weight = VS::ARRAY_FORMAT_BONES|VS::ARRAY_FORMAT_WEIGHTS;
+ ERR_EXPLAIN("Array must have both bones and weights in format or none.");
+ ERR_FAIL_COND( (p_format&bones_weight) && (p_format&bones_weight)!=bones_weight );
+ }
+
+
+ bool has_morph = p_blend_shapes.size();
+
+ Surface::Attrib attribs[VS::ARRAY_MAX],morph_attribs[VS::ARRAY_MAX];
+
+ int stride=0;
+ int morph_stride=0;
+
+ for(int i=0;i<VS::ARRAY_MAX;i++) {
+
+ if (! (p_format&(1<<i) ) ) {
+ attribs[i].enabled=false;
+ morph_attribs[i].enabled=false;
+ continue;
+ }
+
+ attribs[i].enabled=true;
+ attribs[i].offset=stride;
+ attribs[i].index=i;
+
+ if (has_morph) {
+ morph_attribs[i].enabled=true;
+ morph_attribs[i].offset=morph_stride;
+ morph_attribs[i].index=i+8;
+ } else {
+ morph_attribs[i].enabled=false;
+ }
+
+ switch(i) {
+
+ case VS::ARRAY_VERTEX: {
+
+ if (p_format&VS::ARRAY_FLAG_USE_2D_VERTICES) {
+ attribs[i].size=2;
+ } else {
+ attribs[i].size=3;
+ }
+
+ if (p_format&VS::ARRAY_COMPRESS_VERTEX) {
+ attribs[i].type=GL_HALF_FLOAT;
+ stride+=attribs[i].size*2;
+ } else {
+ attribs[i].type=GL_FLOAT;
+ stride+=attribs[i].size*4;
+ }
+
+ attribs[i].normalized=GL_FALSE;
+
+ if (has_morph) {
+ //morph
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_FLOAT;
+ morph_stride+=attribs[i].size*4;
+ }
+ } break;
+ case VS::ARRAY_NORMAL: {
+
+ attribs[i].size=3;
+
+ if (p_format&VS::ARRAY_COMPRESS_NORMAL) {
+ attribs[i].type=GL_BYTE;
+ stride+=4; //pad extra byte
+ attribs[i].normalized=GL_TRUE;
+ } else {
+ attribs[i].type=GL_FLOAT;
+ stride+=12;
+ attribs[i].normalized=GL_FALSE;
+ }
+
+ if (has_morph) {
+ //morph
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_FLOAT;
+ morph_stride+=12;
+ }
+
+ } break;
+ case VS::ARRAY_TANGENT: {
+
+ attribs[i].size=4;
+
+ if (p_format&VS::ARRAY_COMPRESS_TANGENT) {
+ attribs[i].type=GL_BYTE;
+ stride+=4;
+ attribs[i].normalized=GL_TRUE;
+ } else {
+ attribs[i].type=GL_FLOAT;
+ stride+=16;
+ attribs[i].normalized=GL_FALSE;
+ }
+
+ if (has_morph) {
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_FLOAT;
+ morph_stride+=16;
+ }
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ attribs[i].size=4;
+
+ if (p_format&VS::ARRAY_COMPRESS_COLOR) {
+ attribs[i].type=GL_UNSIGNED_BYTE;
+ stride+=4;
+ attribs[i].normalized=GL_TRUE;
+ } else {
+ attribs[i].type=GL_FLOAT;
+ stride+=16;
+ attribs[i].normalized=GL_FALSE;
+ }
+
+ if (has_morph) {
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_FLOAT;
+ morph_stride+=16;
+ }
+
+ } break;
+ case VS::ARRAY_TEX_UV: {
+
+ attribs[i].size=2;
+
+ if (p_format&VS::ARRAY_COMPRESS_TEX_UV) {
+ attribs[i].type=GL_HALF_FLOAT;
+ stride+=4;
+ } else {
+ attribs[i].type=GL_FLOAT;
+ stride+=8;
+ }
+
+ attribs[i].normalized=GL_FALSE;
+
+ if (has_morph) {
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_FLOAT;
+ morph_stride+=8;
+ }
+
+ } break;
+ case VS::ARRAY_TEX_UV2: {
+
+ attribs[i].size=2;
+
+ if (p_format&VS::ARRAY_COMPRESS_TEX_UV2) {
+ attribs[i].type=GL_HALF_FLOAT;
+ stride+=4;
+ } else {
+ attribs[i].type=GL_FLOAT;
+ stride+=8;
+ }
+ attribs[i].normalized=GL_FALSE;
+
+ if (has_morph) {
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_FLOAT;
+ morph_stride+=8;
+ }
+
+ } break;
+ case VS::ARRAY_BONES: {
+
+ attribs[i].size=4;
+
+ if (p_format&VS::ARRAY_COMPRESS_BONES) {
+
+ if (p_format&VS::ARRAY_FLAG_USE_16_BIT_BONES) {
+ attribs[i].type=GL_UNSIGNED_SHORT;
+ stride+=8;
+ } else {
+ attribs[i].type=GL_UNSIGNED_BYTE;
+ stride+=4;
+ }
+ } else {
+ attribs[i].type=GL_UNSIGNED_SHORT;
+ stride+=8;
+ }
+
+ attribs[i].normalized=GL_FALSE;
+
+ if (has_morph) {
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_UNSIGNED_SHORT;
+ morph_stride+=8;
+ }
+
+ } break;
+ case VS::ARRAY_WEIGHTS: {
+
+ attribs[i].size=4;
+
+ if (p_format&VS::ARRAY_COMPRESS_WEIGHTS) {
+
+ attribs[i].type=GL_UNSIGNED_SHORT;
+ stride+=8;
+ attribs[i].normalized=GL_TRUE;
+ } else {
+ attribs[i].type=GL_FLOAT;
+ stride+=16;
+ attribs[i].normalized=GL_FALSE;
+ }
+
+ if (has_morph) {
+ morph_attribs[i].normalized=GL_FALSE;
+ morph_attribs[i].size=attribs[i].size;
+ morph_attribs[i].type=GL_FLOAT;
+ morph_stride+=8;
+ }
+ } break;
+ case VS::ARRAY_INDEX: {
+
+ attribs[i].size=1;
+
+ if (p_vertex_count>=(1<<16)) {
+ attribs[i].type=GL_UNSIGNED_INT;
+ attribs[i].stride=4;
+ } else {
+ attribs[i].type=GL_UNSIGNED_SHORT;
+ attribs[i].stride=2;
+ }
+
+ attribs[i].normalized=GL_FALSE;
+
+ } break;
+
+ }
+ }
+
+ for(int i=0;i<VS::ARRAY_MAX-1;i++) {
+ attribs[i].stride=stride;
+ if (has_morph) {
+ morph_attribs[i].stride=morph_stride;
+ }
+ }
+
+ //validate sizes
+
+ int array_size = stride * p_vertex_count;
+ int index_array_size=0;
+
+ ERR_FAIL_COND(p_array.size()!=array_size);
+
+ if (p_format&VS::ARRAY_FORMAT_INDEX) {
+
+ index_array_size=attribs[VS::ARRAY_INDEX].stride*p_index_count;
+
+ print_line("index count: "+itos(p_index_count)+" stride: "+itos(attribs[VS::ARRAY_INDEX].stride) );
+ }
+
+
+ ERR_FAIL_COND(p_index_array.size()!=index_array_size);
+
+ ERR_FAIL_COND(p_blend_shapes.size()!=mesh->morph_target_count);
+
+ for(int i=0;i<p_blend_shapes.size();i++) {
+ ERR_FAIL_COND(p_blend_shapes[i].size()!=array_size);
+ }
+
+ //ok all valid, create stuff
+
+ Surface * surface = memnew( Surface );
+
+ surface->active=true;
+ surface->array_len=p_vertex_count;
+ surface->index_array_len=p_index_count;
+ surface->primitive=p_primitive;
+ surface->mesh=mesh;
+ surface->format=p_format;
+ surface->skeleton_bone_aabb=p_bone_aabbs;
+ surface->skeleton_bone_used.resize(surface->skeleton_bone_aabb.size());
+ surface->aabb=p_aabb;
+ surface->max_bone=p_bone_aabbs.size();
+
+ for(int i=0;i<surface->skeleton_bone_used.size();i++) {
+ if (surface->skeleton_bone_aabb[i].size.x<0 || surface->skeleton_bone_aabb[i].size.y<0 || surface->skeleton_bone_aabb[i].size.z<0) {
+ surface->skeleton_bone_used[i]=false;
+ } else {
+ surface->skeleton_bone_used[i]=true;
+ }
+ }
+
+ for(int i=0;i<VS::ARRAY_MAX;i++) {
+ surface->attribs[i]=attribs[i];
+ surface->morph_attribs[i]=morph_attribs[i];
+ }
+
+ {
+
+ DVector<uint8_t>::Read vr = p_array.read();
+
+ glGenBuffers(1,&surface->vertex_id);
+ glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id);
+ glBufferData(GL_ARRAY_BUFFER,array_size,vr.ptr(),GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+
+ if (p_format&VS::ARRAY_FORMAT_INDEX) {
+
+ DVector<uint8_t>::Read ir = p_index_array.read();
+
+ glGenBuffers(1,&surface->index_id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_size,ir.ptr(),GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind
+ }
+ //generate arrays for faster state switching
+
+ glGenVertexArrays(1,&surface->array_id);
+ glBindVertexArray(surface->array_id);
+ glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id);
+
+ for(int i=0;i<VS::ARRAY_MAX-1;i++) {
+
+ if (!attribs[i].enabled)
+ continue;
+
+ glVertexAttribPointer(attribs[i].index,attribs[i].size,attribs[i].type,attribs[i].normalized,attribs[i].stride,((uint8_t*)0)+attribs[i].offset);
+ glEnableVertexAttribArray(attribs[i].index);
+
+ }
+
+ if (surface->index_id) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id);
+ }
+
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+ }
+
+ {
+
+ //blend shapes
+
+ for(int i=0;i<p_blend_shapes.size();i++) {
+
+ Surface::MorphTarget mt;
+
+ DVector<uint8_t>::Read vr = p_blend_shapes[i].read();
+
+ glGenBuffers(1,&mt.vertex_id);
+ glBindBuffer(GL_ARRAY_BUFFER,mt.vertex_id);
+ glBufferData(GL_ARRAY_BUFFER,array_size,vr.ptr(),GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+ glGenVertexArrays(1,&mt.array_id);
+ glBindVertexArray(mt.array_id);
+ glBindBuffer(GL_ARRAY_BUFFER,mt.vertex_id);
+
+ for(int i=0;i<VS::ARRAY_MAX-1;i++) {
+
+ if (!attribs[i].enabled)
+ continue;
+
+ glVertexAttribPointer(attribs[i].index,attribs[i].size,attribs[i].type,attribs[i].normalized,attribs[i].stride,((uint8_t*)0)+attribs[i].offset);
+ glEnableVertexAttribArray(attribs[i].index);
+
+ }
+
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+ surface->morph_targets.push_back(mt);
+
+ }
+ }
+
+ mesh->surfaces.push_back(surface);
+ mesh->instance_change_notify();
}
void RasterizerStorageGLES3::mesh_set_morph_target_count(RID p_mesh,int p_amount){
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+
+ ERR_FAIL_COND(mesh->surfaces.size()!=0);
+ ERR_FAIL_COND(p_amount<0);
+
+ mesh->morph_target_count=p_amount;
}
int RasterizerStorageGLES3::mesh_get_morph_target_count(RID p_mesh) const{
- return 0;
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,0);
+
+ return mesh->morph_target_count;
}
void RasterizerStorageGLES3::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode){
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ mesh->morph_target_mode=p_mode;
}
VS::MorphTargetMode RasterizerStorageGLES3::mesh_get_morph_target_mode(RID p_mesh) const{
- return VS::MORPH_MODE_NORMALIZED;
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,VS::MORPH_MODE_NORMALIZED);
+
+ return mesh->morph_target_mode;
}
void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material){
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX(p_surface,mesh->surfaces.size());
+
+ mesh->surfaces[p_surface]->material=p_material;
}
RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const{
- return RID();
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,RID());
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),RID());
+
+ return mesh->surfaces[p_surface]->material;
}
int RasterizerStorageGLES3::mesh_surface_get_array_len(RID p_mesh, int p_surface) const{
- return 0;
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,0);
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),0);
+
+ return mesh->surfaces[p_surface]->array_len;
+
}
int RasterizerStorageGLES3::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const{
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,0);
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),0);
- return 0;
+ return mesh->surfaces[p_surface]->index_array_len;
}
DVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int p_surface) const{
- return DVector<uint8_t>();
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,DVector<uint8_t>());
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),DVector<uint8_t>());
+
+ Surface *surface = mesh->surfaces[p_surface];
+
+ glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id);
+ void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_len,GL_MAP_READ_BIT);
+
+ ERR_FAIL_COND_V(!data,DVector<uint8_t>());
+
+ DVector<uint8_t> ret;
+ ret.resize(surface->array_len);
+
+ {
+
+ DVector<uint8_t>::Write w = ret.write();
+ copymem(w.ptr(),data,surface->array_len);
+ }
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+
+
+ return ret;
}
-DVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh, int p_surface) const{
+DVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh, int p_surface) const {
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,DVector<uint8_t>());
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),DVector<uint8_t>());
+
+ Surface *surface = mesh->surfaces[p_surface];
+
+ ERR_FAIL_COND_V(surface->index_array_len==0,DVector<uint8_t>());
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->vertex_id);
+ void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,surface->index_array_len,GL_MAP_READ_BIT);
+
+ ERR_FAIL_COND_V(!data,DVector<uint8_t>());
+
+ DVector<uint8_t> ret;
+ ret.resize(surface->index_array_len);
+
+ {
+
+ DVector<uint8_t>::Write w = ret.write();
+ copymem(w.ptr(),data,surface->index_array_len);
+ }
+
+ glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
- return DVector<uint8_t>();
+ return ret;
}
uint32_t RasterizerStorageGLES3::mesh_surface_get_format(RID p_mesh, int p_surface) const{
- return 0;
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+
+ ERR_FAIL_COND_V(!mesh,0);
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),0);
+
+ return mesh->surfaces[p_surface]->format;
+
}
+
VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const{
- return VS::PRIMITIVE_MAX;
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,VS::PRIMITIVE_MAX);
+ ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),VS::PRIMITIVE_MAX);
+
+ return mesh->surfaces[p_surface]->primitive;
}
-void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh,int p_index){
+void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){
+
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX(p_surface,mesh->surfaces.size());
+ Surface *surface = mesh->surfaces[p_surface];
+ ERR_FAIL_COND(surface->index_array_len==0);
+
+ glDeleteBuffers(1,&surface->array_id);
+ if (surface->index_id) {
+ glDeleteBuffers(1,&surface->index_id);
+ }
+
+ glDeleteVertexArrays(1,&surface->array_id);
+
+ for(int i=0;i<surface->morph_targets.size();i++) {
+
+ glDeleteBuffers(1,&surface->morph_targets[i].vertex_id);
+ glDeleteVertexArrays(1,&surface->morph_targets[i].array_id);
+ }
+
+ memdelete(surface);
+
+ mesh->surfaces.remove(p_surface);
+
+ mesh->instance_change_notify();
}
int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const{
- return 0;
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,0);
+ return mesh->surfaces.size();
+
}
void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb){
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ mesh->custom_aabb=p_aabb;
}
AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const{
- return AABB();
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh,AABB());
+
+ return mesh->custom_aabb;
+
}
-AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh) const{
+AABB RasterizerStorageGLES3::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;
+/*
+ Skeleton *sk=NULL;
+ if (p_skeleton.is_valid())
+ sk=skeleton_owner.get(p_skeleton);
+*/
+ AABB aabb;
+ /*
+ if (sk && sk->bones.size()!=0) {
+
+
+ for (int i=0;i<mesh->surfaces.size();i++) {
+
+ AABB laabb;
+ if (mesh->surfaces[i]->format&VS::ARRAY_FORMAT_BONES && mesh->surfaces[i]->skeleton_bone_aabb.size()) {
+
+
+ int bs = mesh->surfaces[i]->skeleton_bone_aabb.size();
+ const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr();
+ const bool *skused = mesh->surfaces[i]->skeleton_bone_used.ptr();
+
+ int sbs = sk->bones.size();
+ ERR_CONTINUE(bs>sbs);
+ Skeleton::Bone *skb = sk->bones.ptr();
+
+ bool first=true;
+ for(int j=0;j<bs;j++) {
+
+ if (!skused[j])
+ continue;
+ AABB baabb = skb[ j ].transform_aabb ( skbones[j] );
+ if (first) {
+ laabb=baabb;
+ first=false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+
+ } else {
+
+ laabb=mesh->surfaces[i]->aabb;
+ }
+
+ if (i==0)
+ aabb=laabb;
+ else
+ aabb.merge_with(laabb);
+ }
+ } else {
+*/
+ for (int i=0;i<mesh->surfaces.size();i++) {
+
+ if (i==0)
+ aabb=mesh->surfaces[i]->aabb;
+ else
+ aabb.merge_with(mesh->surfaces[i]->aabb);
+ }
+/*
+ }
+*/
+ return aabb;
- return AABB();
}
void RasterizerStorageGLES3::mesh_clear(RID p_mesh){
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ while(mesh->surfaces.size()) {
+ mesh_remove_surface(p_mesh,0);
+ }
}
/* MULTIMESH API */
@@ -2206,6 +2826,16 @@ void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::L
}
+VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
+
+ return VS::LIGHT_DIRECTIONAL;
+}
+
+AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
+
+ return AABB();
+}
+
/* PROBE API */
RID RasterizerStorageGLES3::reflection_probe_create(){
@@ -2292,6 +2922,42 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color
}
+void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance) {
+
+ Instantiable *inst=NULL;
+ switch(p_instance->base_type) {
+ case VS::INSTANCE_MESH: {
+ inst = mesh_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ default: {
+ ERR_FAIL();
+ }
+ }
+
+ inst->instance_list.add( &p_instance->dependency_item );
+}
+
+void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance){
+
+ Instantiable *inst=NULL;
+
+ switch(p_instance->base_type) {
+ case VS::INSTANCE_MESH: {
+ inst = mesh_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+
+ } break;
+ default: {
+ ERR_FAIL();
+ }
+ }
+
+ ERR_FAIL_COND(!inst);
+
+ inst->instance_list.remove( &p_instance->dependency_item );
+}
+
/* RENDER TARGET */
@@ -2773,6 +3439,15 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder,
}
+VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
+
+ if (mesh_owner.owns(p_rid)) {
+ return VS::INSTANCE_MESH;
+ }
+
+ return VS::INSTANCE_NONE;
+}
+
bool RasterizerStorageGLES3::free(RID p_rid){
if (render_target_owner.owns(p_rid)) {
@@ -2834,6 +3509,15 @@ bool RasterizerStorageGLES3::free(RID p_rid){
material_owner.free(p_rid);
memdelete(material);
+ } else if (mesh_owner.owns(p_rid)) {
+
+ // delete the texture
+ Mesh *mesh = mesh_owner.get(p_rid);
+
+ mesh_clear(p_rid);
+
+ mesh_owner.free(p_rid);
+ memdelete(mesh);
} else if (canvas_occluder_owner.owns(p_rid)) {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index b7b3e607c6..950d65b9d0 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -10,12 +10,14 @@
#include "shader_compiler_gles3.h"
class RasterizerCanvasGLES3;
+class RasterizerSceneGLES3;
class RasterizerStorageGLES3 : public RasterizerStorage {
public:
RasterizerCanvasGLES3 *canvas;
+ RasterizerSceneGLES3 *scene;
enum FBOFormat {
FBO_FORMAT_16_BITS,
@@ -59,6 +61,7 @@ public:
ShaderCompilerGLES3 compiler;
ShaderCompilerGLES3::IdentifierActions actions_canvas;
+ ShaderCompilerGLES3::IdentifierActions actions_scene;
} shaders;
struct Resources {
@@ -230,6 +233,40 @@ public:
} canvas_item;
+ struct Spatial {
+
+ enum BlendMode {
+ BLEND_MODE_MIX,
+ BLEND_MODE_ADD,
+ BLEND_MODE_SUB,
+ BLEND_MODE_MUL,
+ };
+
+ int blend_mode;
+
+ enum DepthDrawMode {
+ DEPTH_DRAW_OPAQUE,
+ DEPTH_DRAW_ALWAYS,
+ DEPTH_DRAW_NEVER,
+ DEPTH_DRAW_ALPHA_PREPASS,
+ };
+
+ int depth_draw_mode;
+
+ enum CullMode {
+ CULL_MODE_FRONT,
+ CULL_MODE_BACK,
+ CULL_MODE_DISABLED,
+ };
+
+ int cull_mode;
+
+ bool uses_alpha;
+ bool unshaded;
+ bool ontop;
+
+ } spatial;
+
Shader() : dirty_list(this) {
shader=NULL;
@@ -272,10 +309,14 @@ public:
SelfList<Material> dirty_list;
Vector<RID> textures;
+ uint32_t index;
+ uint64_t last_pass;
+
Material() : list(this), dirty_list(this) {
shader=NULL;
ubo_id=0;
ubo_size=0;
+ last_pass=0;
}
};
@@ -300,9 +341,155 @@ public:
/* MESH API */
+ struct Instantiable : public RID_Data {
+
+ enum Type {
+ GEOMETRY_INVALID,
+ GEOMETRY_SURFACE,
+ GEOMETRY_IMMEDIATE,
+ GEOMETRY_MULTISURFACE,
+ };
+
+ SelfList<RasterizerScene::InstanceBase>::List instance_list;
+
+ _FORCE_INLINE_ void instance_change_notify() {
+
+ SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
+ while(instances) {
+
+ instances->self()->base_changed();
+ instances=instances->next();
+ }
+ }
+
+ Instantiable() { }
+ virtual ~Instantiable() {
+
+ while(instance_list.first()) {
+ instance_list.first()->self()->base_removed();
+ }
+ }
+ };
+
+ struct Geometry : Instantiable {
+
+ enum Type {
+ GEOMETRY_INVALID,
+ GEOMETRY_SURFACE,
+ GEOMETRY_IMMEDIATE,
+ GEOMETRY_MULTISURFACE,
+ };
+
+ Type type;
+ RID material;
+ uint64_t last_pass;
+ uint32_t index;
+
+ Geometry() {
+ last_pass=0;
+ index=0;
+ }
+
+ };
+
+ struct GeometryOwner : public Instantiable {
+
+ virtual ~GeometryOwner() {}
+ };
+
+ struct Mesh;
+ struct Surface : public Geometry {
+
+ struct Attrib {
+
+ bool enabled;
+ GLuint index;
+ GLint size;
+ GLenum type;
+ GLboolean normalized;
+ GLsizei stride;
+ uint32_t offset;
+ };
+
+ Attrib attribs[VS::ARRAY_MAX];
+ Attrib morph_attribs[VS::ARRAY_MAX];
+
+
+ Mesh *mesh;
+ uint32_t format;
+
+ GLuint array_id;
+ GLuint vertex_id;
+ GLuint index_id;
+
+ Vector<AABB> skeleton_bone_aabb;
+ Vector<bool> skeleton_bone_used;
+
+ //bool packed;
+
+ struct MorphTarget {
+ GLuint vertex_id;
+ GLuint array_id;
+ };
+
+ Vector<MorphTarget> morph_targets;
+
+ AABB aabb;
+
+ int array_len;
+ int index_array_len;
+ int max_bone;
+
+ int array_bytes;
+
+
+ VS::PrimitiveType primitive;
+
+ bool active;
+
+ Surface() {
+
+ array_bytes=0;
+ mesh=NULL;
+ format=0;
+ array_id=0;
+ vertex_id=0;
+ index_id=0;
+ array_len=0;
+ type=GEOMETRY_SURFACE;
+ primitive=VS::PRIMITIVE_POINTS;
+ index_array_len=0;
+ active=false;
+
+ }
+
+ ~Surface() {
+
+ }
+ };
+
+
+ struct Mesh : public GeometryOwner {
+
+ bool active;
+ Vector<Surface*> surfaces;
+ int morph_target_count;
+ VS::MorphTargetMode morph_target_mode;
+ AABB custom_aabb;
+ mutable uint64_t last_pass;
+ Mesh() {
+ morph_target_mode=VS::MORPH_MODE_NORMALIZED;
+ morph_target_count=0;
+ last_pass=0;
+ active=false;
+ }
+ };
+
+ mutable RID_Owner<Mesh> mesh_owner;
+
virtual RID mesh_create();
- virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const Vector<DVector<uint8_t> >& p_blend_shapes=Vector<DVector<uint8_t> >());
+ virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes=Vector<DVector<uint8_t> >(),const Vector<AABB>& p_bone_aabbs=Vector<AABB>());
virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount);
virtual int mesh_get_morph_target_count(RID p_mesh) const;
@@ -324,13 +511,13 @@ public:
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 void mesh_remove_surface(RID p_mesh, int p_surface);
virtual int mesh_get_surface_count(RID p_mesh) const;
virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb);
virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
- virtual AABB mesh_get_aabb(RID p_mesh) const;
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const;
virtual void mesh_clear(RID p_mesh);
/* MULTIMESH API */
@@ -401,6 +588,8 @@ public:
virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode);
+ virtual VS::LightType light_get_type(RID p_light) const;
+ virtual AABB light_get_aabb(RID p_light) const;
/* PROBE API */
virtual RID reflection_probe_create();
@@ -434,6 +623,9 @@ public:
virtual void portal_set_disabled_color(RID p_portal, const Color& p_color);
+ virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance);
+ virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance);
+
/* RENDER TARGET */
struct RenderTarget : public RID_Data {
@@ -522,6 +714,8 @@ public:
virtual RID canvas_light_occluder_create();
virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines);
+ virtual VS::InstanceType get_base_type(RID p_rid) const;
+
virtual bool free(RID p_rid);
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 35191fecf7..ebdf60cf42 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -662,8 +662,8 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co
fragment_code0=code.ascii();
} else {
fragment_code0=code.substr(0,cpos).ascii();
- code = code.substr(cpos+globals_tag.length(),code.length());
-
+ //print_line("CODE0:\n"+String(fragment_code0.get_data()));
+ code = code.substr(cpos+globals_tag.length(),code.length());
cpos = code.find(material_tag);
if (cpos==-1) {
@@ -671,14 +671,18 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co
} else {
fragment_code1=code.substr(0,cpos).ascii();
- String code2 = code.substr(cpos+material_tag.length(),code.length());
+ //print_line("CODE1:\n"+String(fragment_code1.get_data()));
+ String code2 = code.substr(cpos+material_tag.length(),code.length());
cpos = code2.find(code_tag);
+
if (cpos==-1) {
fragment_code2=code2.ascii();
} else {
fragment_code2=code2.substr(0,cpos).ascii();
+ //print_line("CODE2:\n"+String(fragment_code2.get_data()));
+
String code3 = code2.substr(cpos+code_tag.length(),code2.length());
cpos = code3.find(light_code_tag);
@@ -687,7 +691,9 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co
} else {
fragment_code3=code3.substr(0,cpos).ascii();
+ // print_line("CODE3:\n"+String(fragment_code3.get_data()));
fragment_code4 = code3.substr(cpos+light_code_tag.length(),code3.length()).ascii();
+ //print_line("CODE4:\n"+String(fragment_code4.get_data()));
}
}
}
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index 628fa14e4e..0fa0e3b73a 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -4,4 +4,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
env.GLES3_GLSL('copy.glsl');
env.GLES3_GLSL('canvas.glsl');
env.GLES3_GLSL('canvas_shadow.glsl');
+ env.GLES3_GLSL('scene.glsl');
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
new file mode 100644
index 0000000000..4183e828f5
--- /dev/null
+++ b/drivers/gles3/shaders/scene.glsl
@@ -0,0 +1,351 @@
+[vertex]
+
+
+
+/*
+from VisualServer:
+
+ARRAY_VERTEX=0,
+ARRAY_NORMAL=1,
+ARRAY_TANGENT=2,
+ARRAY_COLOR=3,
+ARRAY_TEX_UV=4,
+ARRAY_TEX_UV2=5,
+ARRAY_BONES=6,
+ARRAY_WEIGHTS=7,
+ARRAY_INDEX=8,
+*/
+
+//hack to use uv if no uv present so it works with lightmap
+
+
+/* INPUT ATTRIBS */
+
+layout(location=0) in highp vec4 vertex_attrib;
+layout(location=1) in vec3 normal_attrib;
+layout(location=2) in vec4 tangent_attrib;
+layout(location=3) in vec4 color_attrib;
+layout(location=4) in vec2 uv_attrib;
+layout(location=5) in vec2 uv2_attrib;
+
+uniform float normal_mult;
+
+#ifdef USE_SKELETON
+layout(location=6) mediump ivec4 bone_indices; // attrib:6
+layout(location=7) mediump vec4 bone_weights; // attrib:7
+uniform highp sampler2D skeleton_matrices;
+#endif
+
+#ifdef USE_ATTRIBUTE_INSTANCING
+
+layout(location=8) in highp vec4 instance_xform0;
+layout(location=9) in highp vec4 instance_xform1;
+layout(location=10) in highp vec4 instance_xform2;
+layout(location=11) in lowp vec4 instance_color;
+
+#endif
+
+layout(std140) uniform SceneData { //ubo:0
+
+ highp mat4 projection_matrix;
+ highp mat4 camera_inverse_matrix;
+ highp mat4 camera_matrix;
+ highp vec4 time;
+
+ highp vec4 ambient_light;
+};
+
+uniform highp mat4 world_transform;
+
+/* Varyings */
+
+out vec3 vertex_interp;
+out vec3 normal_interp;
+
+#if defined(ENABLE_COLOR_INTERP)
+out vec4 color_interp;
+#endif
+
+#if defined(ENABLE_UV_INTERP)
+out vec2 uv_interp;
+#endif
+
+#if defined(ENABLE_UV2_INTERP)
+out vec2 uv2_interp;
+#endif
+
+#if defined(ENABLE_VAR1_INTERP)
+out vec4 var1_interp;
+#endif
+
+#if defined(ENABLE_VAR2_INTERP)
+out vec4 var2_interp;
+#endif
+
+#if defined(ENABLE_TANGENT_INTERP)
+out vec3 tangent_interp;
+out vec3 binormal_interp;
+#endif
+
+
+#if !defined(USE_DEPTH_SHADOWS) && defined(USE_SHADOW_PASS)
+
+varying vec4 position_interp;
+
+#endif
+
+#ifdef USE_SHADOW_PASS
+
+uniform highp float shadow_z_offset;
+uniform highp float shadow_z_slope_scale;
+
+#endif
+
+
+VERTEX_SHADER_GLOBALS
+
+
+#if defined(USE_MATERIAL)
+
+layout(std140) uniform UniformData { //ubo:1
+
+MATERIAL_UNIFORMS
+
+};
+
+#endif
+
+
+void main() {
+
+ highp vec4 vertex_in = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0);
+ highp mat4 modelview = camera_inverse_matrix * world_transform;
+ vec3 normal_in = normal_attrib;
+ normal_in*=normal_mult;
+#if defined(ENABLE_TANGENT_INTERP)
+ vec3 tangent_in = tangent_attrib.xyz;
+ tangent_in*=normal_mult;
+ float binormalf = tangent_attrib.a;
+#endif
+
+#ifdef USE_SKELETON
+
+ {
+ //skeleton transform
+ highp mat4 m=mat4(texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.x;
+ m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.y;
+ m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.z;
+ m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.w;
+
+ vertex_in = vertex_in * m;
+ normal_in = (vec4(normal_in,0.0) * m).xyz;
+#if defined(ENABLE_TANGENT_INTERP)
+ tangent_in = (vec4(tangent_in,0.0) * m).xyz;
+#endif
+ }
+
+#endif
+
+ vertex_interp = (modelview * vertex_in).xyz;
+ normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz);
+
+#if defined(ENABLE_TANGENT_INTERP)
+ tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz);
+ binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf );
+#endif
+
+#if defined(ENABLE_COLOR_INTERP)
+ color_interp = color_attrib;
+#endif
+
+#if defined(ENABLE_UV_INTERP)
+ uv_interp = uv_attrib;
+#endif
+#if defined(ENABLE_UV2_INTERP)
+ uv2_interp = uv2_attrib;
+#endif
+
+
+VERTEX_SHADER_CODE
+
+
+#ifdef USE_SHADOW_PASS
+
+ float z_ofs = shadow_z_offset;
+ z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale;
+ vertex_interp.z-=z_ofs;
+#endif
+
+
+#ifdef USE_FOG
+
+ fog_interp.a = pow( clamp( (length(vertex_interp)-fog_params.x)/(fog_params.y-fog_params.x), 0.0, 1.0 ), fog_params.z );
+ fog_interp.rgb = mix( fog_color_begin, fog_color_end, fog_interp.a );
+#endif
+
+#ifndef VERTEX_SHADER_WRITE_POSITION
+//vertex shader might write a position
+ gl_Position = projection_matrix * vec4(vertex_interp,1.0);
+#endif
+
+
+
+
+}
+
+
+[fragment]
+
+
+//hack to use uv if no uv present so it works with lightmap
+
+
+/* Varyings */
+
+#if defined(ENABLE_COLOR_INTERP)
+in vec4 color_interp;
+#endif
+
+#if defined(ENABLE_UV_INTERP)
+in vec2 uv_interp;
+#endif
+
+#if defined(ENABLE_UV2_INTERP)
+in vec2 uv2_interp;
+#endif
+
+#if defined(ENABLE_TANGENT_INTERP)
+in vec3 tangent_interp;
+in vec3 binormal_interp;
+#endif
+
+#if defined(ENABLE_VAR1_INTERP)
+in vec4 var1_interp;
+#endif
+
+#if defined(ENABLE_VAR2_INTERP)
+in vec4 var2_interp;
+#endif
+
+in vec3 vertex_interp;
+in vec3 normal_interp;
+
+
+/* Material Uniforms */
+
+
+FRAGMENT_SHADER_GLOBALS
+
+
+#if defined(USE_MATERIAL)
+
+layout(std140) uniform UniformData {
+
+MATERIAL_UNIFORMS
+
+};
+
+#endif
+
+
+layout(std140) uniform SceneData {
+
+ highp mat4 projection_matrix;
+ highp mat4 camera_inverse_matrix;
+ highp mat4 camera_matrix;
+ highp vec4 time;
+
+ highp vec4 ambient_light;
+};
+
+layout(location=0) out vec4 frag_color;
+
+void main() {
+
+ //lay out everything, whathever is unused is optimized away anyway
+ vec3 vertex = vertex_interp;
+ vec3 albedo = vec3(0.9,0.9,0.9);
+ vec3 metal = vec3(0.0,0.0,0.0);
+ float rough = 0.0;
+ float alpha = 1.0;
+
+#ifdef METERIAL_DOUBLESIDED
+ float side=float(gl_FrontFacing)*2.0-1.0;
+#else
+ float side=1.0;
+#endif
+
+
+#if defined(ENABLE_TANGENT_INTERP)
+ vec3 binormal = normalize(binormal_interp)*side;
+ vec3 tangent = normalize(tangent_interp)*side;
+#endif
+ vec3 normal = normalize(normal_interp)*side;
+
+#if defined(ENABLE_UV_INTERP)
+ vec2 uv = uv_interp;
+#endif
+
+#if defined(ENABLE_UV2_INTERP)
+ vec2 uv2 = uv2_interp;
+#endif
+
+#if defined(ENABLE_COLOR_INTERP)
+ vec4 color = color_interp;
+#endif
+
+#if defined(ENABLE_NORMALMAP)
+
+ vec3 normalmap = vec3(0.0);
+#endif
+
+ float normaldepth=1.0;
+
+
+
+#if defined(ENABLE_DISCARD)
+ bool discard_=false;
+#endif
+
+{
+
+
+FRAGMENT_SHADER_CODE
+
+}
+
+#if defined(ENABLE_NORMALMAP)
+
+ normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side;
+
+#endif
+
+#if defined(ENABLE_DISCARD)
+ if (discard_) {
+ //easy to eliminate dead code
+ discard;
+ }
+#endif
+
+#ifdef ENABLE_CLIP_ALPHA
+ if (diffuse.a<0.99) {
+ //used for doublepass and shadowmapping
+ discard;
+ }
+#endif
+
+
+
+#if defined(USE_LIGHT_SHADER_CODE)
+//light is written by the light shader
+{
+
+LIGHT_SHADER_CODE
+
+}
+#endif
+
+ frag_color=vec4(albedo,alpha);
+}
+
+