Esempio n. 1
0
static void GenTexture(
	const SDL_Surface * surface,
	const TextureInfo & info,
	unsigned & id,
	bool & alpha,
	std::ostream & error)
{
	// detect channels
	int internalformat, format;
	GetTextureFormat(surface, info, internalformat, format, alpha);

	// gen texture
	glGenTextures(1, &id);
	CheckForOpenGLErrors("Texture ID generation", error);

	// init texture
	glBindTexture(GL_TEXTURE_2D, id);

	SetSampler(info);

	glTexImage2D(GL_TEXTURE_2D, 0, internalformat, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);
	CheckForOpenGLErrors("Texture creation", error);

	// If we support generatemipmap, go ahead and do it regardless of the info.mipmap setting.
	// In the GL3 renderer the sampler decides whether or not to do mip filtering, so we conservatively make mipmaps available for all textures.
	GenerateMipmap(GL_TEXTURE_2D);
}
Esempio n. 2
0
void FrameBufferObject::Begin(GraphicsState & glstate, std::ostream & error_output, float viewscale)
{
	CheckForOpenGLErrors("before FBO begin", error_output);

	assert(inited);
	assert(framebuffer_object > 0);
	assert(!textures.empty());

	glstate.BindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);

	CheckForOpenGLErrors("FBO bind to framebuffer", error_output);

	FrameBufferTexture * tex = textures.back();
	if (tex->GetTarget() == FrameBufferTexture::CUBEMAP)
	{
		glFramebufferTexture2D(GL_FRAMEBUFFER, tex->GetAttachment(), tex->GetSide(), tex->GetId(), 0);
		CheckForOpenGLErrors("FBO cubemap side attachment", error_output);
	}

	assert(CheckStatus(error_output));

	glstate.SetViewport(int(tex->GetW() * viewscale), int(tex->GetH() * viewscale));

	CheckForOpenGLErrors("during FBO begin", error_output);
}
Esempio n. 3
0
void GraphicsGL2::DrawScenePassPost(
	const GraphicsConfigPass & pass,
	std::ostream & error_output)
{
	assert(pass.draw.back() == "postprocess");

	if (!pass.conditions.Satisfied(conditions))
		return;

	shader_map_type::iterator si = shaders.find(pass.shader);
	if (si == shaders.end())
	{
		ReportOnce(&pass, "Shader " + pass.shader + " couldn't be found", error_output);
		return;
	}
	postprocess.SetShader(&si->second);

	std::vector <TextureInterface*> input_textures;
	GetScenePassInputTextures(pass.inputs, input_textures);
	postprocess.SetTextures(glstate, input_textures, error_output);

	postprocess.SetColorMask(glstate, pass.write_color, pass.write_alpha);
	postprocess.SetDepthMode(glstate, DepthModeFromString(pass.depthtest), pass.write_depth);
	postprocess.SetBlendMode(glstate, BlendModeFromString(pass.blendmode));

	render_output_map_type::iterator oi = render_outputs.find(pass.output);
	if (oi == render_outputs.end())
	{
		ReportOnce(&pass, "Render output " + pass.output + " couldn't be found", error_output);
		return;
	}
	RenderOutput & output = oi->second;

	// setup camera, even though we don't use it directly for the post process
	// we want to have some info available
	std::string cameraname = pass.camera;
	camera_map_type::iterator ci = cameras.find(cameraname);
	if (ci == cameras.end())
	{
		ReportOnce(&pass, "Camera " + cameraname + " couldn't be found", error_output);
		return;
	}
	postprocess.SetCamera(ci->second);

	output.Begin(glstate, error_output);

	CheckForOpenGLErrors("render output begin", error_output);

	postprocess.ClearOutput(glstate, pass.clear_color, pass.clear_depth);

	postprocess.Render(glstate, error_output);

	CheckForOpenGLErrors("render finish", error_output);

	output.End(glstate, error_output);

	CheckForOpenGLErrors("render output end", error_output);
}
Esempio n. 4
0
void GraphicsGL2::ChangeDisplay(
	const int width, const int height,
	std::ostream & error_output)
{
	glstate.SetViewport(width, height);

	CheckForOpenGLErrors("ChangeDisplay", error_output);

	w = width;
	h = height;
}
Esempio n. 5
0
void FrameBufferObject::End(GraphicsState & glstate, std::ostream & error_output)
{
	CheckForOpenGLErrors("start of FBO end", error_output);

	if (singlesample_framebuffer_object)
	{
		glstate.BindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_object);
		glstate.BindFramebuffer(GL_DRAW_FRAMEBUFFER, singlesample_framebuffer_object->framebuffer_object);

		assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
		assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

		CheckForOpenGLErrors("FBO end multisample binding", error_output);

		const int w = singlesample_framebuffer_object->GetWidth();
		const int h = singlesample_framebuffer_object->GetHeight();
		glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);

		CheckForOpenGLErrors("FBO end multisample blit", error_output);
	}

	CheckForOpenGLErrors("FBO multisample blit", error_output);

	// optionally rebuild mipmaps
	for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++)
	{
		if ((*i)->HasMipMap())
		{
			glstate.BindTexture(0, (*i)->GetTarget(), (*i)->GetId());
			glGenerateMipmap((*i)->GetTarget());
			glstate.BindTexture(0, (*i)->GetTarget(), 0);
		}
	}

	CheckForOpenGLErrors("end of FBO end", error_output);
}
Esempio n. 6
0
void RenderInputScene::SetTextures(
	GraphicsState & glstate,
	const std::vector <TextureInterface*> & textures,
	std::ostream & error_output)
{
	for (unsigned i = 0; i < textures.size(); i++)
	{
		if (textures[i])
		{
			glstate.BindTexture(i, textures[i]->GetTarget(), textures[i]->GetId());

			if (CheckForOpenGLErrors("RenderDrawlists extra texture bind", error_output))
			{
				error_output << "this error occurred while binding texture " << i << " id=" << textures[i]->GetId() << std::endl;
			}
		}
	}
}
Esempio n. 7
0
void GraphicsGL2::BeginScene(std::ostream & error_output)
{
	glstate.Disable(GL_TEXTURE_2D);
	glstate.Enable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	glShadeModel(GL_SMOOTH);
	glClearColor(0,0,0,0);
	glClearDepth(1.0f);
	glstate.Enable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glstate.Disable(GL_LIGHTING);
	glstate.SetColor(0.5,0.5,0.5,1.0);
	glPolygonOffset(-1.0,-1.0);

	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	CheckForOpenGLErrors("BeginScene", error_output);
}
Esempio n. 8
0
void GraphicsGL2::ChangeDisplay(
	const int width, const int height,
	std::ostream & error_output)
{
	glViewport(0, 0, (GLint)width, (GLint)height);

	GLfloat ratio = (GLfloat)width / (GLfloat)height;
	Mat4 m;

	glMatrixMode(GL_PROJECTION);
	m.Perspective(45.0f, ratio, 0.1f, 100.0f);
	glLoadMatrixf(m.GetArray());

	glMatrixMode(GL_MODELVIEW);
	m.LoadIdentity();
	glLoadMatrixf(m.GetArray());

	CheckForOpenGLErrors("ChangeDisplay", error_output);

	w = width;
	h = height;
}
Esempio n. 9
0
static void AttachCubeSide(int i, FrameBufferObject & reflection_fbo, std::ostream & error_output)
{
	switch (i)
	{
		case 0:
		reflection_fbo.SetCubeSide(FrameBufferTexture::POSX);
		break;

		case 1:
		reflection_fbo.SetCubeSide(FrameBufferTexture::NEGX);
		break;

		case 2:
		reflection_fbo.SetCubeSide(FrameBufferTexture::POSY);
		break;

		case 3:
		reflection_fbo.SetCubeSide(FrameBufferTexture::NEGY);
		break;

		case 4:
		reflection_fbo.SetCubeSide(FrameBufferTexture::POSZ);
		break;

		case 5:
		reflection_fbo.SetCubeSide(FrameBufferTexture::NEGZ);
		break;

		default:
		error_output << "Reached odd spot while attaching cubemap side. How many sides are in a cube, anyway? " << i << "?" << std::endl;
		assert(0);
		break;
	};

	CheckForOpenGLErrors("cubemap generation: FBO cube side attachment", error_output);
}
Esempio n. 10
0
bool Texture::LoadDDS(const std::string & path, const TextureInfo & info, std::ostream & error)
{
	std::ifstream file(path.c_str(), std::ifstream::in | std::ifstream::binary);
	if (!file)
		return false;

	// test for dds magic value
	char magic[4];
	file.read(magic, 4);
	if (!IsDDS(magic, 4))
		return false;

	// get length of file:
	file.seekg (0, file.end);
	const unsigned long length = file.tellg();
	file.seekg (0, file.beg);

	// read file into memory
	std::vector<char> data(length);
	file.read(&data[0], length);

	// load dds
	const char * texdata(0);
	unsigned long texlen(0);
	unsigned format(0), width(0), height(0), levels(0);
	if (!ReadDDS(
		(void*)&data[0], length,
		(const void*&)texdata, texlen,
		format, width, height, levels))
	{
		return false;
	}

	// set properties
	m_w = width;
	m_h = height;
	m_scale = 1.0f;
	m_alpha = (format != GL_BGR);
	m_cube = false;

	// gl3 renderer expects srgb
	unsigned iformat = format;
	if (info.srgb)
	{
		if (format == GL_BGR)
			iformat = GL_SRGB8;
		else if (format == GL_BGRA)
			iformat = GL_SRGB8_ALPHA8;
		else if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
			iformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
		else if (format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)
			iformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
		else if (format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
			iformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
	}

	// load texture
	assert(!m_id);
	glGenTextures(1, &m_id);
	CheckForOpenGLErrors("Texture ID generation", error);

	glBindTexture(GL_TEXTURE_2D, m_id);

	SetSampler(info, levels > 1);

	const char * idata = texdata;
	unsigned blocklen = 16 * texlen / (width * height);
	unsigned ilen = texlen;
	unsigned iw = width;
	unsigned ih = height;
	for (unsigned i = 0; i < levels; ++i)
	{
		if (format == GL_BGR || format == GL_BGRA)
		{
			// fixme: support compression here?
			ilen = iw * ih * blocklen / 16;
			glTexImage2D(GL_TEXTURE_2D, i, iformat, iw, ih, 0, format, GL_UNSIGNED_BYTE, idata);
		}
		else
		{
			ilen = std::max(1u, iw / 4) * std::max(1u, ih / 4) * blocklen;
			glCompressedTexImage2D(GL_TEXTURE_2D, i, iformat, iw, ih, 0, ilen, idata);
		}
		CheckForOpenGLErrors("Texture creation", error);

		idata += ilen;
		iw = std::max(1u, iw / 2);
		ih = std::max(1u, ih / 2);
	}

	// force mipmaps for GL3
	if (levels == 1)
		GenerateMipmap(GL_TEXTURE_2D);

	return true;
}
Esempio n. 11
0
bool Texture::LoadCubeVerticalCross(const std::string & path, const TextureInfo & info, std::ostream & error)
{
	SDL_Surface * surface = IMG_Load(path.c_str());
	if (!surface)
	{
		error << "Error loading texture file: " + path << std::endl;
		error << IMG_GetError() << std::endl;
		return false;
	}

	unsigned id = 0;
	glGenTextures(1, &id);
	CheckForOpenGLErrors("Cubemap ID generation", error);
	glBindTexture(GL_TEXTURE_CUBE_MAP, id);
	glEnable(GL_TEXTURE_CUBE_MAP);

	// set sampler
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	if (info.mipmap)
	{
		glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
		if (!glGenerateMipmap)
			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);
	}

	m_id = id;
	m_w = surface->w / 3;
	m_h = surface->h / 4;

	// upload texture
	unsigned bytespp = surface->format->BytesPerPixel;
	std::vector<unsigned char> cubeface(m_w * m_h * bytespp);
	for (int i = 0; i < 6; ++i)
	{
		// detect channels
		int format = GL_RGB;
		switch (bytespp)
		{
			case 1:
				format = GL_LUMINANCE;
				break;
			case 2:
				format = GL_LUMINANCE_ALPHA;
				break;
			case 3:
				format = GL_RGB;
				break;
			case 4:
				format = GL_RGBA;
				break;
			default:
				error << "Texture has unknown format: " + path << std::endl;
				return false;
				break;
		}

		int offsetx = 0;
		int offsety = 0;

		GLenum targetparam;
		if (i == 0)
		{
			targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
			offsetx = 0;
			offsety = m_h;
		}
		else if (i == 1)
		{
			targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
			offsetx = m_w*2;
			offsety = m_h;
		}
		else if (i == 2)
		{
			targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
			offsetx = m_w;
			offsety = m_h*2;
		}
		else if (i == 3)
		{
			targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
			offsetx = m_w;
			offsety = 0;
		}
		else if (i == 4)
		{
			targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
			offsetx = m_w;
			offsety = m_h*3;
		}
		else if (i == 5)
		{
			targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
			offsetx = m_w;
			offsety = m_h;
		}
		else
		{
			error << "Texture has unknown format: " + path << std::endl;
			return false;
		}

		if (i == 4) //special case for negative z
		{
			for (unsigned yi = 0; yi < m_h; yi++)
			{
				for (unsigned xi = 0; xi < m_w; xi++)
				{
					for (unsigned ci = 0; ci < bytespp; ci++)
					{
						int idx1 = ((m_h - yi - 1) + offsety) * surface->w * bytespp + (m_w - xi - 1 + offsetx) * bytespp + ci;
						int idx2 = yi * m_w * bytespp + xi * bytespp + ci;
						cubeface[idx2] = ((unsigned char *)(surface->pixels))[idx1];
					}
				}
			}
		}
		else
		{
			for (unsigned yi = 0; yi < m_h; yi++)
			{
				for (unsigned xi = 0; xi < m_w; xi++)
				{
					for (unsigned ci = 0; ci < bytespp; ci++)
					{
						int idx1 = (yi + offsety) * surface->w * bytespp + (xi + offsetx) * bytespp + ci;
						int idx2 = yi * m_w * bytespp + xi * bytespp + ci;
						cubeface[idx2] = ((unsigned char *)(surface->pixels))[idx1];
					}
				}
			}
		}
		glTexImage2D(targetparam, 0, format, m_w, m_h, 0, format, GL_UNSIGNED_BYTE, &cubeface[0]);
	}

	if (info.mipmap)
		GenerateMipmap(GL_TEXTURE_CUBE_MAP);

	glDisable(GL_TEXTURE_CUBE_MAP);

	CheckForOpenGLErrors("Cubemap creation", error);

	SDL_FreeSurface(surface);

	return true;
}
Esempio n. 12
0
bool Texture::LoadCube(const std::string & path, const TextureInfo & info, std::ostream & error)
{
	if (info.verticalcross)
	{
		return LoadCubeVerticalCross(path, info, error);
	}

	std::string cubefiles[6];
	cubefiles[0] = path+"-xp.png";
	cubefiles[1] = path+"-xn.png";
	cubefiles[2] = path+"-yn.png";
	cubefiles[3] = path+"-yp.png";
	cubefiles[4] = path+"-zn.png";
	cubefiles[5] = path+"-zp.png";

	unsigned id = 0;
	glGenTextures(1, &id);
	CheckForOpenGLErrors("Cubemap texture ID generation", error);
	glBindTexture(GL_TEXTURE_CUBE_MAP, id);
	m_id = id;

	for (int i = 0; i < 6; ++i)
	{
		SDL_Surface * surface = IMG_Load(cubefiles[i].c_str());
		if (!surface)
		{
			error << "Error loading texture file: " + path + " (" + cubefiles[i] + ")" << std::endl;
			error << IMG_GetError() << std::endl;
			return false;
		}

		// store dimensions
		if (i != 0 && ((m_w != (unsigned)surface->w) || (m_h != (unsigned)surface->h)))
		{
			error << "Cube map sides aren't equal sizes" << std::endl;
			return false;
		}
		m_w = surface->w;
		m_h = surface->h;

		// detect channels
		int format = GL_RGB;
		switch (surface->format->BytesPerPixel)
		{
			case 1:
				format = GL_LUMINANCE;
				break;
			case 2:
				format = GL_LUMINANCE_ALPHA;
				break;
			case 3:
				format = GL_RGB;
				break;
			case 4:
				format = GL_RGBA;
				break;
			default:
				error << "Texture has unknown format: " + path + " (" + cubefiles[i] + ")" << std::endl;
				return false;
				break;
		}

		// Create MipMapped Texture
		GLenum targetparam;
		if (i == 0)
			targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
		else if (i == 1)
			targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
		else if (i == 2)
			targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
		else if (i == 3)
			targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
		else if (i == 4)
			targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
		else if (i == 5)
			targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
		else
		{
			error << "Iterated too far: " + path + " (" + cubefiles[i] + ")" << std::endl;
			assert(0);
		}

		glTexImage2D(targetparam, 0, format, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels );

		SDL_FreeSurface(surface);
	}

	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	glDisable(GL_TEXTURE_CUBE_MAP);

	CheckForOpenGLErrors("Cubemap creation", error);

	return true;
}
Esempio n. 13
0
bool Texture::Load(const std::string & path, const TextureInfo & info, std::ostream & error)
{

	if (texid)
	{
		error << "Tried to double load texture " << path << std::endl;
		return false;
	}

	if (!info.data && path.empty())
	{
		error << "Tried to load a texture with an empty name" << std::endl;
		return false;
	}

	if (!info.data && LoadDDS(path, info, error))
	{
		return true;
	}

	if (info.cube)
	{
		return LoadCube(path, info, error);
	}

	SDL_Surface * surface = 0;
	if (info.data)
	{
		Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
		rmask = 0xff000000;
		gmask = 0x00ff0000;
		bmask = 0x0000ff00;
		amask = 0x000000ff;
#else
		rmask = 0x000000ff;
		gmask = 0x0000ff00;
		bmask = 0x00ff0000;
		amask = 0xff000000;
#endif
		surface = SDL_CreateRGBSurfaceFrom(
			info.data, info.width, info.height,
			info.bytespp * 8, info.width * info.bytespp,
			rmask, gmask, bmask, amask);
	}
	else
	{
		surface = IMG_Load(path.c_str());
	}

	if (!surface)
	{
		error << "Error loading texture file: " << path << std::endl;
		error << IMG_GetError() << std::endl;
		return false;
	}

	const unsigned char * pixels = (const unsigned char *)surface->pixels;
	const unsigned bytespp = surface->format->BytesPerPixel;
	unsigned pitch = surface->pitch;
	unsigned w = surface->w;
	unsigned h = surface->h;

	// downsample if requested by application
	std::vector<unsigned char> pixelsd;
	unsigned wd = w;
	unsigned hd = h;
	if (info.maxsize == TextureInfo::SMALL)
	{
		if (w > 256)
			wd = w / 4;
		else if (w > 128)
			wd = w / 2;

		if (h > 256)
			hd = h / 4;
		else if (h > 128)
			hd = h / 2;
	}
	else if (info.maxsize == TextureInfo::MEDIUM)
	{
		if (w > 256)
			wd = w / 2;

		if (h > 256)
			hd = h / 2;
	}
	if (wd < w || hd < h)
	{
		pixelsd.resize(wd * hd * bytespp);

		SampleDownAvg(
			bytespp, w, h, pitch, pixels,
			wd, hd, wd * bytespp, &pixelsd[0]);

		pixels = &pixelsd[0];
		pitch = wd * bytespp;
		w = wd;
		h = hd;
	}

	// store dimensions
	width = w;
	height = h;

	target = GL_TEXTURE_2D;

	// gen texture
	glGenTextures(1, &texid);
	CheckForOpenGLErrors("Texture ID generation", error);

	// setup texture
	glBindTexture(GL_TEXTURE_2D, texid);
	SetSampler(info);

	int internalformat, format;
	GetTextureFormat(surface, info, internalformat, format);

	// upload texture data
	glTexImage2D(GL_TEXTURE_2D, 0, internalformat, w, h, 0, format, GL_UNSIGNED_BYTE, pixels);
	CheckForOpenGLErrors("Texture creation", error);

	// If we support generatemipmap, go ahead and do it regardless of the info.mipmap setting.
	// In the GL3 renderer the sampler decides whether or not to do mip filtering,
	// so we conservatively make mipmaps available for all textures.
	if (GLC_ARB_framebuffer_object)
		glGenerateMipmap(GL_TEXTURE_2D);

	SDL_FreeSurface(surface);

	return true;
}
Esempio n. 14
0
void FrameBufferObject::Init(
	GraphicsState & glstate,
	const std::vector <FrameBufferTexture*> & newtextures,
	std::ostream & error_output,
	bool force_multisample_off)
{
	CheckForOpenGLErrors("FBO init start", error_output);

	const bool verbose = false;

	if (inited)
	{
		if (verbose) error_output << "INFO: deinitializing existing FBO" << std::endl;

		DeInit();

		CheckForOpenGLErrors("FBO deinit", error_output);
	}
	inited = true;

	// need at least some textures
	assert(!newtextures.empty());
	textures = newtextures;

	width = -1;
	height = -1;
	std::vector <FrameBufferTexture*> color_textures;
	FrameBufferTexture * depth_texture = 0;
	for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++)
	{
		// ensure consistent sizes
		if (width == -1)
			width = (*i)->GetW();
		if (height == -1)
			height = (*i)->GetH();
		assert(width == int((*i)->GetW()));
		assert(height == int((*i)->GetH()));

		// separate textures by type
		if ((*i)->GetFormat() == FrameBufferTexture::DEPTH24)
		{
			// can't have more than one depth attachment
			assert(!depth_texture);
			depth_texture = *i;
		}
		else
		{
			color_textures.push_back(*i);
		}
	}
	if (verbose) error_output << "INFO: width " << width << ", height " << height << std::endl;
	if (verbose) error_output << "INFO: color textures: " << color_textures.size() << std::endl;
	if (verbose && depth_texture) error_output << "INFO: depth texture: 1" << std::endl;

	// can't have more than 4 color attachments
	assert(color_textures.size() < 5);

	// check for cubemaps
	for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++)
	{
		if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP)
		{
			if (verbose) error_output << "INFO: found cubemap" << std::endl;

			// can't have MRT with cubemaps
			assert(color_textures.size() == 1);

			// can't have multisample with cubemaps
			assert((*i)->GetMultiSample() == 0);

			// can't have depth texture with cubemaps
			assert(!depth_texture);
		}
	}

	// find what multisample value to use
	int multisample = 0;
	if (!color_textures.empty())
	{
		multisample = -1;
		for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++)
		{
			if (multisample == -1)
				multisample = (*i)->GetMultiSample();

			// all must have the same multisample
			assert(multisample == (*i)->GetMultiSample());
		}
	}

	if (verbose) error_output << "INFO: multisample " << multisample << " found, " << force_multisample_off << std::endl;

	if (force_multisample_off)
		multisample = 0;

	// either we have no multisample or multisample and no depth texture
	assert((multisample == 0) || ((multisample > 0) && depth_texture));

	// initialize framebuffer object
	glGenFramebuffers(1, &framebuffer_object);

	if (verbose) error_output << "INFO: generated FBO " << framebuffer_object << std::endl;

	CheckForOpenGLErrors("FBO generation", error_output);

	// bind framebuffer
	glstate.BindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);

	CheckForOpenGLErrors("FBO binding", error_output);

	if (!depth_texture)
	{
		// create depth render buffer if we're not using a depth texture
		glGenRenderbuffers(1, &depth_renderbuffer);
		glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer);

		if (verbose) error_output << "INFO: generating depth renderbuffer" << std::endl;

		CheckForOpenGLErrors("FBO renderbuffer generation", error_output);

		if (multisample > 0)
		{
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, GL_DEPTH_COMPONENT, width, height);

			if (verbose) error_output << "INFO: using multisampling for depth renderbuffer" << std::endl;
		}
		else
		{
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
		}

		CheckForOpenGLErrors("FBO renderbuffer initialization", error_output);

		// attach depth render buffer to the FBO
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_renderbuffer);

		if (verbose) error_output << "INFO: depth renderbuffer attached to FBO" << std::endl;

		CheckForOpenGLErrors("FBO renderbuffer attachment", error_output);
	}

	if (multisample > 0)
	{
		// create/attach separate multisample color buffers for each color texture
		multisample_renderbuffers.resize(color_textures.size(), 0);
		for (size_t i = 0; i < color_textures.size(); i++)
		{
			glGenRenderbuffers(1, &multisample_renderbuffers[i]);
			glBindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffers[i]);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, color_textures[i]->GetFormat(), width, height);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, multisample_renderbuffers[i]);

			if (verbose) error_output << "INFO: generating separate multisample color buffer " << i << std::endl;

			CheckForOpenGLErrors("FBO multisample color renderbuffer", error_output);
		}
	}
	else
	{
		// attach color textures to frame buffer object
		int count = 0;
		for (std::vector <FrameBufferTexture*>::iterator i = color_textures.begin(); i != color_textures.end(); i++, count++)
		{
			int attachment = GL_COLOR_ATTACHMENT0 + count;
			if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP)
			{
				// if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete
				glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->GetId(), 0);

				if (verbose) error_output << "INFO: attaching arbitrary cubemap face to color attachment " << count << std::endl;
			}
			else
			{
				glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, (*i)->GetTarget(), (*i)->GetId(), 0);

				if (verbose) error_output << "INFO: attaching texture to color attachment " << count << std::endl;
			}
			(*i)->SetAttachment(attachment);

			CheckForOpenGLErrors("FBO attachment", error_output);
		}

		if (depth_texture)
		{
			// attach depth texture to frame buffer object
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture->GetTarget(), depth_texture->GetId(), 0);
			depth_texture->SetAttachment(GL_DEPTH_ATTACHMENT);

			if (verbose) error_output << "INFO: attaching depth texture" << std::endl;
			CheckForOpenGLErrors("FBO attachment", error_output);
		}
	}

	GLenum buffers[4] = {GL_NONE, GL_NONE, GL_NONE, GL_NONE};
	{
		int count = 0;
		for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++, count++)
		{
			buffers[count] = GL_COLOR_ATTACHMENT0 + count;
		}

		glDrawBuffers(count, buffers);
		glReadBuffer(buffers[0]);

		CheckForOpenGLErrors("FBO buffer mask set", error_output);
	}

	if (verbose) error_output << "INFO: set draw buffers: " << buffers[0] << ", " << buffers[1] << ", " << buffers[2] << ", " << buffers[3] << std::endl;
	if (verbose) error_output << "INFO: set read buffer: " << buffers[0] << std::endl;

	if (!CheckStatus(error_output))
	{
		error_output << "Error initializing FBO:" << std::endl;
		int count = 0;
		for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++)
		{
			error_output << "\t" << count << ". " << TargetToString(FrameBufferTexture::Target((*i)->GetTarget()));
			error_output << ": " << FormatToString((*i)->GetFormat()) << std::endl;
			count++;
		}
		assert(0);
	}

	// explicitely unbind framebuffer object
	glstate.BindFramebuffer(GL_FRAMEBUFFER, 0);

	CheckForOpenGLErrors("FBO unbinding", error_output);

	// if multisampling is on, create another framebuffer object for the single sample version of these textures
	if (multisample > 0)
	{
		if (verbose) error_output << "INFO: creating secondary single sample framebuffer object" << std::endl;

		assert(!singlesample_framebuffer_object);
		singlesample_framebuffer_object = new FrameBufferObject();
		singlesample_framebuffer_object->Init(glstate, newtextures, error_output, true);
	}
}
void RenderInputPostprocess::Render(GraphicsState & glstate, std::ostream & error_output)
{
	assert(shader);

	CheckForOpenGLErrors("postprocess begin", error_output);

	glstate.SetColorMask(writecolor, writealpha);
	glstate.SetDepthMask(writedepth);

	if (clearcolor && cleardepth)
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	else if (clearcolor)
		glClear(GL_COLOR_BUFFER_BIT);
	else if (cleardepth)
		glClear(GL_DEPTH_BUFFER_BIT);

	shader->Enable();

	CheckForOpenGLErrors("postprocess shader enable", error_output);

	Mat4 projMatrix, viewMatrix;
	projMatrix.SetOrthographic(0, 1, 0, 1, -1, 1);
	viewMatrix.LoadIdentity();

	glMatrixMode(GL_PROJECTION);
	glLoadMatrixf(projMatrix.GetArray());

	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixf(viewMatrix.GetArray());

	glstate.SetColor(1,1,1,1);

	SetBlendMode(glstate);

	if (writedepth || depth_mode != GL_ALWAYS)
		glstate.Enable(GL_DEPTH_TEST);
	else
		glstate.Disable(GL_DEPTH_TEST);
	glDepthFunc( depth_mode );
	glstate.Enable(GL_TEXTURE_2D);

	glActiveTexture(GL_TEXTURE0);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
	glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);

	CheckForOpenGLErrors("postprocess flag set", error_output);


	float maxu = 1.f;
	float maxv = 1.f;

	int num_nonnull = 0;
	for (unsigned int i = 0; i < source_textures.size(); i++)
	{
		//std::cout << i << ": " << source_textures[i] << std::endl;
		glActiveTexture(GL_TEXTURE0+i);
		if (source_textures[i])
		{
			source_textures[i]->Activate();
			num_nonnull++;
			if (source_textures[i]->IsRect())
			{
				maxu = source_textures[i]->GetW();
				maxv = source_textures[i]->GetH();
			}
		}
	}
	if (source_textures.size() && !num_nonnull)
	{
		error_output << "Out of the " << source_textures.size() << " input textures provided as inputs to this postprocess stage, zero are available. This stage will have no effect." << std::endl;
		return;
	}
	glActiveTexture(GL_TEXTURE0);

	CheckForOpenGLErrors("postprocess texture set", error_output);

	// build the frustum corners
	float ratio = w/h;
	std::vector <Vec3 > frustum_corners(4);
	frustum_corners[0].Set(-lod_far,-lod_far,-lod_far);	//BL
	frustum_corners[1].Set(lod_far,-lod_far,-lod_far);	//BR
	frustum_corners[2].Set(lod_far,lod_far,-lod_far);	//TR
	frustum_corners[3].Set(-lod_far,lod_far,-lod_far);	//TL
	Mat4 inv_proj;
	inv_proj.InvPerspective(camfov, ratio, 0.1, lod_far);
	for (int i = 0; i < 4; i++)
	{
		inv_proj.TransformVectorOut(frustum_corners[i][0], frustum_corners[i][1], frustum_corners[i][2]);
		frustum_corners[i][2] = -lod_far;
	}
	// frustum corners in world space for dynamic sky shader
	std::vector <Vec3 > frustum_corners_w(4);
	Mat4 inv_view_rot;
	(-cam_rotation).GetMatrix4(inv_view_rot);
	for (int i = 0; i < 4; i++)
	{
		frustum_corners_w[i] = frustum_corners[i];
		inv_view_rot.TransformVectorOut(frustum_corners_w[i][0], frustum_corners_w[i][1], frustum_corners_w[i][2]);
	}

	// send shader parameters
	{
		Vec3 lightvec = lightposition;
		cam_rotation.RotateVector(lightvec);
		shader->UploadActiveShaderParameter3f("directlight_eyespace_direction", lightvec);
		shader->UploadActiveShaderParameter1f("contrast", contrast);
		shader->UploadActiveShaderParameter1f("znear", 0.1);
		//std::cout << lightvec << std::endl;
		shader->UploadActiveShaderParameter3f("frustum_corner_bl", frustum_corners[0]);
		shader->UploadActiveShaderParameter3f("frustum_corner_br_delta", frustum_corners[1]-frustum_corners[0]);
		shader->UploadActiveShaderParameter3f("frustum_corner_tl_delta", frustum_corners[3]-frustum_corners[0]);
	}

	// draw a quad
	unsigned faces[2 * 3] = {
		0, 1, 2,
		2, 3, 0,
	};
	float pos[4 * 3] = {
		0.0f,  0.0f, 0.0f,
		1.0f,  0.0f, 0.0f,
		1.0f,  1.0f, 0.0f,
		0.0f,  1.0f, 0.0f,
	};
	// send the UV corners in UV set 0
	float tc0[4 * 2] = {
		0.0f, 0.0f,
		maxu, 0.0f,
		maxu, maxv,
		0.0f, maxv,
	};
	// send the frustum corners in UV set 1
	float tc1[4 * 3] = {
		frustum_corners[0][0], frustum_corners[0][1], frustum_corners[0][2],
		frustum_corners[1][0], frustum_corners[1][1], frustum_corners[1][2],
		frustum_corners[2][0], frustum_corners[2][1], frustum_corners[2][2],
		frustum_corners[3][0], frustum_corners[3][1], frustum_corners[3][2],
	};
	// fructum corners in world space in uv set 2
	float tc2[4 * 3] = {
		frustum_corners_w[0][0], frustum_corners_w[0][1], frustum_corners_w[0][2],
		frustum_corners_w[1][0], frustum_corners_w[1][1], frustum_corners_w[1][2],
		frustum_corners_w[2][0], frustum_corners_w[2][1], frustum_corners_w[2][2],
		frustum_corners_w[3][0], frustum_corners_w[3][1], frustum_corners_w[3][2],
	};

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, pos);

	glClientActiveTexture(GL_TEXTURE0);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(2, GL_FLOAT, 0, tc0);

	glClientActiveTexture(GL_TEXTURE1);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(3, GL_FLOAT, 0, tc1);

	glClientActiveTexture(GL_TEXTURE2);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(3, GL_FLOAT, 0, tc2);

	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, faces);

	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	glClientActiveTexture(GL_TEXTURE1);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	glClientActiveTexture(GL_TEXTURE0);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	glDisableClientState(GL_VERTEX_ARRAY);

	CheckForOpenGLErrors("postprocess draw", error_output);

	glstate.Enable(GL_DEPTH_TEST);
	glstate.Disable(GL_TEXTURE_2D);

	for (unsigned int i = 0; i < source_textures.size(); i++)
	{
		//std::cout << i << ": " << source_textures[i] << std::endl;
		glActiveTexture(GL_TEXTURE0+i);
		if (source_textures[i])
			source_textures[i]->Deactivate();
	}
	glActiveTexture(GL_TEXTURE0);

	CheckForOpenGLErrors("postprocess end", error_output);
}
Esempio n. 16
0
		void RenderManager::doRendering(void)
		{
			auto frameTime = omp_get_wtime();
			glm::mat4 viewMatrix = X39::Singletons::Camera::getInstance().recalculateViewPort();
			::glm::vec4 vec = ::glm::vec4(0.0f);
			float pitch = (float)::X39::Singletons::Camera::getInstance().getPitch();
			float yaw = (float)::X39::Singletons::Camera::getInstance().getYaw();
			float modificator = 0.1F;
			if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_LShift))
				modificator = 1;

			if (::X39::Singletons::Mouse::getInstance().getMode() == ::X39::Singletons::Mouse::MouseMode::Camera)
			{
				if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_W))
					vec.z -= 1 * modificator;
				if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_A))
					vec.x -= 1 * modificator;
				if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_S))
					vec.z += 1 * modificator;
				if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_D))
					vec.x += 1 * modificator;
				if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_Spacebar))
					vec.y += 1 * modificator;
				if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_LCTRL))
					vec.y -= 1 * modificator;
			}
			vec = viewMatrix * vec;
			::X39::Singletons::Camera::getInstance().addPos(::glm::vec3(vec.x, vec.y, vec.z));
