void C4FoWDrawWireframeStrategy::End(C4ShaderCall& call)
{
	// If we have nothing to draw (e.g. directly after initialization), abort early.
	if (vertices.empty()) return;

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	// Upload vertices
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	if (vbo_size < vertices.size())
	{
		glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STREAM_DRAW);
		vbo_size = vertices.size();
	}
	else
	{
		glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]);
	}

	glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position));
	glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color));

	glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Position), 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, x)));
	glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r)));

	// Set Y offset for vertex
	const float y_offset[] = { 0.0f, 0.0f };
	call.SetUniform2fv(C4FoWRSU_VertexOffset, 1, y_offset);

	glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices());

	// Reset GL state
	glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position));
	glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color));
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	// Assume the capacity stays the same:
	vertices.resize(0);
	C4FoWDrawStrategy::End(call);
}
void C4FoWDrawLightTextureStrategy::End(C4ShaderCall& call)
{
	// If we have nothing to draw (e.g. directly after initialization), abort early.
	if (vertices.empty()) return;

	// Upload vertices
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	if (vbo_size < vertices.size())
	{
		glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_DYNAMIC_DRAW);
		vbo_size = vertices.size();
	}
	else
	{
		glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]);
	}

	// Region dimensions
	const float width = region->getSurfaceWidth();
	const float height = region->getSurfaceHeight() / 2.0;

	// Set Y offset for vertex
	float y_offset[] = { 0.0f, 0.0f };
	call.SetUniform2fv(C4FoWRSU_VertexOffset, 1, y_offset);

	// Enable scissor test to only draw in upper or lower half of texture
	glEnable(GL_SCISSOR_TEST);
	glScissor(0, height, width, height);

	// Setup state for 1st pass
	glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position));
	glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color));
	glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Position), 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, x)));
	glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r1)));

	// Set up blend equation, see C4FoWDrawLightTextureStrategy::DrawVertex
	// for details.
	glBlendFunc(GL_ONE, GL_ONE);
	glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);

	// Render 1st pass
	glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices());

	// Prepare state for 2nd pass
	glBlendFunc(GL_ONE, GL_ONE);
	glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
	glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r2)));

	// Render 2nd pass
	glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices());

	// Prepare state for 3rd pass (color pass)
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glBlendEquation(GL_FUNC_ADD);
	glScissor(0, 0, width, height);
	glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r3)));
	y_offset[1] = height;
	call.SetUniform2fv(C4FoWRSU_VertexOffset, 1, y_offset);
	
	// Render 3rd pass
	glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices());

	// Reset GL state
	glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position));
	glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color));
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glDisable(GL_SCISSOR_TEST);

	// Assume the capacity stays the same:
	vertices.resize(0);
	C4FoWDrawStrategy::End(call);
}