Browse Source

Merge pull request #20974 from karroffel/imgeo-gles2

[gles2] added ImmediateGeometry rendering
Thomas Herzog 7 years ago
parent
commit
b6b722d5c1

+ 136 - 0
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -812,6 +812,14 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p
 				}
 				}
 			} break;
 			} break;
 
 
+			case VS::INSTANCE_IMMEDIATE: {
+				RasterizerStorageGLES2::Immediate *im = storage->immediate_owner.getptr(instance->base);
+				ERR_CONTINUE(!im);
+
+				_add_geometry(im, instance, NULL, -1, p_depth_pass, p_shadow_pass);
+
+			} break;
+
 			default: {
 			default: {
 
 
 			} break;
 			} break;
@@ -931,6 +939,13 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste
 			state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV2_INTERP, s->attribs[VS::ARRAY_TEX_UV2].enabled);
 			state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV2_INTERP, s->attribs[VS::ARRAY_TEX_UV2].enabled);
 		} break;
 		} break;
 
 
+		case VS::INSTANCE_IMMEDIATE: {
+			state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, false);
+			state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_COLOR_INTERP, true);
+			state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV_INTERP, true);
+			state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV2_INTERP, true);
+		} break;
+
 		default: {
 		default: {
 
 
 		} break;
 		} break;
@@ -1264,6 +1279,118 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
 
 
 			glBindBuffer(GL_ARRAY_BUFFER, 0);
 			glBindBuffer(GL_ARRAY_BUFFER, 0);
 		} break;
 		} break;
+
+		case VS::INSTANCE_IMMEDIATE: {
+			const RasterizerStorageGLES2::Immediate *im = static_cast<const RasterizerStorageGLES2::Immediate *>(p_element->geometry);
+
+			if (im->building) {
+				return;
+			}
+
+			bool restore_tex = false;
+
+			glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer);
+
+			for (const List<RasterizerStorageGLES2::Immediate::Chunk>::Element *E = im->chunks.front(); E; E = E->next()) {
+				const RasterizerStorageGLES2::Immediate::Chunk &c = E->get();
+
+				if (c.vertices.empty()) {
+					continue;
+				}
+
+				int vertices = c.vertices.size();
+
+				uint32_t buf_ofs = 0;
+
+				storage->info.render.vertices_count += vertices;
+
+				if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) {
+					RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(c.texture);
+
+					t = t->get_ptr();
+
+					if (t->redraw_if_visible) {
+						VisualServerRaster::redraw_request();
+					}
+
+#ifdef TOOLS_ENABLED
+					if (t->detect_3d) {
+						t->detect_3d(t->detect_3d_ud);
+					}
+#endif
+					if (t->render_target) {
+						t->render_target->used_in_frame = true;
+					}
+
+					glActiveTexture(GL_TEXTURE0);
+					glBindTexture(t->target, t->tex_id);
+					restore_tex = true;
+				} else if (restore_tex) {
+
+					glActiveTexture(GL_TEXTURE0);
+					glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
+					restore_tex = false;
+				}
+
+				if (!c.normals.empty()) {
+					glEnableVertexAttribArray(VS::ARRAY_NORMAL);
+					glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr());
+					glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), ((uint8_t *)NULL) + buf_ofs);
+					buf_ofs += sizeof(Vector3) * vertices;
+				} else {
+					glDisableVertexAttribArray(VS::ARRAY_NORMAL);
+				}
+
+				if (!c.tangents.empty()) {
+					glEnableVertexAttribArray(VS::ARRAY_TANGENT);
+					glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr());
+					glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, GL_FALSE, sizeof(Plane), ((uint8_t *)NULL) + buf_ofs);
+					buf_ofs += sizeof(Plane) * vertices;
+				} else {
+					glDisableVertexAttribArray(VS::ARRAY_TANGENT);
+				}
+
+				if (!c.colors.empty()) {
+					glEnableVertexAttribArray(VS::ARRAY_COLOR);
+					glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr());
+					glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)NULL) + buf_ofs);
+					buf_ofs += sizeof(Color) * vertices;
+				} else {
+					glDisableVertexAttribArray(VS::ARRAY_COLOR);
+				}
+
+				if (!c.uvs.empty()) {
+					glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+					glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs.ptr());
+					glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs);
+					buf_ofs += sizeof(Vector2) * vertices;
+				} else {
+					glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
+				}
+
+				if (!c.uv2s.empty()) {
+					glEnableVertexAttribArray(VS::ARRAY_TEX_UV2);
+					glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uv2s.ptr());
+					glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs);
+					buf_ofs += sizeof(Vector2) * vertices;
+				} else {
+					glDisableVertexAttribArray(VS::ARRAY_TEX_UV2);
+				}
+
+				glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+				glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr());
+				glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), ((uint8_t *)NULL) + buf_ofs);
+
+				glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size());
+			}
+
+			if (restore_tex) {
+				glActiveTexture(GL_TEXTURE0);
+				glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
+				restore_tex = false;
+			}
+
+		} break;
 	}
 	}
 }
 }
 
 
