浏览代码

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.
lawnjelly 4 年之前
父节点
当前提交
e88b4f330e

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