Browse Source

Merge pull request #43498 from lawnjelly/ewok_poly_modulate

Poly colors fixes
Rémi Verschelde 4 years ago
parent
commit
b38f7af4fd

+ 25 - 63
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);

+ 1 - 2
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

+ 4 - 4
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
 	}
-#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;
+#else
+#if !defined(MODULATE_USED)
+	color *= final_modulate;
+#endif
 #endif
 
 #ifdef USE_LIGHTING

+ 48 - 40
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,46 +2036,46 @@ 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;
+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;
 
-	int num_elements = p_batch.num_commands;
-	glDrawArrays(GL_TRIANGLES, offset, num_elements);
+	_set_texture_rect_mode(false, false, use_light_angles, use_modulate, use_large_verts);
 
-	storage->info.render._2d_draw_call_count++;
+	//	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);
 
-	glBindVertexArray(0);
+	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;
+	}
 }
 
-void RasterizerCanvasGLES3::_batch_render_rects(const Batch &p_batch, RasterizerStorageGLES3::Material *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 &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;
 
 	_set_texture_rect_mode(false, false, use_light_angles, use_modulate, use_large_verts);
 
@@ -2103,11 +2103,6 @@ void RasterizerCanvasGLES3::_batch_render_rects(const Batch &p_batch, Rasterizer
 			break;
 	}
 
-	//	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];
 
@@ -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);
+		} break;
+		case RasterizerStorageCommon::BT_POLY: {
+			int64_t offset = p_batch.first_vert;
 
-	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;
+			glDrawArrays(GL_TRIANGLES, offset, num_elements);
+		} break;
+	}
 
 	storage->info.render._2d_draw_call_count++;
 

+ 2 - 2
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

+ 5 - 6
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

+ 73 - 2
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;
@@ -2707,6 +2769,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();
@@ -2724,6 +2788,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];
@@ -2820,7 +2885,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.