#pragma endregion
			glClearColor(0.25, 0.25, 0.25, 0);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			//glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();

			glEnable(GL_DEPTH_TEST);
			glDepthFunc(GL_LEQUAL);
			glShadeModel(GL_SMOOTH);
			glEnable(GL_TEXTURE_COORD_ARRAY);
			glEnable(GL_CULL_FACE);
			glFrontFace(GL_CCW);
			glCullFace(GL_BACK);
			glEnable(GL_BLEND);
			glEnable(GL_POINT_SMOOTH);
			glEnable(GL_LINE_SMOOTH);
			//http://wiki.delphigl.com/index.php/glBlendFunc for different examples
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

			glPushMatrix();
			::X39::Singletons::MaterialManager::getInstance().loadMaterial(::X39::Singletons::MaterialManager::getInstance().getMaterialByIndex(0));
			for (auto& it : this->_entityList)
			{
				it->doRender();
			}
			glPopMatrix();

			//2D projection
			glPushMatrix();
			glLoadIdentity();
			glLoadIdentity();
			glDisable(GL_CULL_FACE);
			glClear(GL_DEPTH_BUFFER_BIT);
			glm::vec3 camPos = ::X39::Singletons::Camera::getInstance().getPos();
			char s[256];
			sprintf(s, "POS: %lf, %lf, %lf\nPITCH: %lf, YAW: %lf, ROLL %lf", camPos.x, camPos.y, camPos.z, ::X39::Singletons::Camera::getInstance().getPitch(), ::X39::Singletons::Camera::getInstance().getYaw(), ::X39::Singletons::Camera::getInstance().getRoll());
			::X39::GUI::GuiBase::drawText2D(::X39::Singletons::FontManager::getInstance().getFont(0), s, 1.5, 0, 0);

			//char s[256];
			frameTime = omp_get_wtime() - frameTime;
			sprintf(s, "FPS: %i", (int)(1 / frameTime));
			::X39::GUI::GuiBase::drawText2D(::X39::Singletons::FontManager::getInstance().getFont(0), s, 1.5, 0, 500);
			//::X39::GUI::GuiBase::drawText2D(::X39::Singletons::FontManager::getInstance().getFont(0), "abcdefghijklm\nnopqrstuvwxyz\nABCDEFGHIJKLM\nNOPQRSTUVWXYZ\n1234567890", 10, 0, 0);

			//::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'A', 0, 0, 200, 200);
			//::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'B', 200, 0, 200, 200);
			//::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'C', 200, 200, 200, 200);
			//::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'D', 0, 200, 200, 200);

			//::X39::Singletons::FontManager::getInstance().fontShader.use();
			//::X39::GUI::GuiBase::drawTexture2D(
			//	::X39::Singletons::FontManager::getInstance().getFont(0)->material,
			//	::X39::Singletons::FontManager::getInstance().getCharTextureIndex(::X39::Singletons::FontManager::getInstance().getFont(0), 'A'),
			//	0, 0, 16, 16,
			//	0, 0, 256, 256,
			//	::X39::Singletons::FontManager::getInstance().fontShader
			//);
			//::X39::Singletons::FontManager::getInstance().fontShader.unuse();
			if (::X39::GlobalObject::getInstance().mainDisplay)
				::X39::GlobalObject::getInstance().mainDisplay->draw();
			glPopMatrix();

			SwapBuffers(::X39::GlobalObject::getInstance().handleDeviceContext);
			CheckForOpenGLErrors();
		}
