diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index f29f1caae41..f7b1546d5ea 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -135,60 +135,13 @@ void RasterizerCanvasGLES2::_batch_render_lines(const Batch &p_batch, Rasterizer #endif } -void RasterizerCanvasGLES2::_batch_render_polys(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material) { - - _set_texture_rect_mode(false); - - if (state.canvas_shader.bind()) { - _set_uniforms(); - state.canvas_shader.use_material((void *)p_material); - } - - // batch tex - const BatchTex &tex = bdata.batch_textures[p_batch.batch_texture_id]; - _bind_canvas_texture(tex.RID_texture, tex.RID_normal); - - // state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, Transform()); - - int sizeof_vert = sizeof(BatchVertexColored); - - // bind the index and vertex buffer - glBindBuffer(GL_ARRAY_BUFFER, bdata.gl_vertex_buffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bdata.gl_index_buffer); - - uint64_t pointer = 0; - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof_vert, (const void *)pointer); - - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (2 * 4))); - - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof_vert, CAST_INT_TO_UCHAR_PTR(pointer + (4 * 4))); - - int64_t offset = p_batch.first_vert; // 6 inds per quad at 2 bytes each - - int num_elements = p_batch.num_commands; - glDrawArrays(GL_TRIANGLES, offset, num_elements); - - storage->info.render._2d_draw_call_count++; - - // could these have ifs? - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); - glDisableVertexAttribArray(VS::ARRAY_COLOR); - - // may not be necessary .. state change optimization still TODO - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -void RasterizerCanvasGLES2::_batch_render_rects(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material) { - +void RasterizerCanvasGLES2::_batch_render_generic(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material) { ERR_FAIL_COND(p_batch.num_commands <= 0); - const bool &colored_verts = bdata.use_colored_vertices; const bool &use_light_angles = bdata.use_light_angles; const bool &use_modulate = bdata.use_modulate; const bool &use_large_verts = bdata.use_large_verts; + const bool &colored_verts = bdata.use_colored_vertices | use_light_angles | use_modulate | use_large_verts; int sizeof_vert; @@ -196,9 +149,10 @@ void RasterizerCanvasGLES2::_batch_render_rects(const Batch &p_batch, Rasterizer default: sizeof_vert = 0; // prevent compiler warning - this should never happen break; - case RasterizerStorageCommon::FVF_UNBATCHED: // should not happen + case RasterizerStorageCommon::FVF_UNBATCHED: { + sizeof_vert = 0; // prevent compiler warning - this should never happen return; - break; + } break; case RasterizerStorageCommon::FVF_REGULAR: // no change sizeof_vert = sizeof(BatchVertex); break; @@ -216,13 +170,11 @@ void RasterizerCanvasGLES2::_batch_render_rects(const Batch &p_batch, Rasterizer break; } - // batch tex - const BatchTex &tex = bdata.batch_textures[p_batch.batch_texture_id]; - // make sure to set all conditionals BEFORE binding the shader - //state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); _set_texture_rect_mode(false, use_light_angles, use_modulate, use_large_verts); + // batch tex + const BatchTex &tex = bdata.batch_textures[p_batch.batch_texture_id]; //VSG::rasterizer->gl_check_for_error(); // force repeat is set if non power of 2 texture, and repeat is needed if hardware doesn't support npot @@ -235,9 +187,6 @@ void RasterizerCanvasGLES2::_batch_render_rects(const Batch &p_batch, Rasterizer state.canvas_shader.use_material((void *)p_material); } - // batch tex - //const BatchTex &tex = bdata.batch_textures[p_batch.batch_texture_id]; - _bind_canvas_texture(tex.RID_texture, tex.RID_normal); // bind the index and vertex buffer @@ -297,10 +246,23 @@ void RasterizerCanvasGLES2::_batch_render_rects(const Batch &p_batch, Rasterizer tex.tex_pixel_size.to(tps); state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, tps); - int64_t offset = p_batch.first_vert * 3; + switch (p_batch.type) { + default: { + // prevent compiler warning + } break; + case RasterizerStorageCommon::BT_RECT: { + int64_t offset = p_batch.first_vert * 3; - int num_elements = p_batch.num_commands * 6; - glDrawElements(GL_TRIANGLES, num_elements, GL_UNSIGNED_SHORT, (void *)offset); + int num_elements = p_batch.num_commands * 6; + glDrawElements(GL_TRIANGLES, num_elements, GL_UNSIGNED_SHORT, (void *)offset); + } break; + case RasterizerStorageCommon::BT_POLY: { + int64_t offset = p_batch.first_vert; + + int num_elements = p_batch.num_commands; + glDrawArrays(GL_TRIANGLES, offset, num_elements); + } break; + } storage->info.render._2d_draw_call_count++; @@ -341,10 +303,10 @@ void RasterizerCanvasGLES2::render_batches(Item::Command *const *p_commands, Ite switch (batch.type) { case RasterizerStorageCommon::BT_RECT: { - _batch_render_rects(batch, p_material); + _batch_render_generic(batch, p_material); } break; case RasterizerStorageCommon::BT_POLY: { - _batch_render_polys(batch, p_material); + _batch_render_generic(batch, p_material); } break; case RasterizerStorageCommon::BT_LINE: { _batch_render_lines(batch, p_material, false); diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h index b5518d336fc..50853df46a3 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.h +++ b/drivers/gles2/rasterizer_canvas_gles2.h @@ -59,8 +59,7 @@ private: // low level batch funcs void _batch_upload_buffers(); - void _batch_render_rects(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material); - void _batch_render_polys(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material); + void _batch_render_generic(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material); void _batch_render_lines(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material, bool p_anti_alias); // funcs used from rasterizer_canvas_batcher template diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index ecb53ee40b2..444839ff9ba 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -479,13 +479,13 @@ FRAGMENT_SHADER_CODE normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth); #endif } + +#ifdef USE_ATTRIB_MODULATE + color *= modulate_interp; +#else #if !defined(MODULATE_USED) color *= final_modulate; #endif - -#ifdef USE_ATTRIB_MODULATE - // todo .. this won't be used at the same time as MODULATE_USED - color *= modulate_interp; #endif #ifdef USE_LIGHTING diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 9bb66e26bf8..66ba3982914 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -511,10 +511,10 @@ void RasterizerCanvasGLES3::render_batches(Item::Command *const *p_commands, Ite switch (batch.type) { case RasterizerStorageCommon::BT_RECT: { - _batch_render_rects(batch, p_material); + _batch_render_generic(batch, p_material); } break; case RasterizerStorageCommon::BT_POLY: { - _batch_render_polys(batch, p_material); + _batch_render_generic(batch, p_material); } break; case RasterizerStorageCommon::BT_LINE: { _batch_render_lines(batch, p_material, false); @@ -2036,43 +2036,8 @@ void RasterizerCanvasGLES3::_batch_render_lines(const Batch &p_batch, Rasterizer #endif } -void RasterizerCanvasGLES3::_batch_render_polys(const Batch &p_batch, RasterizerStorageGLES3::Material *p_material) { - ERR_FAIL_COND(p_batch.num_commands <= 0); - - _set_texture_rect_mode(false); - state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); - - glBindVertexArray(batch_gl_data.batch_vertex_array[1]); - - // batch tex - const BatchTex &tex = bdata.batch_textures[p_batch.batch_texture_id]; - - _bind_canvas_texture(tex.RID_texture, tex.RID_normal); - - // may not need this disable - // glDisableVertexAttribArray(VS::ARRAY_COLOR); - // glVertexAttrib4fv(VS::ARRAY_COLOR, p_batch.color.get_data()); - - // we need to convert explicitly from pod Vec2 to Vector2 ... - // could use a cast but this might be unsafe in future - Vector2 tps; - tex.tex_pixel_size.to(tps); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, tps); - - int64_t offset = p_batch.first_vert; - - int num_elements = p_batch.num_commands; - glDrawArrays(GL_TRIANGLES, offset, num_elements); - - storage->info.render._2d_draw_call_count++; - - glBindVertexArray(0); -} - -void RasterizerCanvasGLES3::_batch_render_rects(const Batch &p_batch, RasterizerStorageGLES3::Material *p_material) { - ERR_FAIL_COND(p_batch.num_commands <= 0); - - const bool &colored_verts = bdata.use_colored_vertices; +void RasterizerCanvasGLES3::_batch_render_prepare() { + //const bool &colored_verts = bdata.use_colored_vertices; const bool &use_light_angles = bdata.use_light_angles; const bool &use_modulate = bdata.use_modulate; const bool &use_large_verts = bdata.use_large_verts; @@ -2102,11 +2067,41 @@ void RasterizerCanvasGLES3::_batch_render_rects(const Batch &p_batch, Rasterizer glBindVertexArray(batch_gl_data.batch_vertex_array[4]); break; } +} - // if (state.canvas_shader.bind()) { - // _set_uniforms(); - // state.canvas_shader.use_material((void *)p_material); - // } +void RasterizerCanvasGLES3::_batch_render_generic(const Batch &p_batch, RasterizerStorageGLES3::Material *p_material) { + ERR_FAIL_COND(p_batch.num_commands <= 0); + + const bool &use_light_angles = bdata.use_light_angles; + const bool &use_modulate = bdata.use_modulate; + const bool &use_large_verts = bdata.use_large_verts; + const bool &colored_verts = bdata.use_colored_vertices | use_light_angles | use_modulate | use_large_verts; + + _set_texture_rect_mode(false, false, use_light_angles, use_modulate, use_large_verts); + + // state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, p_rect->flags & CANVAS_RECT_CLIP_UV); + state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false); + + switch (bdata.fvf) { + case RasterizerStorageCommon::FVF_UNBATCHED: // should not happen + return; + break; + case RasterizerStorageCommon::FVF_REGULAR: // no change + glBindVertexArray(batch_gl_data.batch_vertex_array[0]); + break; + case RasterizerStorageCommon::FVF_COLOR: + glBindVertexArray(batch_gl_data.batch_vertex_array[1]); + break; + case RasterizerStorageCommon::FVF_LIGHT_ANGLE: + glBindVertexArray(batch_gl_data.batch_vertex_array[2]); + break; + case RasterizerStorageCommon::FVF_MODULATED: + glBindVertexArray(batch_gl_data.batch_vertex_array[3]); + break; + case RasterizerStorageCommon::FVF_LARGE: + glBindVertexArray(batch_gl_data.batch_vertex_array[4]); + break; + } // batch tex const BatchTex &tex = bdata.batch_textures[p_batch.batch_texture_id]; @@ -2143,10 +2138,23 @@ void RasterizerCanvasGLES3::_batch_render_rects(const Batch &p_batch, Rasterizer tex.tex_pixel_size.to(tps); state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, tps); - int64_t offset = p_batch.first_vert * 3; // 6 inds per quad at 2 bytes each + switch (p_batch.type) { + default: { + // prevent compiler warning + } break; + case RasterizerStorageCommon::BT_RECT: { + int64_t offset = p_batch.first_vert * 3; // 6 inds per quad at 2 bytes each - int num_elements = p_batch.num_commands * 6; - glDrawElements(GL_TRIANGLES, num_elements, GL_UNSIGNED_SHORT, (void *)offset); + int num_elements = p_batch.num_commands * 6; + glDrawElements(GL_TRIANGLES, num_elements, GL_UNSIGNED_SHORT, (void *)offset); + } break; + case RasterizerStorageCommon::BT_POLY: { + int64_t offset = p_batch.first_vert; + + int num_elements = p_batch.num_commands; + glDrawArrays(GL_TRIANGLES, offset, num_elements); + } break; + } storage->info.render._2d_draw_call_count++; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index cec859fee7b..c4dd74b86c6 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -62,8 +62,8 @@ private: // low level batch funcs void _batch_upload_buffers(); - void _batch_render_rects(const Batch &p_batch, RasterizerStorageGLES3::Material *p_material); - void _batch_render_polys(const Batch &p_batch, RasterizerStorageGLES3::Material *p_material); + void _batch_render_prepare(); + void _batch_render_generic(const Batch &p_batch, RasterizerStorageGLES3::Material *p_material); void _batch_render_lines(const Batch &p_batch, RasterizerStorageGLES3::Material *p_material, bool p_anti_alias); // funcs used from rasterizer_canvas_batcher template diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 116a4da8aac..9a1122c9206 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -66,7 +66,7 @@ out mediump vec4 color_interp; #ifdef USE_ATTRIB_MODULATE // modulate doesn't need interpolating but we need to send it to the fragment shader -out mediump vec4 modulate_interp; +flat out mediump vec4 modulate_interp; #endif #ifdef MODULATE_USED @@ -332,7 +332,7 @@ in highp vec2 uv_interp; in mediump vec4 color_interp; #ifdef USE_ATTRIB_MODULATE -in mediump vec4 modulate_interp; +flat in mediump vec4 modulate_interp; #endif #if defined(SCREEN_TEXTURE_USED) @@ -582,13 +582,12 @@ FRAGMENT_SHADER_CODE color = vec4(vec3(enc32), 1.0); #endif +#ifdef USE_ATTRIB_MODULATE + color *= modulate_interp; +#else #if !defined(MODULATE_USED) color *= final_modulate; #endif - -#ifdef USE_ATTRIB_MODULATE - // todo .. this won't be used at the same time as MODULATE_USED - color *= modulate_interp; #endif #ifdef USE_LIGHTING diff --git a/drivers/gles_common/rasterizer_canvas_batcher.h b/drivers/gles_common/rasterizer_canvas_batcher.h index 05b950e789c..2f8657274a5 100644 --- a/drivers/gles_common/rasterizer_canvas_batcher.h +++ b/drivers/gles_common/rasterizer_canvas_batcher.h @@ -1492,9 +1492,42 @@ bool C_PREAMBLE::_prefill_polygon(RasterizerCanvas::Item::CommandPolygon *p_poly CRASH_COND(!vertex_colors); #endif + // are we using large FVF? + //////////////////////////////////// + const bool use_large_verts = bdata.use_large_verts; + const bool use_modulate = bdata.use_modulate; + + BatchColor *vertex_modulates = nullptr; + if (use_modulate) { + vertex_modulates = bdata.vertex_modulates.request(num_inds); +#if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED) + CRASH_COND(!vertex_modulates); +#endif + // precalc the vertex modulate (will be shared by all verts) + // we store the modulate as an attribute in the fvf rather than a uniform + vertex_modulates[0].set(r_fill_state.final_modulate); + } + + BatchTransform *pBT = nullptr; + if (use_large_verts) { + pBT = bdata.vertex_transforms.request(num_inds); +#if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED) + CRASH_COND(!pBT); +#endif + // precalc the batch transform (will be shared by all verts) + // we store the transform as an attribute in the fvf rather than a uniform + const Transform2D &tr = r_fill_state.transform_combined; + + pBT[0].translate.set(tr.elements[2]); + // could do swizzling in shader? + pBT[0].basis[0].set(tr.elements[0][0], tr.elements[1][0]); + pBT[0].basis[1].set(tr.elements[0][1], tr.elements[1][1]); + } + //////////////////////////////////// + // the modulate is always baked Color modulate; - if (multiply_final_modulate) + if (!use_large_verts && !use_modulate && multiply_final_modulate) modulate = r_fill_state.final_modulate; else modulate = Color(1, 1, 1, 1); @@ -1508,6 +1541,11 @@ bool C_PREAMBLE::_prefill_polygon(RasterizerCanvas::Item::CommandPolygon *p_poly } // N.B. polygons don't have color thus don't need a batch change with color + // This code is left as reference in case of problems. + // if (!r_fill_state.curr_batch->color.equals(modulate)) { + // change_batch = true; + // bdata.total_color_changes++; + // } if (change_batch) { // put the tex pixel size in a local (less verbose and can be a register) @@ -1586,8 +1624,32 @@ bool C_PREAMBLE::_prefill_polygon(RasterizerCanvas::Item::CommandPolygon *p_poly } vertex_colors[n] = precalced_colors[ind]; + + if (use_modulate) { + vertex_modulates[n] = vertex_modulates[0]; + } + + if (use_large_verts) { + // reuse precalced transform (same for each vertex within polygon) + pBT[n] = pBT[0]; + } } } // if not software skinning + else { + // software skinning extra passes + if (use_modulate) { + for (int n = 0; n < num_inds; n++) { + vertex_modulates[n] = vertex_modulates[0]; + } + } + // not sure if this will produce garbage if software skinning is changing vertex pos + // in the shader, but is included for completeness + if (use_large_verts) { + for (int n = 0; n < num_inds; n++) { + pBT[n] = pBT[0]; + } + } + } // increment total vert count bdata.total_verts += num_inds; @@ -2704,6 +2766,8 @@ T_PREAMBLE template void C_PREAMBLE::_translate_batches_to_larger_FVF() { + bool include_poly_color = INCLUDE_LIGHT_ANGLES | INCLUDE_MODULATE | INCLUDE_LARGE; + // zeros the size and sets up how big each unit is bdata.unit_vertices.prepare(sizeof(BATCH_VERTEX_TYPE)); bdata.batches_temp.reset(); @@ -2721,6 +2785,7 @@ void C_PREAMBLE::_translate_batches_to_larger_FVF() { Batch *dest_batch = nullptr; + const BatchColor *source_vertex_colors = &bdata.vertex_colors[0]; const float *source_light_angles = &bdata.light_angles[0]; const BatchColor *source_vertex_modulates = &bdata.vertex_modulates[0]; const BatchTransform *source_vertex_transforms = &bdata.vertex_transforms[0]; @@ -2817,7 +2882,13 @@ void C_PREAMBLE::_translate_batches_to_larger_FVF() { #endif cv->pos = bv.pos; cv->uv = bv.uv; - cv->col = source_batch.color; + + // polys are special, they can have per vertex colors + if (!include_poly_color) { + cv->col = source_batch.color; + } else { + cv->col = *source_vertex_colors++; + } if (INCLUDE_LIGHT_ANGLES) { // this is required to allow compilation with non light angle vertex.