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);
}
Esempio n. 2
0
void CStdGL::SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdProjectionMatrix* out_modelview)
{
	// Initialize multi blit shader.
	int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
	glBlendFunc(GL_SRC_ALPHA, iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);

	call.Start();

	// Upload uniforms
	const DWORD dwModClr = BlitModulated ? BlitModulateClr : 0xffffffff;
	const float fMod[4] = {
		((dwModClr >> 16) & 0xff) / 255.0f,
		((dwModClr >>  8) & 0xff) / 255.0f,
		((dwModClr      ) & 0xff) / 255.0f,
		((dwModClr >> 24) & 0xff) / 255.0f
	};

	call.SetUniform4fv(C4SSU_ClrMod, 1, fMod);
	call.SetUniform3fv(C4SSU_Gamma, 1, gammaOut);

	if(baseTex != 0)
	{
		call.AllocTexUnit(C4SSU_BaseTex);
		glBindTexture(GL_TEXTURE_2D, baseTex);
	}

	if(overlayTex != 0)
	{
		call.AllocTexUnit(C4SSU_OverlayTex);
		glBindTexture(GL_TEXTURE_2D, overlayTex);

		const float fOverlayModClr[4] = {
			((dwOverlayModClr >> 16) & 0xff) / 255.0f,
			((dwOverlayModClr >>  8) & 0xff) / 255.0f,
			((dwOverlayModClr      ) & 0xff) / 255.0f,
			((dwOverlayModClr >> 24) & 0xff) / 255.0f
		};

		call.SetUniform4fv(C4SSU_OverlayClr, 1, fOverlayModClr);
	}
Esempio n. 3
0
void C4ParticleChunk::Draw(C4TargetFacet cgo, C4Object *obj, C4ShaderCall& call, int texUnit, const StdProjectionMatrix& modelview)
{
	if (particleCount == 0) return;
	const int stride = sizeof(C4Particle::DrawingData::Vertex);
	assert(sourceDefinition && "No source definition assigned to particle chunk.");
	C4TexRef *textureRef = &sourceDefinition->Gfx.GetFace().textures[0];
	assert(textureRef != 0 && "Particle definition had no texture assigned.");

	// use a relative offset?
	// (note the normal matrix is unaffected by this)
	if ((attachment & C4ATTACH_MoveRelative) && (obj != 0))
	{
		StdProjectionMatrix new_modelview(modelview);
		Translate(new_modelview, fixtof(obj->GetFixedX()), fixtof(obj->GetFixedY()), 0.0f);
		call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, new_modelview);
	}
	else
	{
		call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, modelview);
	}

	// enable additive blending for particles with that blit mode
	glBlendFunc(GL_SRC_ALPHA, (blitMode & C4GFXBLIT_ADDITIVE) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);

	glActiveTexture(texUnit);
	glBindTexture(GL_TEXTURE_2D, textureRef->texName);

	// generate the buffer as necessary
	if (drawingDataVertexBufferObject == 0)
	{
		// clear up old data
		ClearBufferObjects();
		// generate new buffer objects
		glGenBuffers(1, &drawingDataVertexBufferObject);
		assert (drawingDataVertexBufferObject != 0 && "Could not generate OpenGL buffer object.");
		// Immediately bind the buffer.
		// glVertexAttribPointer requires a valid GL_ARRAY_BUFFER to be bound and we need the buffer to be created for glObjectLabel.
		glBindBuffer(GL_ARRAY_BUFFER, drawingDataVertexBufferObject);

#ifdef GL_KHR_debug
		if (glObjectLabel)
			glObjectLabel(GL_BUFFER, drawingDataVertexBufferObject, -1, "<particles>/VBO");
#endif

		// generate new VAO ID
		drawingDataVertexArraysObject = pGL->GenVAOID();
		assert (drawingDataVertexArraysObject != 0 && "Could not generate a VAO ID.");
	}


	// Push the new vertex data
	glBindBuffer(GL_ARRAY_BUFFER, drawingDataVertexBufferObject);
	glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(C4Particle::DrawingData::Vertex) * particleCount, &vertexCoordinates[0], GL_DYNAMIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	// set up the vertex array structure
	GLuint vao;
	const bool has_vao = pGL->GetVAO(drawingDataVertexArraysObject, vao);
	glBindVertexArray(vao);

	assert ((drawingDataVertexBufferObject != 0) && "No buffer object has been created yet.");
	assert ((drawingDataVertexArraysObject != 0) && "No vertex arrays object has been created yet.");

	if (!has_vao)
	{
		glBindBuffer(GL_ARRAY_BUFFER, drawingDataVertexBufferObject);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ::Particles.GetIBO());
#ifdef GL_KHR_debug
		if (glObjectLabel)
			glObjectLabel(GL_VERTEX_ARRAY, vao, -1, "<particles>/VAO");
#endif

		glEnableVertexAttribArray(call.GetAttribute(C4SSA_Position));
		glEnableVertexAttribArray(call.GetAttribute(C4SSA_Color));
		glEnableVertexAttribArray(call.GetAttribute(C4SSA_TexCoord));
		glVertexAttribPointer(call.GetAttribute(C4SSA_Position), 2, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<GLvoid*>(offsetof(C4Particle::DrawingData::Vertex, x)));
		glVertexAttribPointer(call.GetAttribute(C4SSA_TexCoord), 2, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<GLvoid*>(offsetof(C4Particle::DrawingData::Vertex, u)));
		glVertexAttribPointer(call.GetAttribute(C4SSA_Color), 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<GLvoid*>(offsetof(C4Particle::DrawingData::Vertex, r)));
	}

	glDrawElements(GL_TRIANGLE_STRIP, static_cast<GLsizei> (5 * particleCount), GL_UNSIGNED_INT, 0);

	// reset buffer data
	glBindVertexArray(0);
}
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);
}