Esempio n. 17
0
void GraphicsGL2::EndScene(std::ostream & error_output)
{
	CheckForOpenGLErrors("EndScene", error_output);
}
Esempio n. 18
0
bool GraphicsGL2::EnableShaders(std::ostream & info_output, std::ostream & error_output)
{
	CheckForOpenGLErrors("EnableShaders: start", error_output);

	// unload shaders
	glUseProgramObjectARB(0);
	shaders.clear();
	CheckForOpenGLErrors("EnableShaders: shader unload", error_output);

	// unload inputs/outputs
	render_outputs.clear();
	texture_outputs.clear();
	texture_inputs.clear();
	CheckForOpenGLErrors("EnableShaders: FBO deinit", error_output);

	// reload configuration
	config = GraphicsConfig();
	std::string rcpath = shaderpath + "/" + renderconfigfile;
	if (!config.Load(rcpath, error_output))
	{
		error_output << "EnableShaders: Error loading render configuration file: " << rcpath << std::endl;
		return false;
	}

	bool ssao = (lighting > 0);
	bool ssao_low = (lighting == 1);
	bool ssao_high = (lighting == 2);
	bool reflection_disabled = (reflection_status == REFLECTION_DISABLED);
	bool reflection_dynamic = (reflection_status == REFLECTION_DYNAMIC);
	bool shadows_near = shadows;
	bool shadows_medium = shadows && shadow_distance > 0;
	bool shadows_far = shadows && shadow_distance > 1;
	bool shadow_quality_low = shadows && (shadow_quality == 0);
	bool shadow_quality_medium = shadows && (shadow_quality == 1);
	bool shadow_quality_high = shadows && (shadow_quality == 2);
	bool shadow_quality_vhigh = shadows && (shadow_quality == 3);
	bool shadow_quality_ultra = shadows && (shadow_quality == 4);

	// for now, map vhigh and ultra to high
	shadow_quality_high = shadow_quality_high || shadow_quality_vhigh || shadow_quality_ultra;
	shadow_quality_vhigh = false;
	shadow_quality_ultra = true;

	conditions.clear();
	if (fsaa > 1) conditions.insert("fsaa");
	#define ADDCONDITION(x) if (x) conditions.insert(#x)
	ADDCONDITION(bloom);
	ADDCONDITION(normalmaps);
	ADDCONDITION(ssao);
	ADDCONDITION(ssao_low);
	ADDCONDITION(ssao_high);
	ADDCONDITION(reflection_disabled);
	ADDCONDITION(reflection_dynamic);
	ADDCONDITION(shadows_near);
	ADDCONDITION(shadows_medium);
	ADDCONDITION(shadows_far);
	ADDCONDITION(shadow_quality_low);
	ADDCONDITION(shadow_quality_medium);
	ADDCONDITION(shadow_quality_high);
	ADDCONDITION(shadow_quality_vhigh);
// 		ADDCONDITION(shadow_quality_ultra);
	ADDCONDITION(sky_dynamic);
	#undef ADDCONDITION

	// add some common textures
	if (reflection_status == REFLECTION_STATIC)
		texture_inputs["reflection_cube"] = static_reflection;
	texture_inputs["ambient_cube"] = static_ambient;

	// setup frame buffer textures
	const bool has_texture_float = GLEW_ARB_texture_float && GLEW_ARB_half_float_pixel;
	for (std::vector <GraphicsConfigOutput>::const_iterator i = config.outputs.begin(); i != config.outputs.end(); i++)
	{
		if (!i->conditions.Satisfied(conditions))
			continue;

		if (texture_outputs.find(i->name) != texture_outputs.end())
		{
			error_output << "Ignore duplicate definiion of output: " << i->name << std::endl;
			continue;
		}

		if (i->type == "framebuffer")
		{
			render_outputs[i->name].RenderToFramebuffer(w, h);
		}
		else
		{
			FrameBufferTexture::Target target = TextureTargetFromString(i->type);
			FrameBufferTexture::Format format = TextureFormatFromString(i->format);
			if (!has_texture_float && (format == FrameBufferTexture::RGBA16 || format == FrameBufferTexture::RGB16))
			{
				error_output << "Your video card doesn't support floating point textures." << std::endl;
				error_output << "Failed to load render output: " << i->name << " " << i->type << std::endl;
				return false;
			}

			// initialize fbtexture
			int multisampling = (i->multisample < 0) ? fsaa : 0;
			FrameBufferTexture & fbtex = texture_outputs[i->name];
			fbtex.Init(
				i->width.GetSize(w), i->height.GetSize(h),
				target, format, (i->filter == "nearest"), i->mipmap,
				error_output, multisampling, (i->format == "depthshadow"));

			// register texture as input
			texture_inputs[i->name] = fbtex;
		}

		info_output << "Initialized render output: " << i->name;
		info_output << (i->type != "framebuffer" ? " (FBO)" : " (framebuffer alias)") << std::endl;
	}
	render_outputs["framebuffer"].RenderToFramebuffer(w, h);

	// gen graphics config shaders map
	typedef std::map <std::string, const GraphicsConfigShader *> ConfigShaderMap;
	ConfigShaderMap config_shaders;
	for (std::vector <GraphicsConfigShader>::const_iterator s = config.shaders.begin(); s != config.shaders.end(); s++)
	{
		std::pair <ConfigShaderMap::iterator, bool> result = config_shaders.insert(std::make_pair(s->name, &*s));
		if (!result.second)
			error_output << "Ignore duplicate definition of shader: " << s->name << std::endl;
	}

	// setup frame buffer objects and shaders
	std::vector <std::string> shader_uniforms(Uniforms::str, end(Uniforms::str));
	std::vector <std::string> shader_defines;
	GetShaderDefines(shader_defines);
	for (std::vector <GraphicsConfigPass>::const_iterator i = config.passes.begin(); i != config.passes.end(); i++)
	{
		// check conditions
		if (!i->conditions.Satisfied(conditions))
			continue;

		// load pass output
		const std::string & outname = i->output;
		if (render_outputs.find(outname) == render_outputs.end())
		{
			// collect a list of textures for the outputs
			std::vector <std::string> outputs = Tokenize(outname, " ");
			std::vector <FrameBufferTexture*> fbotex;
			for (std::vector <std::string>::const_iterator o = outputs.begin(); o != outputs.end(); o++)
			{
				texture_output_map_type::iterator to = texture_outputs.find(*o);
				if (to != texture_outputs.end())
				{
					fbotex.push_back(&to->second);
				}
			}
			if (fbotex.empty())
			{
				error_output << "None of these outputs are active: " << outname << std::endl;
				return false;
			}

			// initialize fbo
			FrameBufferObject & fbo = render_outputs[outname].RenderToFBO();
			fbo.Init(glstate, fbotex, error_output);
		}

		// load pass shader
		const std::string & shadername = i->shader;
		if (shaders.find(shadername) == shaders.end())
		{
			ConfigShaderMap::const_iterator csi = config_shaders.find(shadername);
			if (csi == config_shaders.end())
			{
				error_output << "Shader not defined: " << shadername << std::endl;
				return false;
			}
			const GraphicsConfigShader * cs = csi->second;

			std::vector <std::string> defines = Tokenize(cs->defines, " ");
			defines.reserve(defines.size() + shader_defines.size());
			defines.insert(defines.end(), shader_defines.begin(), shader_defines.end());

			Shader & shader = shaders[cs->name];
			if (!shader.Load(
				shaderpath + "/" + cs->vertex,
				shaderpath + "/" + cs->fragment,
				defines, shader_uniforms,
				info_output, error_output))
			{
				return false;
			}
		}
	}

	return true;
}
Esempio n. 19
0
void GraphicsGL2::DrawScenePass(
	const GraphicsConfigPass & pass,
	std::map <std::string, PtrVector <Drawable> > & culled_static_drawlist,
	std::ostream & error_output)
{
	// log failure here?
	if (!pass.conditions.Satisfied(conditions))
		return;

	// setup shader
	shader_map_type::iterator si = shaders.find(pass.shader);
	if (si == shaders.end())
	{
		ReportOnce(&pass, "Shader " + pass.shader + " couldn't be found", error_output);
		return;
	}
	renderscene.SetShader(&si->second);

	// setup textures
	std::vector <TextureInterface*> input_textures;
	GetScenePassInputTextures(pass.inputs, input_textures);
	renderscene.SetTextures(glstate, input_textures, error_output);

	// setup state
	renderscene.SetColorMask(glstate, pass.write_color, pass.write_alpha);
	renderscene.SetDepthMode(glstate, DepthModeFromString(pass.depthtest), pass.write_depth);
	renderscene.SetBlendMode(glstate, BlendModeFromString(pass.blendmode));

	// setup output
	render_output_map_type::iterator oi = render_outputs.find(pass.output);
	if (oi == render_outputs.end())
	{
		ReportOnce(&pass, "Render output " + pass.output + " couldn't be found", error_output);
		return;
	}
	RenderOutput & output = oi->second;

	// handle the cubemap case
	const bool cubemap = (output.IsFBO() && output.RenderToFBO().IsCubemap());
	const int cubesides = cubemap ? 6 : 1;
	std::string cameraname = pass.camera;
	for (int cubeside = 0; cubeside < cubesides; cubeside++)
	{
		if (cubemap)
		{
			// build a name for the sub camera
			std::stringstream converter;
			converter << pass.camera << "_cubeside" << cubeside;
			cameraname = converter.str();

			// attach the correct cube side on the render output
			AttachCubeSide(cubeside, output.RenderToFBO(), error_output);
		}

		// setup camera
		camera_map_type::iterator ci = cameras.find(cameraname);
		if (ci == cameras.end())
		{
			ReportOnce(&pass, "Camera " + pass.camera + " couldn't be found", error_output);
			return;
		}
		renderscene.SetCamera(ci->second);

		// render pass draw layers
		output.Begin(glstate, error_output);
		renderscene.ClearOutput(glstate, pass.clear_color, pass.clear_depth);
		for (std::vector <std::string>::const_iterator d = pass.draw.begin(); d != pass.draw.end(); d++)
		{
			const std::string & layer = *d;

			// setup dynamic drawlist
			reseatable_reference <PtrVector <Drawable> > container_dynamic = dynamic_drawlist.GetByName(layer);
			if (!container_dynamic)
			{
				ReportOnce(&pass, "Drawable container " + layer + " couldn't be found", error_output);
				return;
			}

			// setup static drawlist
			const std::string drawlist_key = BuildKey(cameraname, layer);
			std::map <std::string, PtrVector <Drawable> >::const_iterator container_static = culled_static_drawlist.find(drawlist_key);
			if (container_static == culled_static_drawlist.end())
			{
				ReportOnce(&pass, "Couldn't find culled static drawlist for camera/draw combination: " + drawlist_key, error_output);
				return;
			}

			if (!container_dynamic->empty() || !container_static->second.empty())
			{
				renderscene.SetDrawLists(*container_dynamic, container_static->second);
				renderscene.Render(glstate, error_output);
			}
		}
		output.End(glstate, error_output);
		CheckForOpenGLErrors("render output end", error_output);
	}
}