Poly colors fixes

This adds support for custom shaders for polys, and properly handles modulate in the case of large FVF and modulate FVF.

It also fixes poly vertex colors not being sent to OpenGL.
This commit is contained in:
lawnjelly 2020-11-12 19:16:33 +00:00
parent adf2dabbde
commit e88b4f330e
7 changed files with 164 additions and 125 deletions

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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++;

View file

@ -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

View file

@ -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

View file

@ -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 <class BATCH_VERTEX_TYPE, bool INCLUDE_LIGHT_ANGLES, bool INCLUDE_MODULATE, bool INCLUDE_LARGE>
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.