Example #1
0
void CDecalsDrawerGL4::UpdateOverlap_Initialize()
{
	glClearStencil(0);
	glClear(GL_STENCIL_BUFFER_BIT);
	//glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
	//glClear(GL_COLOR_BUFFER_BIT);

	glStencilFunc(GL_ALWAYS, 0, 0xFF);
	glStencilOp(GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP);

	CVertexArray* va = GetVertexArray();
	va->Initialize();
	for (Decal& d: decals) {
		DRAW_DECAL(va, &d);
	}
	va->DrawArray2dT(GL_QUADS);

	/*const size_t datasize = 4 * OVERLAP_TEST_TEXTURE_SIZE * OVERLAP_TEST_TEXTURE_SIZE;
	unsigned char* img = new unsigned char[datasize];
	memset(img, 0, datasize);
	glReadPixels(0, 0, OVERLAP_TEST_TEXTURE_SIZE, OVERLAP_TEST_TEXTURE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, img);
	CBitmap bitmap(img, OVERLAP_TEST_TEXTURE_SIZE, OVERLAP_TEST_TEXTURE_SIZE);
	bitmap.Save("decals.png", true);
	delete[] img;*/
}
Example #2
0
std::vector<int> CDecalsDrawerGL4::UpdateOverlap_CheckQueries()
{
	// query the results of the last issued test (if any pixels were rendered for the decal)
	std::vector<int> candidatesForRemoval;
	candidatesForRemoval.reserve(waitingOverlapGlQueries.size());
	for (auto& p: waitingOverlapGlQueries) {
		GLint rendered = GL_FALSE;
		glGetQueryObjectiv(p.second, GL_QUERY_RESULT, &rendered);
		glDeleteQueries(1, &p.second);
		if (rendered == GL_FALSE) {
			candidatesForRemoval.push_back(p.first);
		}
	}
	waitingOverlapGlQueries.clear();

	// no candidates left, restart with stage 0
	if (candidatesForRemoval.empty()) {
		overlapStage = 0;
		return candidatesForRemoval;
	}

	//FIXME comment
	auto sortBeginIt = candidatesForRemoval.begin();
	auto sortEndIt = candidatesForRemoval.end();
	while (sortBeginIt != sortEndIt) {
		std::sort(sortBeginIt, sortEndIt, [&](const int& idx1, const int& idx2){
			return decals[idx1].generation < decals[idx2].generation;
		});
		sortEndIt = std::partition(sortBeginIt+1, sortEndIt, [&](const int& idx){
			return !Overlap(decals[*sortBeginIt], decals[idx]);
		});
		++sortBeginIt;
	}
	auto eraseIt = sortEndIt;

	// free one decal (+ remove it from the overlap texture)
	int freed = 0;
	CVertexArray* va = GetVertexArray();
	glStencilFunc(GL_ALWAYS, 0, 0xFF);
	glStencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP);
	va->Initialize();
	for (auto it = candidatesForRemoval.begin(); it != eraseIt; ++it) {
		const int curIndex = *it;
		const Decal& d = decals[curIndex];
		DRAW_DECAL(va, &d);
		FreeDecal(curIndex);
		freed++;
	}
	va->DrawArray2dT(GL_QUADS);
	candidatesForRemoval.erase(candidatesForRemoval.begin(), eraseIt);

	//FIXME
	LOG_L(L_ERROR, "Query freed: %i of %i (decals:%i groups:%i)", freed, int(candidatesForRemoval.size()), int(decals.size() - freeIds.size()), int(groups.size()));

	// overlap texture changed, so need to retest the others
	return candidatesForRemoval;
}
Example #3
0
void CDecalsDrawerGL4::UpdateOverlap_GenerateQueries(const std::vector<int>& candidatesForOverlap)
{
	glStencilFunc(GL_GREATER, MAX_OVERLAP, 0xFF);
	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

	CVertexArray* va = GetVertexArray();
	for (int i: candidatesForOverlap) {
		Decal& d0 = decals[i];
		GLuint q;
		glGenQueries(1, &q);
		glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, q);

		va->Initialize();
		DRAW_DECAL(va, &d0);
		va->DrawArray2dT(GL_QUADS);

		glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE);
		waitingOverlapGlQueries.emplace_back(i, q);
	}
}
Example #4
0
void CDecalsDrawerGL4::GenerateAtlasTexture()
{
	std::unordered_map<std::string, STex> textures;
	GetBuildingDecals(textures);
	GetGroundScars(textures);
	GetFallbacks(textures);

	CQuadtreeAtlasAlloc atlas;
	atlas.SetNonPowerOfTwo(globalRendering->supportNPOTs);
	atlas.SetMaxSize(globalRendering->maxTextureSize, globalRendering->maxTextureSize);
	for (auto it = textures.begin(); it != textures.end(); ++it) {
		if (it->second.id == 0)
			continue;

		const float maxSize = 1024; //512;
		int2 size = it->second.size;
		if (size.x > maxSize) {
			size.y = size.y * (maxSize / size.x);
			size.x = maxSize;
		}
		if (size.y > maxSize) {
			size.x = size.x * (maxSize / size.y);
			size.y = maxSize;
		}

		atlas.AddEntry(it->first, size);
	}
	/*bool success =*/ atlas.Allocate();



	glGenTextures(1, &atlasTex);
	glBindTexture(GL_TEXTURE_2D, atlasTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4.0f);
	glSpringTexStorage2D(GL_TEXTURE_2D, atlas.GetMaxMipMaps(), GL_RGBA8, atlas.GetAtlasSize().x, atlas.GetAtlasSize().y);

	FBO fb;
	if (!fb.IsValid()) {
		LOG_L(L_ERROR, "[%s] framebuffer not valid", __FUNCTION__);
		return;
	}
	fb.Bind();
	fb.AttachTexture(atlasTex);
	if (!fb.CheckStatus(LOG_SECTION_DECALS_GL4)) {
		LOG_L(L_ERROR, "[%s] Couldn't render to FBO!", __FUNCTION__);
		return;
	}

	glViewport(0, 0, atlas.GetAtlasSize().x, atlas.GetAtlasSize().y);
	glSpringMatrix2dProj(atlas.GetAtlasSize().x, atlas.GetAtlasSize().y);

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // transparent black
	glClear(GL_COLOR_BUFFER_BIT);

	glActiveTexture(GL_TEXTURE0);
	glEnable(GL_TEXTURE_2D);

	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ZERO);
	glDisable(GL_DEPTH_TEST);

	CVertexArray va;
	for (auto& p: textures) {
		if (p.second.id == 0)
			continue;

		const float4 texCoords = atlas.GetTexCoords(p.first);
		const float4 absCoords = atlas.GetEntry(p.first);
		atlasTexs[p.first] = SAtlasTex(texCoords);

		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		glBindTexture(GL_TEXTURE_2D, p.second.id);

		va.Initialize();
		va.AddVertex2dT(absCoords.x,   absCoords.y, 0.0f, 0.0f);
		va.AddVertex2dT(absCoords.z+1, absCoords.y, 1.0f, 0.0f); //FIXME why +1?
		va.AddVertex2dT(absCoords.x,   absCoords.w+1, 0.0f, 1.0f);
		va.AddVertex2dT(absCoords.z+1, absCoords.w+1, 1.0f, 1.0f); //FIXME why +1?
		va.DrawArray2dT(GL_TRIANGLE_STRIP);

		glDeleteTextures(1, &p.second.id);
	}

	fb.Unbind();
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glBindTexture(GL_TEXTURE_2D, atlasTex);
	glGenerateMipmap(GL_TEXTURE_2D);

#ifdef DEBUG_SAVE_ATLAS
	glSaveTexture(atlasTex, "x_decal_atlas.png");
#endif
}