Merge pull request #61425 from clayjohn/GLES3-2D
This commit is contained in:
commit
20a1b85589
|
@ -445,6 +445,9 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
|||
}
|
||||
|
||||
void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index) {
|
||||
// Used by Polygon and Mesh.
|
||||
static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
|
||||
|
||||
RS::CanvasItemTextureFilter current_filter = state.default_filter;
|
||||
RS::CanvasItemTextureRepeat current_repeat = state.default_repeat;
|
||||
|
||||
|
@ -474,7 +477,10 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
|||
continue;
|
||||
}
|
||||
|
||||
_update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
|
||||
if (c->type != Item::Command::TYPE_MESH) {
|
||||
// For Meshes, this gets updated below.
|
||||
_update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
state.instance_data_array[r_index].modulation[i] = 0.0;
|
||||
|
@ -680,30 +686,9 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
|||
state.instance_data_array[r_index].ninepatch_margins[j] = 0;
|
||||
}
|
||||
|
||||
// If the previous operation is not done yet, allocate a new buffer
|
||||
if (state.fences[state.current_buffer] != GLsync()) {
|
||||
GLint syncStatus;
|
||||
glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
|
||||
if (syncStatus == GL_UNSIGNALED) {
|
||||
_allocate_instance_data_buffer();
|
||||
} else {
|
||||
glDeleteSync(state.fences[state.current_buffer]);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]);
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
//WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData), &state.instance_data_array[0], GL_DYNAMIC_DRAW);
|
||||
#else
|
||||
void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
memcpy(ubo, &state.instance_data_array[0], sizeof(InstanceData));
|
||||
glUnmapBuffer(GL_UNIFORM_BUFFER);
|
||||
#endif
|
||||
_bind_instance_data_buffer(1);
|
||||
glBindVertexArray(pb->vertex_array);
|
||||
|
||||
static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
|
||||
|
||||
if (pb->index_buffer != 0) {
|
||||
glDrawElements(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr);
|
||||
} else {
|
||||
|
@ -764,12 +749,18 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
|||
case Item::Command::TYPE_MESH:
|
||||
case Item::Command::TYPE_MULTIMESH:
|
||||
case Item::Command::TYPE_PARTICLES: {
|
||||
/*
|
||||
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
|
||||
RID mesh;
|
||||
RID mesh_instance;
|
||||
RID texture;
|
||||
Color modulate(1, 1, 1, 1);
|
||||
int instance_count = 1;
|
||||
uint32_t instance_count = 1;
|
||||
GLuint multimesh_buffer = 0;
|
||||
uint32_t multimesh_stride = 0;
|
||||
uint32_t multimesh_color_offset = 0;
|
||||
uint32_t multimesh_custom_data_offset = 0;
|
||||
bool multimesh_uses_color = false;
|
||||
bool multimesh_uses_custom_data = false;
|
||||
|
||||
if (c->type == Item::Command::TYPE_MESH) {
|
||||
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
|
||||
|
@ -781,26 +772,25 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
|||
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
|
||||
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
|
||||
RID multimesh = mm->multimesh;
|
||||
mesh = storage->multimesh_get_mesh(multimesh);
|
||||
mesh = mesh_storage->multimesh_get_mesh(multimesh);
|
||||
texture = mm->texture;
|
||||
|
||||
if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
|
||||
if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
|
||||
break;
|
||||
}
|
||||
|
||||
instance_count = storage->multimesh_get_instances_to_draw(multimesh);
|
||||
instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh);
|
||||
|
||||
if (instance_count == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
state.instance_data_array[r_index].flags |= 1; //multimesh, trails disabled
|
||||
if (storage->multimesh_uses_colors(multimesh)) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
|
||||
}
|
||||
if (storage->multimesh_uses_custom_data(multimesh)) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
|
||||
}
|
||||
multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
|
||||
multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
|
||||
multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
|
||||
multimesh_custom_data_offset = mesh_storage->multimesh_get_custom_data_offset(multimesh);
|
||||
multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
|
||||
multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
|
||||
}
|
||||
|
||||
// TODO: implement particles here
|
||||
|
@ -816,8 +806,15 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
|||
}
|
||||
|
||||
_bind_canvas_texture(texture, current_filter, current_repeat, r_index);
|
||||
if (instance_count == 1) {
|
||||
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
|
||||
} else if (instance_count > 1) {
|
||||
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED);
|
||||
} else {
|
||||
ERR_PRINT("Must have at least one mesh instance to draw mesh");
|
||||
}
|
||||
|
||||
uint32_t surf_count = storage->mesh_get_surface_count(mesh);
|
||||
uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
|
||||
|
||||
state.instance_data_array[r_index].modulation[0] = base_color.r * modulate.r;
|
||||
state.instance_data_array[r_index].modulation[1] = base_color.g * modulate.g;
|
||||
|
@ -829,19 +826,79 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
|||
state.instance_data_array[r_index].dst_rect[j] = 0;
|
||||
state.instance_data_array[r_index].ninepatch_margins[j] = 0;
|
||||
}
|
||||
|
||||
_bind_instance_data_buffer(1);
|
||||
for (uint32_t j = 0; j < surf_count; j++) {
|
||||
RS::SurfaceData *surface = storage->mesh_get_surface(mesh, j);
|
||||
void *surface = mesh_storage->mesh_get_surface(mesh, j);
|
||||
|
||||
RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface);
|
||||
RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
|
||||
ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
|
||||
|
||||
glBindVertexArray(surface->vertex_array);
|
||||
static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
|
||||
GLuint vertex_array_gl = 0;
|
||||
GLuint index_array_gl = 0;
|
||||
|
||||
// Draw directly, no need to batch
|
||||
uint32_t input_mask = 0; // 2D meshes always use the same vertex format
|
||||
if (mesh_instance.is_valid()) {
|
||||
mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array_gl);
|
||||
} else {
|
||||
mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array_gl);
|
||||
}
|
||||
|
||||
index_array_gl = mesh_storage->mesh_surface_get_index_buffer(surface, 0);
|
||||
bool use_index_buffer = false;
|
||||
glBindVertexArray(vertex_array_gl);
|
||||
if (index_array_gl != 0) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
|
||||
use_index_buffer = true;
|
||||
}
|
||||
|
||||
if (instance_count > 1) {
|
||||
// Bind instance buffers.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
|
||||
glVertexAttribDivisor(5, 1);
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
|
||||
glVertexAttribDivisor(6, 1);
|
||||
|
||||
if (multimesh_uses_color) {
|
||||
glEnableVertexAttribArray(7);
|
||||
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
|
||||
glVertexAttribDivisor(7, 1);
|
||||
}
|
||||
if (multimesh_uses_custom_data) {
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_custom_data_offset * sizeof(float)));
|
||||
glVertexAttribDivisor(8, 1);
|
||||
}
|
||||
}
|
||||
|
||||
GLenum primitive_gl = prim[int(primitive)];
|
||||
if (instance_count == 1) {
|
||||
if (use_index_buffer) {
|
||||
glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0);
|
||||
} else {
|
||||
glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface));
|
||||
}
|
||||
} else if (instance_count > 1) {
|
||||
if (use_index_buffer) {
|
||||
glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0, instance_count);
|
||||
} else {
|
||||
glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), instance_count);
|
||||
}
|
||||
}
|
||||
|
||||
state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (instance_count > 1) {
|
||||
glDisableVertexAttribArray(5);
|
||||
glDisableVertexAttribArray(6);
|
||||
glDisableVertexAttribArray(7);
|
||||
glDisableVertexAttribArray(8);
|
||||
}
|
||||
}
|
||||
*/
|
||||
} break;
|
||||
case Item::Command::TYPE_TRANSFORM: {
|
||||
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
|
||||
|
@ -886,26 +943,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
|||
|
||||
void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
|
||||
if (r_index > 0) {
|
||||
// If the previous operation is not done yet, allocate a new buffer
|
||||
if (state.fences[state.current_buffer] != GLsync()) {
|
||||
GLint syncStatus;
|
||||
glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
|
||||
if (syncStatus == GL_UNSIGNALED) {
|
||||
_allocate_instance_data_buffer();
|
||||
} else {
|
||||
glDeleteSync(state.fences[state.current_buffer]);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]);
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
//WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * r_index, state.instance_data_array, GL_DYNAMIC_DRAW);
|
||||
#else
|
||||
void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData) * r_index, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
memcpy(ubo, state.instance_data_array, sizeof(InstanceData) * r_index);
|
||||
glUnmapBuffer(GL_UNIFORM_BUFFER);
|
||||
#endif
|
||||
_bind_instance_data_buffer(r_index);
|
||||
glBindVertexArray(data.canvas_quad_array);
|
||||
if (state.current_primitive_points == 0) {
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, r_index);
|
||||
|
@ -939,6 +977,32 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::_bind_instance_data_buffer(uint32_t p_max_index) {
|
||||
if (p_max_index == 0) {
|
||||
return;
|
||||
}
|
||||
// If the previous operation is not done yet, allocate a new buffer
|
||||
if (state.fences[state.current_buffer] != GLsync()) {
|
||||
GLint syncStatus;
|
||||
glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
|
||||
if (syncStatus == GL_UNSIGNALED) {
|
||||
_allocate_instance_data_buffer();
|
||||
} else {
|
||||
glDeleteSync(state.fences[state.current_buffer]);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]);
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
//WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * p_max_index, state.instance_data_array, GL_DYNAMIC_DRAW);
|
||||
#else
|
||||
void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData) * p_max_index, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
memcpy(ubo, state.instance_data_array, sizeof(InstanceData) * p_max_index);
|
||||
glUnmapBuffer(GL_UNIFORM_BUFFER);
|
||||
#endif
|
||||
}
|
||||
|
||||
RID RasterizerCanvasGLES3::light_create() {
|
||||
return RID();
|
||||
}
|
||||
|
|
|
@ -252,6 +252,7 @@ public:
|
|||
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
|
||||
void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index);
|
||||
void _render_batch(uint32_t &p_max_index);
|
||||
void _bind_instance_data_buffer(uint32_t p_max_index);
|
||||
void _allocate_instance_data_buffer();
|
||||
|
||||
void set_time(double p_time);
|
||||
|
|
|
@ -5,6 +5,7 @@ mode_quad =
|
|||
mode_ninepatch = #define USE_NINEPATCH
|
||||
mode_primitive = #define USE_PRIMITIVE
|
||||
mode_attributes = #define USE_ATTRIBUTES
|
||||
mode_instanced = #define USE_ATTRIBUTES \n#define USE_INSTANCING
|
||||
|
||||
#[specializations]
|
||||
|
||||
|
@ -20,6 +21,15 @@ layout(location = 4) in vec2 uv_attrib;
|
|||
layout(location = 10) in uvec4 bone_attrib;
|
||||
layout(location = 11) in vec4 weight_attrib;
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
|
||||
layout(location = 5) in highp vec4 instance_xform0;
|
||||
layout(location = 6) in highp vec4 instance_xform1;
|
||||
layout(location = 7) in lowp vec4 instance_color;
|
||||
layout(location = 8) in highp vec4 instance_custom_data;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// This needs to be outside clang-format so the ubo comment is in the right place
|
||||
|
@ -77,13 +87,21 @@ void main() {
|
|||
vec4 bone_weights = vec4(0.0);
|
||||
|
||||
#elif defined(USE_ATTRIBUTES)
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
draw_data_instance = 0;
|
||||
#endif
|
||||
vec2 vertex = vertex_attrib;
|
||||
vec4 color = color_attrib * draw_data[draw_data_instance].modulation;
|
||||
vec2 uv = uv_attrib;
|
||||
|
||||
uvec4 bones = bone_attrib;
|
||||
vec4 bone_weights = weight_attrib;
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
color *= instance_color;
|
||||
instance_custom = instance_custom_data;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
|
@ -98,81 +116,10 @@ void main() {
|
|||
|
||||
mat4 model_matrix = mat4(vec4(draw_data[draw_data_instance].world_x, 0.0, 0.0), vec4(draw_data[draw_data_instance].world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data[draw_data_instance].world_ofs, 0.0, 1.0));
|
||||
|
||||
// MultiMeshes don't batch, so always read from draw_data[0]
|
||||
uint instancing = draw_data[0].flags & FLAGS_INSTANCING_MASK;
|
||||
#ifdef USE_INSTANCING
|
||||
model_matrix = model_matrix * transpose(mat4(instance_xform0, instance_xform1, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)));
|
||||
#endif // USE_INSTANCING
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
/*
|
||||
if (instancing > 1) {
|
||||
// trails
|
||||
|
||||
uint stride = 2 + 1 + 1; //particles always uses this format
|
||||
|
||||
uint trail_size = instancing;
|
||||
|
||||
uint offset = trail_size * stride * gl_InstanceID;
|
||||
|
||||
vec4 pcolor;
|
||||
vec2 new_vertex;
|
||||
{
|
||||
uint boffset = offset + bone_attrib.x * stride;
|
||||
new_vertex = (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.x;
|
||||
pcolor = transforms.data[boffset + 2] * weight_attrib.x;
|
||||
}
|
||||
if (weight_attrib.y > 0.001) {
|
||||
uint boffset = offset + bone_attrib.y * stride;
|
||||
new_vertex += (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.y;
|
||||
pcolor += transforms.data[boffset + 2] * weight_attrib.y;
|
||||
}
|
||||
if (weight_attrib.z > 0.001) {
|
||||
uint boffset = offset + bone_attrib.z * stride;
|
||||
new_vertex += (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.z;
|
||||
pcolor += transforms.data[boffset + 2] * weight_attrib.z;
|
||||
}
|
||||
if (weight_attrib.w > 0.001) {
|
||||
uint boffset = offset + bone_attrib.w * stride;
|
||||
new_vertex += (vec4(vertex, 0.0, 1.0) * mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy * weight_attrib.w;
|
||||
pcolor += transforms.data[boffset + 2] * weight_attrib.w;
|
||||
}
|
||||
|
||||
instance_custom = transforms.data[offset + 3];
|
||||
|
||||
vertex = new_vertex;
|
||||
color *= pcolor;
|
||||
} else*/
|
||||
#endif // USE_ATTRIBUTES
|
||||
/*
|
||||
{
|
||||
if (instancing == 1) {
|
||||
uint stride = 2;
|
||||
{
|
||||
if (bool(draw_data[0].flags & FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
stride += 1;
|
||||
}
|
||||
if (bool(draw_data[0].flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
stride += 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint offset = stride * gl_InstanceID;
|
||||
|
||||
mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
offset += 2;
|
||||
|
||||
if (bool(draw_data[0].flags & FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
color *= transforms.data[offset];
|
||||
offset += 1;
|
||||
}
|
||||
|
||||
if (bool(draw_data[0].flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
instance_custom = transforms.data[offset];
|
||||
}
|
||||
|
||||
matrix = transpose(matrix);
|
||||
model_matrix = model_matrix * matrix;
|
||||
}
|
||||
}
|
||||
*/
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
if (bool(draw_data[draw_data_instance].flags & FLAGS_USING_PARTICLES)) {
|
||||
//scale by texture size
|
||||
|
|
|
@ -722,6 +722,18 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
|
|||
|
||||
for (int i = 0; i < RS::ARRAY_INDEX; i++) {
|
||||
if (!attribs[i].enabled) {
|
||||
glDisableVertexAttribArray(i);
|
||||
if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
|
||||
if (i == RS::ARRAY_COLOR) {
|
||||
glVertexAttrib4f(i, 1, 1, 1, 1);
|
||||
} else if (i == RS::ARRAY_TEX_UV) {
|
||||
glVertexAttrib2f(i, 1, 1);
|
||||
} else if (i == RS::ARRAY_BONES) {
|
||||
glVertexAttrib4f(i, 1, 1, 1, 1);
|
||||
} else if (i == RS::ARRAY_WEIGHTS) {
|
||||
glVertexAttrib4f(i, 1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (i <= RS::ARRAY_TANGENT) {
|
||||
|
@ -941,7 +953,6 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
|
|||
multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
|
||||
multimesh->buffer_set = false;
|
||||
|
||||
//print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
|
||||
multimesh->data_cache = Vector<float>();
|
||||
multimesh->aabb = AABB();
|
||||
multimesh->aabb_dirty = false;
|
||||
|
|
|
@ -493,6 +493,26 @@ public:
|
|||
return multimesh->instances;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ GLuint multimesh_get_gl_buffer(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
return multimesh->buffer;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t multimesh_get_stride(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
return multimesh->stride_cache;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t multimesh_get_color_offset(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
return multimesh->color_offset_cache;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t multimesh_get_custom_data_offset(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
return multimesh->custom_data_offset_cache;
|
||||
}
|
||||
|
||||
/* SKELETON API */
|
||||
|
||||
Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
|
||||
|
|
|
@ -29,3 +29,102 @@
|
|||
/*************************************************************************/
|
||||
|
||||
#include "renderer_canvas_render.h"
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
|
||||
const Rect2 &RendererCanvasRender::Item::get_rect() const {
|
||||
if (custom_rect || (!rect_dirty && !update_when_visible)) {
|
||||
return rect;
|
||||
}
|
||||
|
||||
//must update rect
|
||||
|
||||
if (commands == nullptr) {
|
||||
rect = Rect2();
|
||||
rect_dirty = false;
|
||||
return rect;
|
||||
}
|
||||
|
||||
Transform2D xf;
|
||||
bool found_xform = false;
|
||||
bool first = true;
|
||||
|
||||
const Item::Command *c = commands;
|
||||
|
||||
while (c) {
|
||||
Rect2 r;
|
||||
|
||||
switch (c->type) {
|
||||
case Item::Command::TYPE_RECT: {
|
||||
const Item::CommandRect *crect = static_cast<const Item::CommandRect *>(c);
|
||||
r = crect->rect;
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_NINEPATCH: {
|
||||
const Item::CommandNinePatch *style = static_cast<const Item::CommandNinePatch *>(c);
|
||||
r = style->rect;
|
||||
} break;
|
||||
|
||||
case Item::Command::TYPE_POLYGON: {
|
||||
const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c);
|
||||
r = polygon->polygon.rect_cache;
|
||||
} break;
|
||||
case Item::Command::TYPE_PRIMITIVE: {
|
||||
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
|
||||
for (uint32_t j = 0; j < primitive->point_count; j++) {
|
||||
if (j == 0) {
|
||||
r.position = primitive->points[0];
|
||||
} else {
|
||||
r.expand_to(primitive->points[j]);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Item::Command::TYPE_MESH: {
|
||||
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
|
||||
AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, RID());
|
||||
|
||||
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_MULTIMESH: {
|
||||
const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c);
|
||||
AABB aabb = RSG::mesh_storage->multimesh_get_aabb(multimesh->multimesh);
|
||||
|
||||
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_PARTICLES: {
|
||||
const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c);
|
||||
if (particles_cmd->particles.is_valid()) {
|
||||
AABB aabb = RendererRD::ParticlesStorage::get_singleton()->particles_get_aabb(particles_cmd->particles);
|
||||
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
|
||||
}
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_TRANSFORM: {
|
||||
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
|
||||
xf = transform->xform;
|
||||
found_xform = true;
|
||||
[[fallthrough]];
|
||||
}
|
||||
default: {
|
||||
c = c->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_xform) {
|
||||
r = xf.xform(r);
|
||||
}
|
||||
|
||||
if (first) {
|
||||
rect = r;
|
||||
first = false;
|
||||
} else {
|
||||
rect = rect.merge(r);
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
|
||||
rect_dirty = false;
|
||||
return rect;
|
||||
}
|
||||
|
|
|
@ -356,103 +356,7 @@ public:
|
|||
|
||||
Rect2 global_rect_cache;
|
||||
|
||||
const Rect2 &get_rect() const {
|
||||
if (custom_rect || (!rect_dirty && !update_when_visible)) {
|
||||
return rect;
|
||||
}
|
||||
|
||||
//must update rect
|
||||
|
||||
if (commands == nullptr) {
|
||||
rect = Rect2();
|
||||
rect_dirty = false;
|
||||
return rect;
|
||||
}
|
||||
|
||||
Transform2D xf;
|
||||
bool found_xform = false;
|
||||
bool first = true;
|
||||
|
||||
const Item::Command *c = commands;
|
||||
|
||||
while (c) {
|
||||
Rect2 r;
|
||||
|
||||
switch (c->type) {
|
||||
case Item::Command::TYPE_RECT: {
|
||||
const Item::CommandRect *crect = static_cast<const Item::CommandRect *>(c);
|
||||
r = crect->rect;
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_NINEPATCH: {
|
||||
const Item::CommandNinePatch *style = static_cast<const Item::CommandNinePatch *>(c);
|
||||
r = style->rect;
|
||||
} break;
|
||||
|
||||
case Item::Command::TYPE_POLYGON: {
|
||||
const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c);
|
||||
r = polygon->polygon.rect_cache;
|
||||
} break;
|
||||
case Item::Command::TYPE_PRIMITIVE: {
|
||||
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
|
||||
for (uint32_t j = 0; j < primitive->point_count; j++) {
|
||||
if (j == 0) {
|
||||
r.position = primitive->points[0];
|
||||
} else {
|
||||
r.expand_to(primitive->points[j]);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Item::Command::TYPE_MESH: {
|
||||
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
|
||||
AABB aabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(mesh->mesh, RID());
|
||||
|
||||
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_MULTIMESH: {
|
||||
const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c);
|
||||
AABB aabb = RendererRD::MeshStorage::get_singleton()->multimesh_get_aabb(multimesh->multimesh);
|
||||
|
||||
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_PARTICLES: {
|
||||
const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c);
|
||||
if (particles_cmd->particles.is_valid()) {
|
||||
AABB aabb = RendererRD::ParticlesStorage::get_singleton()->particles_get_aabb(particles_cmd->particles);
|
||||
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
|
||||
}
|
||||
|
||||
} break;
|
||||
case Item::Command::TYPE_TRANSFORM: {
|
||||
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
|
||||
xf = transform->xform;
|
||||
found_xform = true;
|
||||
[[fallthrough]];
|
||||
}
|
||||
default: {
|
||||
c = c->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_xform) {
|
||||
r = xf.xform(r);
|
||||
}
|
||||
|
||||
if (first) {
|
||||
rect = r;
|
||||
first = false;
|
||||
} else {
|
||||
rect = rect.merge(r);
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
|
||||
rect_dirty = false;
|
||||
return rect;
|
||||
}
|
||||
const Rect2 &get_rect() const;
|
||||
|
||||
Command *commands = nullptr;
|
||||
Command *last_command = nullptr;
|
||||
|
|
Loading…
Reference in New Issue