Merge pull request #20974 from karroffel/imgeo-gles2
[gles2] added ImmediateGeometry rendering
This commit is contained in:
commit
b6b722d5c1
4 changed files with 276 additions and 11 deletions
|
@ -812,6 +812,14 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p
|
|||
}
|
||||
} 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: {
|
||||
|
||||
} 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);
|
||||
} 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: {
|
||||
|
||||
} break;
|
||||
|
@ -1264,6 +1279,118 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
|
|||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
} 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);
|
||||
}
|
||||
|
||||
{
|
||||
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
|
||||
{
|
||||
int max_shadow_cubemap_sampler_size = 512;
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
|
||||
GLuint sky_verts;
|
||||
|
||||
GLuint immediate_buffer;
|
||||
|
||||
// ResolveShaderGLES3 resolve_shader;
|
||||
// ScreenSpaceReflectionShaderGLES3 ssr_shader;
|
||||
// EffectBlurShaderGLES3 effect_blur_shader;
|
||||
|
|
|
@ -2679,45 +2679,132 @@ void RasterizerStorageGLES2::update_dirty_multimeshes() {
|
|||
/* IMMEDIATE API */
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
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) {
|
||||
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 {
|
||||
return RID();
|
||||
const Immediate *im = immediate_owner.get(p_immediate);
|
||||
ERR_FAIL_COND_V(!im, RID());
|
||||
return im->material;
|
||||
}
|
||||
|
||||
/* SKELETON API */
|
||||
|
@ -3729,16 +3816,16 @@ VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
|
|||
|
||||
if (mesh_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_MESH;
|
||||
}
|
||||
if (light_owner.owns(p_rid)) {
|
||||
} else if (light_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_LIGHT;
|
||||
}
|
||||
if (multimesh_owner.owns(p_rid)) {
|
||||
} else if (multimesh_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_MULTIMESH;
|
||||
}
|
||||
|
||||
} else if (immediate_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_IMMEDIATE;
|
||||
} else {
|
||||
return VS::INSTANCE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool RasterizerStorageGLES2::free(RID p_rid) {
|
||||
|
||||
|
@ -3894,6 +3981,14 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
|
|||
multimesh_owner.free(p_rid);
|
||||
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;
|
||||
} else if (light_owner.owns(p_rid)) {
|
||||
|
||||
|
|
|
@ -797,8 +797,40 @@ public:
|
|||
|
||||
/* 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 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_normal(RID p_immediate, const Vector3 &p_normal);
|
||||
virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent);
|
||||
|
|
Loading…
Reference in a new issue