@@ -2247,6 +2374,15 @@ void RasterizerSceneGLES2::initialize() {
 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 		glBindBuffer(GL_ARRAY_BUFFER, 0);
 	}
 	}
 
 
+	{
+		uint32_t immediate_buffer_size = GLOBAL_DEF("rendering/limits/buffers/immediate_buffer_size_kb", 2048);
+
+		glGenBuffers(1, &state.immediate_buffer);
+		glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer);
+		glBufferData(GL_ARRAY_BUFFER, immediate_buffer_size * 1024, NULL, GL_DYNAMIC_DRAW);
+		glBindBuffer(GL_ARRAY_BUFFER, 0);
+	}
+
 	// cubemaps for shadows
 	// cubemaps for shadows
 	{
 	{
 		int max_shadow_cubemap_sampler_size = 512;
 		int max_shadow_cubemap_sampler_size = 512;

+ 2 - 0
drivers/gles2/rasterizer_scene_gles2.h

@@ -74,6 +74,8 @@ public:
 
 
 		GLuint sky_verts;
 		GLuint sky_verts;
 
 
+		GLuint immediate_buffer;
+
 		// ResolveShaderGLES3 resolve_shader;
 		// ResolveShaderGLES3 resolve_shader;
 		// ScreenSpaceReflectionShaderGLES3 ssr_shader;
 		// ScreenSpaceReflectionShaderGLES3 ssr_shader;
 		// EffectBlurShaderGLES3 effect_blur_shader;
 		// EffectBlurShaderGLES3 effect_blur_shader;

+ 105 - 10
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -2679,45 +2679,132 @@ void RasterizerStorageGLES2::update_dirty_multimeshes() {
 /* IMMEDIATE API */
 /* IMMEDIATE API */
 
 
 RID RasterizerStorageGLES2::immediate_create() {
 RID RasterizerStorageGLES2::immediate_create() {
-	return RID();
+	Immediate *im = memnew(Immediate);
+	return immediate_owner.make_rid(im);
 }
 }
 
 
-void RasterizerStorageGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture) {
+void RasterizerStorageGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, 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_primitive;
+	im->chunks.push_back(ic);
+	im->mask = 0;
+	im->building = true;
 }
 }
 
 
 void RasterizerStorageGLES2::immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {
 void RasterizerStorageGLES2::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.position = 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->uv2s.push_back(chunk_uv2);
+	im->mask |= VS::ARRAY_FORMAT_VERTEX;
+	c->vertices.push_back(p_vertex);
 }
 }
 
 
 void RasterizerStorageGLES2::immediate_normal(RID p_immediate, const Vector3 &p_normal) {
 void RasterizerStorageGLES2::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 RasterizerStorageGLES2::immediate_tangent(RID p_immediate, const Plane &p_tangent) {
 void RasterizerStorageGLES2::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 RasterizerStorageGLES2::immediate_color(RID p_immediate, const Color &p_color) {
 void RasterizerStorageGLES2::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 RasterizerStorageGLES2::immediate_uv(RID p_immediate, const Vector2 &tex_uv) {
 void RasterizerStorageGLES2::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 RasterizerStorageGLES2::immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {
 void RasterizerStorageGLES2::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 RasterizerStorageGLES2::immediate_end(RID p_immediate) {
 void RasterizerStorageGLES2::immediate_end(RID p_immediate) {
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	im->building = false;
+	im->instance_change_notify();
 }
 }
 
 
 void RasterizerStorageGLES2::immediate_clear(RID p_immediate) {
 void RasterizerStorageGLES2::immediate_clear(RID p_immediate) {
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(im->building);
+
+	im->chunks.clear();
+	im->instance_change_notify();
 }
 }
 
 
 AABB RasterizerStorageGLES2::immediate_get_aabb(RID p_immediate) const {
 AABB RasterizerStorageGLES2::immediate_get_aabb(RID p_immediate) const {
-	return AABB();
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND_V(!im, AABB());
+	return im->aabb;
 }
 }
 
 
 void RasterizerStorageGLES2::immediate_set_material(RID p_immediate, RID p_material) {
 void RasterizerStorageGLES2::immediate_set_material(RID p_immediate, RID p_material) {
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+
+	im->material = p_material;
+	im->instance_material_change_notify();
 }
 }
 
 
 RID RasterizerStorageGLES2::immediate_get_material(RID p_immediate) const {
 RID RasterizerStorageGLES2::immediate_get_material(RID p_immediate) const {
-	return RID();
+	const Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND_V(!im, RID());
+	return im->material;
 }
 }
 
 
 /* SKELETON API */
 /* SKELETON API */
@@ -3729,15 +3816,15 @@ VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
 
 
 	if (mesh_owner.owns(p_rid)) {
 	if (mesh_owner.owns(p_rid)) {
 		return VS::INSTANCE_MESH;
 		return VS::INSTANCE_MESH;
-	}
-	if (light_owner.owns(p_rid)) {
+	} else if (light_owner.owns(p_rid)) {
 		return VS::INSTANCE_LIGHT;
 		return VS::INSTANCE_LIGHT;
-	}
-	if (multimesh_owner.owns(p_rid)) {
+	} else if (multimesh_owner.owns(p_rid)) {
 		return VS::INSTANCE_MULTIMESH;
 		return VS::INSTANCE_MULTIMESH;
+	} else if (immediate_owner.owns(p_rid)) {
+		return VS::INSTANCE_IMMEDIATE;
+	} else {
+		return VS::INSTANCE_NONE;
 	}
 	}
-
-	return VS::INSTANCE_NONE;
 }
 }
 
 
 bool RasterizerStorageGLES2::free(RID p_rid) {
 bool RasterizerStorageGLES2::free(RID p_rid) {
@@ -3894,6 +3981,14 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
 		multimesh_owner.free(p_rid);
 		multimesh_owner.free(p_rid);
 		memdelete(multimesh);
 		memdelete(multimesh);
 
 
+		return true;
+	} else if (immediate_owner.owns(p_rid)) {
+		Immediate *im = immediate_owner.get(p_rid);
+		im->instance_remove_deps();
+
+		immediate_owner.free(p_rid);
+		memdelete(im);
+
 		return true;
 		return true;
 	} else if (light_owner.owns(p_rid)) {
 	} else if (light_owner.owns(p_rid)) {
 
 

+ 33 - 1
drivers/gles2/rasterizer_storage_gles2.h

@@ -797,8 +797,40 @@ public:
 
 
 	/* IMMEDIATE API */
 	/* IMMEDIATE API */
 
 
+	struct Immediate : public Geometry {
+
+		struct Chunk {
+			RID texture;
+			VS::PrimitiveType primitive;
+			Vector<Vector3> vertices;
+			Vector<Vector3> normals;
+			Vector<Plane> tangents;
+			Vector<Color> colors;
+			Vector<Vector2> uvs;
+			Vector<Vector2> uv2s;
+		};
+
+		List<Chunk> chunks;
+		bool building;
+		int mask;
+		AABB aabb;
+
+		Immediate() {
+			type = GEOMETRY_IMMEDIATE;
+			building = false;
+		}
+	};
+
+	Vector3 chunk_normal;
+	Plane chunk_tangent;
+	Color chunk_color;
+	Vector2 chunk_uv;
+	Vector2 chunk_uv2;
+
+	mutable RID_Owner<Immediate> immediate_owner;
+
 	virtual RID immediate_create();
 	virtual RID immediate_create();
-	virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID());
+	virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture = RID());
 	virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex);
 	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_normal(RID p_immediate, const Vector3 &p_normal);
 	virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent);
 	virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent);