Ejemplo n.º 1
0
//--------------------------------------------------------------------------------------
// Name: CreateLightingFBO()
// Desc: 
//--------------------------------------------------------------------------------------
VOID CSample::CreateLightingFBO()
{
    FreeLightingFBO();

    glGenRenderbuffers( 1, &m_hDiffuseSpecularDepthBufId );
    glBindRenderbuffer( GL_RENDERBUFFER, m_hDiffuseSpecularDepthBufId );    
    glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_nWidth, m_nHeight );

    glGenFramebuffers( 1, &m_hDiffuseSpecularBufId );
    glBindFramebuffer( GL_FRAMEBUFFER, m_hDiffuseSpecularBufId );

    glGenTextures( 1, &m_hDiffuseSpecularTexId );
    glBindTexture( GL_TEXTURE_2D, m_hDiffuseSpecularTexId );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_nWidth, m_nHeight, 0, GL_RGB, 
                  GL_UNSIGNED_BYTE, NULL );

    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, m_hDiffuseSpecularTexId );

    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_hDiffuseSpecularTexId, 0 );

    CheckFrameBufferStatus();

    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
Ejemplo n.º 2
0
bool GLVideo::BeginTargetScene(const Color& dwBGColor, const bool clear)
{
	// explicit static cast for better performance
	TexturePtr texturePtr = m_currentTarget.lock();
	if (!texturePtr)
	{
		Message(GS_L("There's no render target"), GSMT_ERROR);
	}
	Texture *pTexture = texturePtr.get(); // safety compile-time error checking
	GLTexture *pGLTexture = static_cast<GLTexture*>(pTexture); // safer direct cast
	const GLuint target = pGLTexture->GetTextureInfo().m_frameBuffer;
	glBindFramebuffer(GL_FRAMEBUFFER, target);

	CheckFrameBufferStatus(target, pGLTexture->GetTextureInfo().m_texture, false);

	if (clear)
	{
		math::Vector4 color;
		color.SetColor(dwBGColor);
		glClearColor(color.x, color.y, color.z, color.w);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

	UpdateInternalShadersViewData(GetScreenSizeF(), true);
	m_rendering = true;
	return true;
}
Ejemplo n.º 3
0
/// Creates just 1 dedicated buffer to receive the depth-data. Preferably in 32-bit floating point to ensure better quality?
bool FrameBuffer::CreateDepthBuffer(Vector2i depthBufferSize)
{
	Free();
	// Store the size here..?
	this->size = depthBufferSize;
	/// OpenGL specific data
	/// Frame buffer object for deferred shading
	/// GLuint frameBufferObject;	// Main frame buffer object to use
	/// GLuint depthBuffer;			// Depth buffer to act as Z-buffer for when parsing the input to the frame buffer
	GLuint error;
	/// Setup main Frame buffer object
	if (frameBufferObject == -1)
		frameBufferObject = GLFrameBuffers::New();
	error = glGetError();

	/// Bind it for manipulatoin.
	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);
	AssertGLError("FrameBuffer::CreateRenderBuffers");
	/// Establish some variables before we try tweaking properties..
	Vector2i textureSize = size;
	
	// Delete the old buffers as needed.
	renderBuffers.ClearAndDelete();	
	
	// Create the buffers.
	RenderBuffer * depthBuf = new RenderBuffer("Depth", BufferType::DEPTH_BUFFER, BufferStorageType::DEPTH_32F, textureSize);
	renderBuffers.Add(depthBuf);

	// Bind to 0 when done.
	glBindRenderbuffer(GL_RENDERBUFFER, 0);	
	AssertGLError("FrameBuffer::CreateRenderBuffers");
	CreateTexturesAndBind();
	int frameBufferColorAttachmentsSet = 7;

	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Check that status of our generated frame buffer
	AssertGLError("FrameBuffer::CreateRenderBuffers");
	
	// Check that frame buffer is okay to work on.
	status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
	if (!CheckFrameBufferStatus(status, name))
		return false;

	/// Only have frame buffer parameters in OpenGL 4.3 core and above...
	if (GL_VERSION_MAJOR >= 4 && GL_VERSION_MINOR >= 3){
		/// Set frame buffer parameters
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 512);
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 512);
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 4);
		error = glGetError();
	}
	// Unbind our frame buffer object, along with its attached render buffers
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	AssertGLError("FrameBuffer::CreateRenderBuffers");	
	// Ok!
	good = true;
	return true;
}
Ejemplo n.º 4
0
/// Creates a default set of render-buffers for deferred rendering. Included: diffuse, normal, position, specular, emissive (all triple-vectors) + a depth buffer.   
bool FrameBuffer::CreateDeferredBuffers(Vector2i inSize)
{
	Free();
	this->size = inSize;
	/// OpenGL specific data
	if (frameBufferObject == -1)
		frameBufferObject = GLFrameBuffers::New();
	int error = glGetError();
	/// Bind it for manipulatoin.
	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);
	AssertGLError("FrameBuffer::CreateRenderBuffers");
	/// Establish some variables before we try tweaking properties..
	Vector2i textureSize = size;	
	// Delete the old buffers as needed.
	renderBuffers.ClearAndDelete();	
	// Add the depth-buffer.
	renderBuffers.AddItem(new RenderBuffer("Depth", BufferType::DEPTH_BUFFER, BufferStorageType::DEPTH_24F, textureSize));
	// Create the buffers.
	RenderBuffer * diffBuf = new RenderBuffer("Diffuse", BufferType::COLOR_BUFFER_1, ColorStorageType(), textureSize);
	renderBuffers.AddItem(diffBuf);
	renderBuffers.Add(new RenderBuffer("Normal", BufferType::COLOR_BUFFER_2, BufferStorageType::RGB_16F, textureSize),
		new RenderBuffer("Position", BufferType::COLOR_BUFFER_3, BufferStorageType::RGB_32F, textureSize),
		new RenderBuffer("Specular", BufferType::COLOR_BUFFER_4, BufferStorageType::RGB_32F, textureSize),
		new RenderBuffer("Emissive", BufferType::COLOR_BUFFER_5, BufferStorageType::RGB_32F, textureSize));

	// Bind to 0 when done.
	glBindRenderbuffer(GL_RENDERBUFFER, 0);	
	AssertGLError("FrameBuffer::CreateRenderBuffers");
	CreateTexturesAndBind();
	int frameBufferColorAttachmentsSet = renderBuffers.Size();

	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Check that status of our generated frame buffer
	AssertGLError("FrameBuffer::CreateRenderBuffers");
	
	// Check that frame buffer is okay to work on.
	status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
	if (!CheckFrameBufferStatus(status, name))
		return false;

	/// Only have frame buffer parameters in OpenGL 4.3 core and above...
	if (GL_VERSION_MAJOR >= 4 && GL_VERSION_MINOR >= 3){
		/// Set frame buffer parameters
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 512);
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 512);
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 4);
		error = glGetError();
	}
	// Unbind our frame buffer object, along with its attached render buffers
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	AssertGLError("FrameBuffer::CreateRenderBuffers");	
	// Ok!
	good = true;
	return true;
}
Ejemplo n.º 5
0
//--------------------------------------------------------------------------------------
// Name: InitOffScreenFramebuffer()
// Desc: Initializes off-screen framebuffer color attachment.
//--------------------------------------------------------------------------------------
void CSample::InitOffScreenFramebuffer(unsigned int n_texture_to_use)
{
    glBindFramebuffer     (GL_DRAW_FRAMEBUFFER,
                           m_fboId);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
                           GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D_MULTISAMPLE,
                           g_textures[n_texture_to_use].texture,
                           0); /* level */

    if( TRUE != CheckFrameBufferStatus() )
        return;
}
Ejemplo n.º 6
0
BOOL CSample::CreateDrawBuffers()
{
	FreeDrawBuffers();
	
	glGenFramebuffers(1, &m_hFrameBufferNameId);
	glBindFramebuffer(GL_FRAMEBUFFER, m_hFrameBufferNameId);
	
	glGenTextures( 1, &( m_pTextureIds[ CEL_SHADED_FBO ] ) );
	glBindTexture( GL_TEXTURE_2D, m_pTextureIds[ CEL_SHADED_FBO ] );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_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 );
	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_nFBOTextureWidth, m_nFBOTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );

	glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureIds[ CEL_SHADED_FBO ], 0 );
	
	glGenTextures( 1, &( m_pTextureIds[ NORMAL_AND_DEPTH_FBO ] ) );
	glBindTexture( GL_TEXTURE_2D, m_pTextureIds[ NORMAL_AND_DEPTH_FBO ] );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_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 );
	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_nFBOTextureWidth, m_nFBOTextureHeight,0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );

	glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_pTextureIds[ NORMAL_AND_DEPTH_FBO ], 0 );

	glGenTextures( 1, &m_hDepthbufferId);
	glBindTexture( GL_TEXTURE_2D, m_hDepthbufferId);
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_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);
	glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_nFBOTextureWidth, m_nFBOTextureHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );

	glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_hDepthbufferId, 0);
	glFramebufferTexture2D( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_hDepthbufferId, 0);

	if( FALSE == CheckFrameBufferStatus() )
		return FALSE;
	

	glBindTexture(GL_TEXTURE_2D, 0);
	glBindFramebuffer( GL_FRAMEBUFFER, 0 );

	return TRUE;
}
Ejemplo n.º 7
0
bool GLES2Texture::CreateRenderTarget(
	VideoWeakPtr video,
	const unsigned int width,
	const unsigned int height,
	const Texture::TARGET_FORMAT fmt)
{
	m_textureInfo.m_texture = m_textureID++;

	SetTexture(0);

	const GLint glfmt = (fmt == Texture::TF_ARGB) ? GL_RGBA : GL_RGB;

	glTexImage2D(GL_TEXTURE_2D, 0, glfmt,
		static_cast<GLsizei>(width), static_cast<GLsizei>(height),
		0, static_cast<GLenum>(glfmt), (fmt == Texture::TF_ARGB) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5, NULL);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	// attach 2D texture
	glGenFramebuffers(1, &m_textureInfo.m_frameBuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, m_textureInfo.m_frameBuffer);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureInfo.m_texture, 0);

	// create depth buffer... removed for now... will be back whenever it's needed
	/*GLuint depthRenderbuffer;
	glGenRenderbuffers(1, &depthRenderbuffer);
	glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);*/

	CheckFrameBufferStatus(m_logger, m_textureInfo.m_frameBuffer, m_textureInfo.m_texture, true);
	UnbindFrameBuffer();

	m_type = TT_RENDER_TARGET;
	m_profile.width = width;
	m_profile.height = height;
	m_profile.originalWidth = m_profile.width;
	m_profile.originalHeight = m_profile.height;

	GLES2UniformParameter::m_boundTexture2D = 0;
	glBindTexture(GL_TEXTURE_2D, 0);
	return true;
}
Ejemplo n.º 8
0
/// Creates a default set of render-buffers for the output of rendering (deferred or otherwise), including color (diffuse) and depth.
bool FrameBuffer::CreateDeferredOutputBuffers(Vector2i inSize)
{
	Free();
	this->size = inSize;
	/// OpenGL specific data
	if (frameBufferObject == -1)
		frameBufferObject = GLFrameBuffers::New();
	int error = glGetError();
	/// Bind it for manipulatoin.
	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);
	AssertGLError("FrameBuffer::CreateDeferredOutputBuffers");
	Vector2i textureSize = size;
	renderBuffers.ClearAndDelete();	
	renderBuffers.AddItem(new RenderBuffer("Depth", BufferType::DEPTH_BUFFER, BufferStorageType::DEPTH_24F, textureSize));
	RenderBuffer * diffBuf = new RenderBuffer("Diffuse", BufferType::COLOR_BUFFER_1, ColorStorageType(), textureSize);
	renderBuffers.AddItem(diffBuf);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);	
	AssertGLError("FrameBuffer::CreateDeferredOutputBuffers");
	CreateTexturesAndBind();
	int frameBufferColorAttachmentsSet = renderBuffers.Size();

	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Check that status of our generated frame buffer
	AssertGLError("FrameBuffer::CreateRenderBuffers");
	
	// Check that frame buffer is okay to work on.
	status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
	if (!CheckFrameBufferStatus(status, name))
		return false;

	/// Only have frame buffer parameters in OpenGL 4.3 core and above...
	if (GL_VERSION_MAJOR >= 4 && GL_VERSION_MINOR >= 3){
		/// Set frame buffer parameters
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 512);
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 512);
	//	glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 4);
		error = glGetError();
	}
	// Unbind our frame buffer object, along with its attached render buffers
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	AssertGLError("FrameBuffer::CreateRenderBuffers");	
	// Ok!
	good = true;
	return true;
}
Ejemplo n.º 9
0
/// Yas. Only inherits main stats of the other buffer, keeps size.
bool FrameBuffer::CreateBuffersLikeIn(FrameBuffer * otherBuffer)
{
	Free();
	/// OpenGL specific data
	if (frameBufferObject == -1)
		frameBufferObject = GLFrameBuffers::New();
	int error = glGetError();
	/// Bind it for manipulatoin.
	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);
	AssertGLError("FrameBuffer::CreateBuffersLikeIn");
	Vector2i textureSize = size;
	renderBuffers.ClearAndDelete();	
	/// Create render buffers.
	for (int i = 0; i < otherBuffer->renderBuffers.Size(); ++i)
	{
		RenderBuffer * ref = otherBuffer->renderBuffers[i];
		if (ref->type == BufferType::DEPTH_BUFFER && skipDepthBuffers)
			continue;
		RenderBuffer * newOne = new RenderBuffer(ref->name, ref->type, ref->storageType, textureSize);
		renderBuffers.AddItem(newOne);
		glBindRenderbuffer(GL_RENDERBUFFER, 0);	
	}

	AssertGLError("FrameBuffer::CreateBuffersLikeIn");
	CreateTexturesAndBind();
	int frameBufferColorAttachmentsSet = renderBuffers.Size();

	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Check that status of our generated frame buffer
	AssertGLError("FrameBuffer::CreateBuffersLikeIn");
	
	// Check that frame buffer is okay to work on.
	status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
	if (!CheckFrameBufferStatus(status, name))
		return false;

	// Unbind our frame buffer object, along with its attached render buffers
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	AssertGLError("FrameBuffer::CreateBuffersLikeIn");	
	// Ok!
	good = true;
	return true;
}
Ejemplo n.º 10
0
//--------------------------------------------------------------------------------------
// Name: CreateShadowMapFBO()
// Desc: 
//--------------------------------------------------------------------------------------
VOID CSample::CreateShadowMapFBO()
{
    FreeShadowMapFBO();

    // Create shadow texture
    {   
        glGenTextures( 1, &m_hShadowMapTexId );
        glBindTexture( GL_TEXTURE_2D, m_hShadowMapTexId );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE );
        
        // Setup hardware comparison
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
        
        glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 
                  m_nShadowMapFBOTextureWidth, m_nShadowMapFBOTextureHeight, 
                  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL );
    }

    glGenFramebuffers( 1, &m_hShadowMapBufId );
    glBindFramebuffer( GL_FRAMEBUFFER, m_hShadowMapBufId );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_hShadowMapTexId, 0 );


	//ATI cards need you to specify no color attached
	GLenum noColorAttach = GL_NONE;
	glDrawBuffers( 1, &noColorAttach );

    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, m_hShadowMapTexId );
 
    CheckFrameBufferStatus();

    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
Ejemplo n.º 11
0
Archivo: main.c Proyecto: farosis/gfx
void InitGLES(void)
{
  GLint linked;
  GLuint vertexShader;
  GLuint fragmentShader;
  assert((vertexShader = LoadShader("vert.glsl", GL_VERTEX_SHADER)) != 0);
  assert((fragmentShader = LoadShader("frag.glsl", GL_FRAGMENT_SHADER)) != 0);
  assert((program = glCreateProgram()) != 0);
  glAttachShader(program, vertexShader);
  glAttachShader(program, fragmentShader);
  glLinkProgram(program);
  glGetProgramiv(program, GL_LINK_STATUS, &linked);
  if (!linked) {
    GLint infoLen = 0;
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
    if (infoLen > 1) {
      char *infoLog = malloc(infoLen);
      glGetProgramInfoLog(program, infoLen, NULL, infoLog);
      fprintf(stderr, "Error linking program:\n%s\n", infoLog);
      free(infoLog);
    }
    glDeleteProgram(program);
    exit(1);
  }

  //*
  GLuint fbid;
  glGenFramebuffers(1, &fbid);
  glBindFramebuffer(GL_FRAMEBUFFER, fbid);

  GLuint texid;
  glGenTextures(1, &texid);
  glBindTexture(GL_TEXTURE_2D, texid);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  #ifdef _OGLES_30_
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, TARGET_SIZE, TARGET_SIZE, 0, GL_RGBA, GL_FLOAT, NULL);
  #endif
  #ifdef _OGLES_20_
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TARGET_SIZE, TARGET_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  #endif
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texid, 0);

  GLuint rbid;
  glGenRenderbuffers(1, &rbid);
  glBindRenderbuffer(GL_RENDERBUFFER, rbid);
  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, TARGET_SIZE, TARGET_SIZE);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbid);

  CheckFrameBufferStatus();
  //*/

  glClearColor(0, 0, 0, 0);
  glViewport(0, 0, TARGET_SIZE, TARGET_SIZE);
  glEnable(GL_DEPTH_TEST);

  glUseProgram(program);
}