Ejemplo n.º 1
0
void		draw() {

	fbo1.draw(render_tri);
	fbo2.draw(render_quad);

	// render to screen

	prep_ortho();

	//render();

	switch(mode) {
		case 1:
			render_tri();
			break;
		case 2:
			render_quad();
			break;
		case 3:
			render_from_texture();
			break;
	}

	glfwSwapBuffers(window);
	glfwPollEvents();

}
Ejemplo n.º 2
0
bool GraphicsContext3DInternal::paintCompositedResultsToCanvas(CanvasRenderingContext* context)
{
    LOGWEBGL("paintCompositedResultsToCanvas()");
    ImageBuffer* imageBuffer = context->canvas()->buffer();
    const SkBitmap& canvasBitmap =
        imageBuffer->context()->platformContext()->recordingCanvas()->getDevice()->accessBitmap(false);
    SkCanvas canvas(canvasBitmap);

    MutexLocker lock(m_fboMutex);

    FBO* fbo = m_frontFBO;
    if (!fbo)
        return false;

    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kARGB_8888_Config, m_width, m_height, fbo->bytesPerRow());

    unsigned char* bits = NULL;
    if (fbo->lockGraphicBuffer((void**)&bits)) {
        bitmap.setPixels(bits);

        SkRect  dstRect;
        dstRect.iset(0, 0, imageBuffer->size().width(), imageBuffer->size().height());
        canvas.save();
        canvas.translate(0, SkIntToScalar(imageBuffer->size().height()));
        canvas.scale(SK_Scalar1, -SK_Scalar1);
        canvas.drawBitmapRect(bitmap, 0, dstRect);
        canvas.restore();
        bitmap.setPixels(0);
        fbo->unlockGraphicBuffer();
    }

    return true;
}
Ejemplo n.º 3
0
PassRefPtr<ImageData> GraphicsContext3DInternal::paintRenderingResultsToImageData()
{
    LOGWEBGL("paintRenderingResultsToImageData()");

    // Reading premultiplied alpha would involve unpremultiplying, which is lossy.
    if (m_attrs.premultipliedAlpha)
        return 0;

    RefPtr<ImageData> imageData = ImageData::create(IntSize(m_width, m_height));
    unsigned char* pixels = imageData->data()->data()->data();
    //[CAPPFIX_WEB_WEBGL] - better performance
    if (m_canvasDirty) {
        glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    } else {
        LOGWEBGL("paintRenderingResultsToImageData() >>> from clean canvas, so read the back buffer >>> m_canvasDirty:%d", m_canvasDirty);
        unsigned char* bits;
        MutexLocker lock(m_fboMutex);

        FBO* fbo = m_frontFBO;
        if (!fbo)
            return NULL;

        if (fbo->lockGraphicBuffer((void**)&bits)) {
            memcpy(pixels, bits, (m_width * m_height * 4));
            fbo->unlockGraphicBuffer();
        }
    }
    LOGWEBGL("-paintRenderingResultsToImageData()");
    // [CAPPFIX_WEB_WEBGL_END]
    return imageData;
}
Ejemplo n.º 4
0
bool GraphicsContext3DInternal::lockFrontBuffer(T& image, SkRect& rect)
{
    LOGWEBGL("GraphicsContext3DInternal::lockFrontBuffer()");
    MutexLocker lock(m_fboMutex);
    FBO* fbo = m_frontFBO;

    if (!fbo || !fbo->image()) {
        LOGWEBGL("-GraphicsContext3DInternal::lockFrontBuffer(), fbo = %p", fbo);
        return false;
    }

    fbo->setLocked(true);
    image = (T)(fbo->image());

    RenderObject* renderer = m_canvas->renderer();
    if (renderer && renderer->isBox()) {
        RenderBox* box = (RenderBox*)renderer;
        rect.setXYWH(box->borderLeft() + box->paddingLeft(),
                     box->borderTop() + box->paddingTop(),
                     box->contentWidth(),
                     box->contentHeight());
    }

    return true;
}
Ejemplo n.º 5
0
int LuaFBOs::DeleteFBO(lua_State* L)
{
	if (lua_isnil(L, 1)) {
		return 0;
	}
	FBO* fbo = (FBO*)luaL_checkudata(L, 1, "FBO");
	fbo->Free(L);
	return 0;
}
Ejemplo n.º 6
0
int LuaFBOs::DeleteFBO(lua_State* L)
{
	if (lua_isnil(L, 1)) {
		return 0;
	}
	FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
	fbo->Free(L);
	return 0;
}
Ejemplo n.º 7
0
void Renderer::renderDeferredShading()
{
  if (!m_shaderDSLighting || !m_shaderDSCompositing)
    init(m_windowWidth, m_windowHeight);

  if (!m_dsLightColor || !m_dsLightRootNode)
    throw std::string("Error in renderDeferredShading - Light Color or Light Root Node was not set");

  FBO *a = new FBO(m_windowWidth,m_windowHeight,3,false,false);

  a->bind();

  glCullFace(GL_FRONT);
  glEnable(GL_CULL_FACE);
  glDisable(GL_DEPTH_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_ONE, GL_ONE);
  glClearColor(0, 0, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  m_shaderDSLighting->bind();

  m_shaderDSLighting->sendMat4("viewMatrix", m_currentViewMatrix);
  m_shaderDSLighting->sendMat4("projectionMatrix", m_currentProjectionMatrix);

  m_shaderDSLighting->sendSampler2D("positionMap", m_gBuffer->getColorTexture(0), 0);
  m_shaderDSLighting->sendSampler2D("normalMap", m_gBuffer->getColorTexture(1), 1);

  m_shaderDSLighting->sendInt("windowWidth", m_windowWidth);
  m_shaderDSLighting->sendInt("windowHeight", m_windowHeight);

  m_shaderDSLighting->sendVec3("lightColor", *m_dsLightColor);

  m_dsLightRootNode->render(*m_shaderDSLighting);

  glDisable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);
  glDisable(GL_BLEND);
  glClearColor(1.0, 1.0, 1.0, 0.0);
  m_shaderDSLighting->unbind();
  a->unbind();

  //COMPOSITING TEIL ===============================
  bindFBO();
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  m_shaderDSCompositing->bind();

  m_shaderDSCompositing->sendSampler2D("colorMap", getLastFBO()->getColorTexture(2), 0);
  m_shaderDSCompositing->sendSampler2D("lightMap", a->getColorTexture(2), 1);

  m_sfq.renderGeometry();

  m_shaderDSCompositing->unbind();
  unbindFBO();

  delete a;
}
Ejemplo n.º 8
0
 void onFrame(){
   
   model = glm::mat4(1.0);
   
   vec3 totals = rotateBehavior.tick(now()).totals();
   model = glm::rotate(model, totals.x, vec3(1.0f,0.0f,0.0f));
   model = glm::rotate(model, totals.y, vec3(0.0f,1.0f,0.0f));
   model = glm::rotate(model, totals.z, vec3(0.0f,0.0f,1.0f));
   
   
   //draw cube 1 into an offscreen texture
   fbo.bind(); {
     glViewport(0, 0, fbo.width, fbo.height);
     glClearColor(0.1,0.1,0.1,1.0);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
     draw(model, cubeMeshBuffer1, texture, textureProgram);
     
   } fbo.unbind();
   
   
   //draw cube 2 with the offscreen texture using phong shading
   glViewport(0, 0, width, height);
   glClearColor(0.0,0.0,0.0,1.0);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
   model = glm::mat4(1.0);
   
   model = glm::translate(model, vec3(1.0,0.0,0.0));
   model = glm::rotate(model, totals.x, vec3(1.0f,0.0f,0.0f));
   model = glm::rotate(model, totals.y, vec3(0.0f,1.0f,0.0f));
   model = glm::rotate(model, totals.z, vec3(0.0f,0.0f,1.0f));
   
   draw(model, cubeMeshBuffer2, fbo.texture, phongProgram);
   
   
   
   //draw cube 3 - a colored cube
   
   model = mat4(1.0);
   model = glm::translate(model, vec3(-1.0,0.0,0.0));
   
   model = glm::rotate(model, -totals.x, vec3(1.0f,0.0f,0.0f));
   model = glm::rotate(model, -totals.y, vec3(0.0f,1.0f,0.0f));
   model = glm::rotate(model, -totals.z, vec3(0.0f,0.0f,1.0f));
   
   programColor.bind(); {
     glUniformMatrix4fv(programColor.uniform("model"), 1, 0, ptr(model));
     glUniformMatrix4fv(programColor.uniform("view"), 1, 0, ptr(view));
     glUniformMatrix4fv(programColor.uniform("proj"), 1, 0, ptr(proj));
     
     cubeMeshBuffer3.draw();
     
   } programColor.unbind();
   
 }
Ejemplo n.º 9
0
void		init() {



	// FBO
	fbo1.create();
	fbo2.create();


}
Ejemplo n.º 10
0
FBO* FBO::createFBO(EGLDisplay dpy, int width, int height, GraphicsContext3D::Attributes attributes)
{
    LOGWEBGL("createFBO()");
    FBO* fbo = new FBO(dpy);

    if (!fbo->init(width, height, attributes)) {
        delete fbo;
        return 0;
    }
    return fbo;
}
Ejemplo n.º 11
0
void GraphicsContext3DInternal::releaseFrontBuffer()
{
    LOGWEBGL("GraphicsContext3DInternal::releaseFrontBuffer()");
    MutexLocker lock(m_fboMutex);
    FBO* fbo = m_frontFBO;

    if (fbo) {
        fbo->setLocked(false);
        if (fbo->sync() != EGL_NO_SYNC_KHR) {
            eglDestroySyncKHR(m_dpy, fbo->sync());
        }
        fbo->setSync();
    }
    updateFrontBuffer();
}
	void onDraw(Graphics& g){

		// To render our scene to the FBO, we must first bind it
		fbo.bind();
			// Clear FBO
			g.clear(Graphics::COLOR_BUFFER_BIT | Graphics::DEPTH_BUFFER_BIT);

			// Render our scene as we normally would
			g.draw(mesh);

		// When done rendering our scene to the FBO, we must unbind it
		fbo.unbind();

		// To prove that this all worked, we render the FBO's color texture
		tex.quadViewport(g);
	}
Ejemplo n.º 13
0
bool GLResource::black( Frame *dst )
{
	int w = dst->profile.getVideoWidth();
	int h = dst->profile.getVideoHeight();

	FBO *fbo = getFBO( w, h, GL_RGBA );
	if ( !fbo )
		return false;

	glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo() );
	glClear( GL_COLOR_BUFFER_BIT );
	glBindFramebuffer( GL_FRAMEBUFFER, 0 );

	dst->setFBO( fbo );
	return true;
}
	void onResize(const ViewpointWindow& win, int w, int h){
		// Note: all attachments (textures, RBOs, etc.) to the FBO must have the
		// same width and height.

		// Configure texture on GPU
		tex.format(Graphics::RGB);
		tex.type(Graphics::UBYTE);
		tex.resize(w,h);
		tex.submit(); // ensure texture gets configured on GPU

		// Configure render buffer object on GPU
		rbo.resize(w,h);

		// Finally, attach color texture and depth RBO to FBO
		fbo.attachTexture2D(tex.id());
		fbo.attachRBO(rbo, FBO::DEPTH_ATTACHMENT);
	}
Ejemplo n.º 15
0
Texture* GraphicsEngine::GaussianBlur(Texture* input, float radius, bool halfRes)
{
	FBO* blurFBO = GetFBO(BLUR);

	if (halfRes)
		blurFBO = GetFBO(HALF);

	blurFBO->BindForWriting();
	blurFBO->SetDrawBuffer(0);

	GetShader("Gaussian")->Use();
	GetShader("Gaussian")->SetUniform2f("blurSize", 1.0f / Screen.width * (1 + halfRes), 1.0f / Screen.height * (1 + halfRes));
	GetShader("Gaussian")->SetUniform1f("radius", radius);

	//Horizontal Blur
	GetShader("Gaussian")->SetUniform1i("verticalBlur", false);
	input->Bind();
	FBO::Render();

	blurFBO->SetDrawBuffer(1);

	//Vertical Blur
	GetShader("Gaussian")->SetUniform1i("verticalBlur", true);
	blurFBO->GetTexture()->Bind();
	FBO::Render();

	return blurFBO->GetActiveTexture();
}
Ejemplo n.º 16
0
int main(void) {



	glfwSetErrorCallback(error_callback);
	if (!glfwInit())
		exit(EXIT_FAILURE);
	window = glfwCreateWindow(900, 900, "Simple example", NULL, NULL);
	if(!window) {
		glfwTerminate();
		exit(EXIT_FAILURE);
	}
	glfwMakeContextCurrent(window);
	glfwSetKeyCallback(window, key_callback);
	glfwSetWindowSizeCallback(window, size_callback);

	int err = glewInit();
	if(err != GLEW_OK) {
		abort();
	}

	glfwGetFramebufferSize(window, &width, &height);
	ratio = (float)width / (float)height;

	init();
	init_shaders();

	while (!glfwWindowShouldClose(window)) draw();

	fbo1.cleanup();
	fbo2.cleanup();


	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);
}
Ejemplo n.º 17
0
  void onCreate() {
    
    rh.loadTexture(texture, "resources/hubble.jpg");
    texture.minFilter(GL_NEAREST);
    texture.maxFilter(GL_NEAREST);
    
    rh.loadProgram(textureProgram, "resources/texture", posLoc, -1, texCoordLoc, -1);
    rh.loadProgram(phongProgram, "resources/phong", posLoc, normalLoc, texCoordLoc, -1);
    rh.loadProgram(programColor, "resources/color", posLoc, normalLoc, -1, colorLoc);
    
    MeshData md1;
    addCube(md1, true, 0.95);
    
    MeshData md2;
    addCube(md2, true, 0.5);
    
    MeshData md3;
    addCube(md3, 0.33); //this version makes normals, texcoords, and colors each side with a different default color
    
    cubeMeshBuffer1.init(md1, posLoc, normalLoc, texCoordLoc, -1);
    cubeMeshBuffer2.init(md2, posLoc, normalLoc, texCoordLoc, -1);
    
    cubeMeshBuffer3.init(md3, posLoc, normalLoc, -1, colorLoc);
    
    
    fbo.create(32, 32);

millisToNano(1000);
    
    rotateBehavior = Behavior(now()).delay(1000).length(5000).range(vec3(3.14, 3.14, 3.14)).reversing(true).repeats(-1).sine();
    
    
    proj = glm::perspective(45.0, 1.0, 0.1, 100.0);
    view = glm::lookAt(vec3(0.0,0.0,5), vec3(0,0,0), vec3(0,1,0) );
    model = glm::mat4();
    
    glEnable(GL_DEPTH_TEST);
    glViewport(0, 0, width, height);
  }
Ejemplo n.º 18
0
void CGlobalRendering::PostInit() {
	supportNPOTs = GLEW_ARB_texture_non_power_of_two;
	haveARB   = GLEW_ARB_vertex_program && GLEW_ARB_fragment_program;
	haveGLSL  = (glGetString(GL_SHADING_LANGUAGE_VERSION) != NULL);
	haveGLSL &= GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader;
	haveGLSL &= !!GLEW_VERSION_2_0; // we want OpenGL 2.0 core functions

	{
		const char* glVendor = (const char*) glGetString(GL_VENDOR);
		const char* glRenderer = (const char*) glGetString(GL_RENDERER);
		const std::string vendor = (glVendor != NULL)? StringToLower(std::string(glVendor)): "";
		const std::string renderer = (glRenderer != NULL)? StringToLower(std::string(glRenderer)): "";

		haveATI    = (vendor.find("ati ") != std::string::npos) || (vendor.find("amd ") != std::string::npos);
		haveMesa   = (renderer.find("mesa ") != std::string::npos);
		haveIntel  = (vendor.find("intel ") != std::string::npos);
		haveNvidia = (vendor.find("nvidia ") != std::string::npos);

		//FIXME Neither Intel's nor Mesa's GLSL implementation seem to be in a workable state atm (date: Nov. 2011)
		haveGLSL &= !haveIntel;
		haveGLSL &= !haveMesa;

		if (haveATI) {
			// x-series doesn't support NPOTs (but hd-series does)
			supportNPOTs = (renderer.find(" x") == std::string::npos && renderer.find(" 9") == std::string::npos);
		}
	}

	// use some ATI bugfixes?
	const int atiHacksCfg = configHandler->GetInt("AtiHacks");
	atiHacks = haveATI && (atiHacksCfg < 0); // runtime detect
	atiHacks |= (atiHacksCfg > 0); // user override

	// Runtime compress textures?
	if (GLEW_ARB_texture_compression) {
		// we don't even need to check it, 'cos groundtextures must have that extension
		// default to off because it reduces quality (smallest mipmap level is bigger)
		compressTextures = configHandler->GetBool("CompressTextures");
	}

	// maximum 2D texture size
	{
		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
	}

	// detect if GL_DEPTH_COMPONENT24 is supported (many ATIs don't do so)
	{
		// ATI seems to support GL_DEPTH_COMPONENT24 for static textures, but you can't render to them
		/*
		GLint state = 0;
		glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 16, 16, 0, GL_LUMINANCE, GL_FLOAT, NULL);
		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &state);
		support24bitDepthBuffers = (state > 0);
		*/

		support24bitDepthBuffers = false;
		if (FBO::IsSupported() && !atiHacks) {
			const int fboSizeX = 16, fboSizeY = 16;

			FBO fbo;
			fbo.Bind();
			fbo.CreateRenderBuffer(GL_COLOR_ATTACHMENT0_EXT, GL_RGBA8, fboSizeX, fboSizeY);
			fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT,  GL_DEPTH_COMPONENT24, fboSizeX, fboSizeY);
			const GLenum status = fbo.GetStatus();
			fbo.Unbind();

			support24bitDepthBuffers = (status == GL_FRAMEBUFFER_COMPLETE_EXT);
		}
	}

	// print info
	LOG(
		"GL info:\n"
		"\thaveARB: %i, haveGLSL: %i, ATI hacks: %i\n"
		"\tFBO support: %i, NPOT-texture support: %i, 24bit Z-buffer support: %i\n"
		"\tmaximum texture size: %i, compress MIP-map textures: %i",
		haveARB, haveGLSL, atiHacks,
		FBO::IsSupported(), supportNPOTs, support24bitDepthBuffers,
		maxTextureSize, compressTextures
	);
}
Ejemplo n.º 19
0
int LuaFBOs::CreateFBO(lua_State* L)
{
	FBO fbo;
	fbo.Init(L);

	const int table = 1;
/*
	if (lua_istable(L, table)) {
		lua_getfield(L, table, "target");
		if (lua_isnumber(L, -1)) {
			fbo.target = (GLenum)lua_toint(L, -1);
		} else {
			lua_pop(L, 1);
		}
	}
*/
	const GLenum bindTarget = GetBindingEnum(fbo.target);
	if (bindTarget == 0) {
		return 0;
	}

	// maintain a lua table to hold RBO references
 	lua_newtable(L);
	fbo.luaRef = luaL_ref(L, LUA_REGISTRYINDEX);
	if (fbo.luaRef == LUA_NOREF) {
		return 0;
	}

	GLint currentFBO;
	glGetIntegerv(bindTarget, &currentFBO);

	glGenFramebuffersEXT(1, &fbo.id);
	glBindFramebufferEXT(fbo.target, fbo.id);


	FBO* fboPtr = static_cast<FBO*>(lua_newuserdata(L, sizeof(FBO)));
	*fboPtr = fbo;

	luaL_getmetatable(L, "FBO");
	lua_setmetatable(L, -2);

	// parse the initialization table
	if (lua_istable(L, table)) {
		for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) {
			if (lua_israwstring(L, -2)) {
				const string key = lua_tostring(L, -2);
				const GLenum type = ParseAttachment(key);
				if (type != 0) {
					ApplyAttachment(L, -1, fboPtr, type);
				}
				else if (key == "drawbuffers") {
					ApplyDrawBuffers(L, -1);
				}
			}
		}
	}

	// revert to the old fbo
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, currentFBO);

	if (fboPtr->luaRef != LUA_NOREF) {
		CLuaHandle::GetActiveFBOs(L).fbos.insert(fboPtr);
	}

	return 1;
}
Ejemplo n.º 20
0
int LuaFBOs::meta_gc(lua_State* L)
{
	FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
	fbo->Free(L);
	return 0;
}
Ejemplo n.º 21
0
void CGrassDrawer::CreateFarTex()
{
	//TODO create normalmap, too?
	const int sizeMod = 2;
	const int billboardSize = 256;
	const int numAngles = 16;
	const int texSizeX = billboardSize * numAngles;
	const int texSizeY = billboardSize;

	if (farTex == 0) {
		glGenTextures(1, &farTex);
		glBindTexture(GL_TEXTURE_2D, farTex);
		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);
		glSpringTexStorage2D(GL_TEXTURE_2D, -1, GL_RGBA8, texSizeX, texSizeY);
	}

	FBO fboTex;
	fboTex.Bind();
	fboTex.AttachTexture(farTex);
	fboTex.CheckStatus("GRASSDRAWER1");

	FBO fbo;
	fbo.Bind();
	fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT16, texSizeX * sizeMod, texSizeY * sizeMod);
	fbo.CreateRenderBuffer(GL_COLOR_ATTACHMENT0_EXT, GL_RGBA8, texSizeX * sizeMod, texSizeY * sizeMod);
	fbo.CheckStatus("GRASSDRAWER2");

	if (!fboTex.IsValid() || !fbo.IsValid()) {
		grassOff = true;
		return;
	}

	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();

	glDisable(GL_FOG);
	glDisable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);
	glBindTexture(GL_TEXTURE_2D, grassBladeTex);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_CLIP_PLANE0);
	glEnable(GL_DEPTH_TEST);
	glDepthMask(GL_TRUE);
	glColor4f(1,1,1,1);

	glViewport(0,0,texSizeX*sizeMod, texSizeY*sizeMod);
	glClearColor(mapInfo->grass.color.r,mapInfo->grass.color.g,mapInfo->grass.color.b,0.f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.f,0.f,0.f,0.f);

	static const GLdouble eq[4] = {0.f, 1.f, 0.f, 0.f};

	// render turf from different vertical angles
	for (int a=0;a<numAngles;++a) {
		glViewport(a*billboardSize*sizeMod, 0, billboardSize*sizeMod, billboardSize*sizeMod);
		glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
			glRotatef(a*90.f/(numAngles-1),1,0,0);
			//glTranslatef(0,-0.5f,0);
		glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			glOrtho(-partTurfSize, partTurfSize, partTurfSize, -partTurfSize, -turfSize, turfSize);

		// has to be applied after the matrix transformations,
		// cause it uses those an `compiles` them into the clip plane
		glClipPlane(GL_CLIP_PLANE0, &eq[0]);

		glCallList(grassDL);
	}

	glDisable(GL_CLIP_PLANE0);

	// scale down the rendered fartextures (MSAA) and write to the final texture
	glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo.fboId);
	glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, fboTex.fboId);
	glBlitFramebufferEXT(0, 0, texSizeX*sizeMod, texSizeY*sizeMod,
		0, 0, texSizeX, texSizeY,
		GL_COLOR_BUFFER_BIT, GL_LINEAR);

	// compute mipmaps
	glBindTexture(GL_TEXTURE_2D, farTex);
	glGenerateMipmap(GL_TEXTURE_2D);

	// blur non-rendered areas, so in mipmaps color data isn't blurred with background color
	{
		const int mipLevels = std::ceil(std::log((float)(std::max(texSizeX, texSizeY) + 1)));

		glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
		glMatrixMode(GL_PROJECTION);
			glLoadIdentity();

		glEnable(GL_BLEND);
		glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, GL_ZERO, GL_DST_ALPHA);

		// copy each mipmap to its predecessor background
		// -> fill background with blurred color data
		fboTex.Bind();
		for (int mipLevel = mipLevels - 2; mipLevel >= 0; --mipLevel) {
			fboTex.AttachTexture(farTex, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT, mipLevel);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, mipLevel + 1.f);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, mipLevel + 1.f);
			glViewport(0, 0, texSizeX>>mipLevel, texSizeY>>mipLevel);

			CVertexArray* va = GetVertexArray();
			va->Initialize();
				va->AddVertexT(float3(-1.0f,  1.0f, 0.0f), 0.0f, 1.0f);
				va->AddVertexT(float3( 1.0f,  1.0f, 0.0f), 1.0f, 1.0f);
				va->AddVertexT(float3( 1.0f, -1.0f, 0.0f), 1.0f, 0.0f);
				va->AddVertexT(float3(-1.0f, -1.0f, 0.0f), 0.0f, 0.0f);
			va->DrawArrayT(GL_QUADS);
		}

		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		// recreate mipmaps from now blurred base level
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, -1000.f);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD,  1000.f);
		glGenerateMipmap(GL_TEXTURE_2D);
	}

	glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY);
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	FBO::Unbind();
	//glSaveTexture(farTex, "grassfar.png");
}
Ejemplo n.º 22
0
FBO* GLResource::getFBO( int width, int height, GLint iformat )
{
	int i;

	for ( i = 0; i < fboList.count(); ++i ) {
		FBO *f = fboList.at(i);
		if ( f->isFree() && ( f->width() != width || f->height() != height || f->format() != iformat ) ) {
			delete fboList.takeAt( i-- );
		}
	}

	for ( i = 0; i < fboList.count(); ++i ) {
		FBO *f = fboList.at(i);
		if ( f->isFree() && f->width() == width && f->height() == height && f->format() == iformat ) {
			f->setFree( false );
			return f;
		}
	}

	FBO *f = new FBO( width, height, iformat );
	if ( !f->isValid() ) {
		delete f;
		return NULL;
	}

	fboList.append( f );
	f->setFree( false );
	return f;
}
Ejemplo n.º 23
0
void GraphicsContext3DInternal::swapBuffers()
{
    if (s_loggingEnabled)
        m_webGLFPSTimer->tick();

    LOGWEBGL("+swapBuffers()");

    MutexLocker lock(m_fboMutex);
    FBO* fbo = m_currentFBO;
    if (fbo == 0)
        return;

    makeContextCurrent();

    bool mustRestoreFBO = (m_boundFBO != fbo->fbo());
    if (mustRestoreFBO) {
        glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo());
    }

    // Create the fence sync and notify the sync thread
    fbo->setSync();
    //[CAPPFIX_WEB_WEBGL] - Improve UI Response Begin
    if (!m_needImproveUIResponseMode)
    //[CAPPFIX_WEB_WEBGL_END]
#if USE(SHARED_TEXTURE_WEBGL)
        glFinish();
#else
        glFlush();
#endif

    m_queuedBuffers.append(fbo);
    m_threadCondition.broadcast();

#if USE(SHARED_TEXTURE_WEBGL)
    // Dequeue a new buffer
    fbo = dequeueBuffer();
#else
    //[CAPPFIX_WEB_WEBGL] - Improve UI Response Begin
    int tick = 0;
    if (!m_needImproveUIResponseMode)
        tick = getTickCount();
    //[CAPPFIX_WEB_WEBGL_END]
    // Dequeue a new buffer
    fbo = dequeueBuffer();

    //[CAPPFIX_WEB_WEBGL] - Improve UI Response Begin
    if (!m_needImproveUIResponseMode &&  getTickCount() - tick > SWP_WebGL_IUR_Time) {
        m_needImproveUIResponseMode = true;
        LOGWEBGL("On needImproveUIResponseMode");
    }
    //[CAPPFIX_WEB_WEBGL_END]
#endif
    m_currentFBO = fbo;

    if (!mustRestoreFBO) {
        m_boundFBO = m_currentFBO->fbo();
    }
    glBindFramebuffer(GL_FRAMEBUFFER, m_boundFBO);
    m_canvasDirty = false;
    m_layerComposited = true;
    LOGWEBGL("-swapBuffers()");
}
Ejemplo n.º 24
0
void Renderer::renderSSAO()
{
  if (!m_shaderSSAOcalc || !m_shaderSSAOblur || !m_shaderSSAOfinal)
    init(m_windowWidth, m_windowHeight);

  FBO *a = new FBO(m_windowWidth, m_windowHeight, 3, false, false);
  FBO *b = new FBO(m_windowWidth, m_windowHeight, 3, false, false);

  a->bind();
  glClearColor(1, 1, 1, 1);

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  m_shaderSSAOcalc->bind();

  m_shaderSSAOcalc->sendSampler2D("positionMap", m_gBuffer->getColorTexture(0), 0);
  m_shaderSSAOcalc->sendSampler2D("normalMap", m_gBuffer->getColorTexture(1), 1);
  m_shaderSSAOcalc->sendMat4("sceneProjectionMatrix", m_currentProjectionMatrix);
  m_shaderSSAOcalc->sendFloat("radius", *m_ssaoRadius);
  m_shaderSSAOcalc->sendFloat("quality", *m_ssaoQuality);

  m_sfq.renderGeometry();

  m_shaderSSAOcalc->unbind();
  a->unbind();



  //Blur #1 SSAO calculation
  b->bind();

  //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  m_shaderSSAOblur->bind();
  m_shaderSSAOblur->sendSampler2D("colortexture", a->getColorTexture(2), 0);
  m_shaderSSAOblur->sendInt("secondPass", 0);
  m_sfq.renderGeometry();

  m_shaderSSAOblur->unbind();
  b->unbind();



  //Blur #2 SSAO calculation
  a->bind();
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  m_shaderSSAOblur->bind();
  m_shaderSSAOblur->sendSampler2D("colortexture", b->getColorTexture(2), 0);
  m_shaderSSAOblur->sendFloat("secondPass", 1);
  m_sfq.renderGeometry();

  m_shaderSSAOblur->unbind();
  a->unbind();

  glClearColor(0, 0, 0, 0);


  //COLOR COMPOSITING
  bindFBO();
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  m_shaderSSAOfinal->bind();
  m_shaderSSAOfinal->sendSampler2D("colorMap", getLastFBO()->getColorTexture(2), 0);
  m_shaderSSAOfinal->sendSampler2D("ssaoMap", a->getColorTexture(2), 1);
  m_sfq.renderGeometry();
  m_shaderSSAOfinal->unbind();
  unbindFBO();

  delete a;
  delete b;
}
Ejemplo n.º 25
0
void CGrassDrawer::CreateFarTex()
{
	int sizeMod=2;

	glGenTextures(1, &farTex);
	glBindTexture(GL_TEXTURE_2D, farTex);
	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);
	glSpringTexStorage2D(GL_TEXTURE_2D, -1, GL_RGBA8, 1024, 64);

	FBO fboTex;
	fboTex.Bind();
	fboTex.AttachTexture(farTex);
	fboTex.CheckStatus("GRASSDRAWER1");

	FBO fbo;
	fbo.Bind();
	fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT16, 1024 * sizeMod, 64 * sizeMod);
	fbo.CreateRenderBuffer(GL_COLOR_ATTACHMENT0_EXT, GL_RGBA8, 1024 * sizeMod, 64 * sizeMod);
	fbo.CheckStatus("GRASSDRAWER2");

	if (!fboTex.IsValid() || !fbo.IsValid()) {
		grassOff = true;
		return;
	}

	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();

	glDisable(GL_FOG);
	glDisable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);
	glBindTexture(GL_TEXTURE_2D, grassBladeTex);
	glEnable(GL_TEXTURE_2D);
	glColor4f(1,1,1,1);

	glViewport(0,0,1024*sizeMod, 64*sizeMod);
	glClearColor(0.75f,0.9f,0.75f,0.f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.f,0.f,0.f,0.f);

	// render turf from different vertical angles
	for (int a=0;a<16;++a) {
		glViewport(a*64*sizeMod, 0, 64*sizeMod, 64*sizeMod);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glRotatef((a-1)*90/15.0f,1,0,0);
		glTranslatef(0,-0.5f,0);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(-partTurfSize, partTurfSize, -partTurfSize, partTurfSize, -turfSize, turfSize);

		glCallList(grassDL);
	}

	glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY);
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	// scale down the rendered fartextures (MSAA) and write to the final texture
	glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo.fboId);
	glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, fboTex.fboId);
	glBlitFramebufferEXT(0, 0, 1024*sizeMod, 64*sizeMod,
		0, 0, 1024, 64,
		GL_COLOR_BUFFER_BIT, GL_LINEAR);

	fbo.Unbind();

	// compute mipmaps
	glBindTexture(GL_TEXTURE_2D, farTex);
	glGenerateMipmap(GL_TEXTURE_2D);
}
Ejemplo n.º 26
0
void CGlobalRendering::PostInit() {
	supportNPOTs = GLEW_ARB_texture_non_power_of_two;
	haveARB   = GLEW_ARB_vertex_program && GLEW_ARB_fragment_program;
	haveGLSL  = (glGetString(GL_SHADING_LANGUAGE_VERSION) != NULL);
	haveGLSL &= GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader;
	haveGLSL &= !!GLEW_VERSION_2_0; // we want OpenGL 2.0 core functions

	{
		const char* glVendor = (const char*) glGetString(GL_VENDOR);
		const char* glRenderer = (const char*) glGetString(GL_RENDERER);
		const std::string vendor = (glVendor != NULL)? StringToLower(std::string(glVendor)): "";
		const std::string renderer = (glRenderer != NULL)? StringToLower(std::string(glRenderer)): "";

		haveATI    = (vendor.find("ati ") != std::string::npos) || (vendor.find("amd ") != std::string::npos);
		haveMesa   = (renderer.find("mesa ") != std::string::npos) || (renderer.find("gallium ") != std::string::npos);
		haveIntel  = (vendor.find("intel") != std::string::npos);
		haveNvidia = (vendor.find("nvidia ") != std::string::npos);

		//FIXME Neither Intel's nor Mesa's GLSL implementation seem to be in a workable state atm (date: Nov. 2011)
		haveGLSL &= !haveIntel;
		haveGLSL &= !haveMesa;
		//FIXME add an user config to force enable it!

		if (haveATI) {
			// x-series doesn't support NPOTs (but hd-series does)
			supportNPOTs = (renderer.find(" x") == std::string::npos && renderer.find(" 9") == std::string::npos);
		}
	}

	// use some ATI bugfixes?
	const int atiHacksCfg = configHandler->GetInt("AtiHacks");
	atiHacks = haveATI && (atiHacksCfg < 0); // runtime detect
	atiHacks |= (atiHacksCfg > 0); // user override

	// Runtime compress textures?
	if (GLEW_ARB_texture_compression) {
		// we don't even need to check it, 'cos groundtextures must have that extension
		// default to off because it reduces quality (smallest mipmap level is bigger)
		compressTextures = configHandler->GetBool("CompressTextures");
	}

#ifdef GLEW_NV_primitive_restart
	supportRestartPrimitive = !!(GLEW_NV_primitive_restart);
#endif

	// maximum 2D texture size
	{
		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
	}

	// retrieve maximu smoothed PointSize
	float2 aliasedPointSizeRange, smoothPointSizeRange;
	glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, (GLfloat*)&aliasedPointSizeRange);
	glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE,  (GLfloat*)&smoothPointSizeRange);
	maxSmoothPointSize = std::min(aliasedPointSizeRange.y, smoothPointSizeRange.y);

	// some GLSL relevant information
	{
		glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &glslMaxUniformBufferBindings);
		glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE,      &glslMaxUniformBufferSize);
		glGetIntegerv(GL_MAX_VARYING_FLOATS,          &glslMaxVaryings);
		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,          &glslMaxAttributes);
		glGetIntegerv(GL_MAX_DRAW_BUFFERS,            &glslMaxDrawBuffers);
		glGetIntegerv(GL_MAX_ELEMENTS_INDICES,        &glslMaxRecommendedIndices);
		glGetIntegerv(GL_MAX_ELEMENTS_VERTICES,       &glslMaxRecommendedVertices);
		glslMaxVaryings /= 4; // GL_MAX_VARYING_FLOATS returns max individual floats, we want float4
	}

	// detect if GL_DEPTH_COMPONENT24 is supported (many ATIs don't do so)
	{
		// ATI seems to support GL_DEPTH_COMPONENT24 for static textures, but you can't render to them
		/*
		GLint state = 0;
		glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 16, 16, 0, GL_LUMINANCE, GL_FLOAT, NULL);
		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &state);
		support24bitDepthBuffers = (state > 0);
		*/

		support24bitDepthBuffers = false;
		if (FBO::IsSupported() && !atiHacks) {
			const int fboSizeX = 16, fboSizeY = 16;

			FBO fbo;
			fbo.Bind();
			fbo.CreateRenderBuffer(GL_COLOR_ATTACHMENT0_EXT, GL_RGBA8, fboSizeX, fboSizeY);
			fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT,  GL_DEPTH_COMPONENT24, fboSizeX, fboSizeY);
			const GLenum status = fbo.GetStatus();
			fbo.Unbind();

			support24bitDepthBuffers = (status == GL_FRAMEBUFFER_COMPLETE_EXT);
		}
	}

	// print info
	LOG(
		"GL info:\n"
		"\thaveARB: %i, haveGLSL: %i, ATI hacks: %i\n"
		"\tFBO support: %i, NPOT-texture support: %i, 24bit Z-buffer support: %i\n"
		"\tmaximum texture size: %i, compress MIP-map textures: %i\n"
		"\tmaximum SmoothPointSize: %0.0f, maximum vec4 varying/attributes: %i/%i\n"
		"\tmaximum drawbuffers: %i, maximum recommended indices/vertices: %i/%i\n"
		"\tnumber of UniformBufferBindings: %i (%ikB)",
		haveARB, haveGLSL, atiHacks,
		FBO::IsSupported(), supportNPOTs, support24bitDepthBuffers,
		maxTextureSize, compressTextures, maxSmoothPointSize,
		glslMaxVaryings, glslMaxAttributes, glslMaxDrawBuffers,
		glslMaxRecommendedIndices, glslMaxRecommendedVertices,
		glslMaxUniformBufferBindings, glslMaxUniformBufferSize / 1024
	);

	teamNanospray = configHandler->GetBool("TeamNanoSpray");
}
Ejemplo n.º 27
0
int LuaFBOs::meta_gc(lua_State* L)
{
	FBO* fbo = (FBO*)luaL_checkudata(L, 1, "FBO");
	fbo->Free(L);
	return 0;
}
Ejemplo n.º 28
0
void Composer::movitRender( Frame *dst, bool update )
{
	int i, j, start=0;
	Frame *f;
	//QTime time;
	//time.start();
	
	Profile projectProfile = sampler->getProfile();

	// find the lowest frame to process
	for ( j = 0 ; j < dst->sample->frames.count(); ++j ) {
		if ( (f = dst->sample->frames[j]->frame) ) {
			start = j;
			break;
		}
	}

	// build a "description" of the required chain
	// processing frames from bottom to top
	i = start;
	double pts = sampler->currentPTS();
	QStringList currentDescriptor;
	int ow = projectProfile.getVideoWidth();
	int oh = projectProfile.getVideoHeight();
	while ( (f = getNextFrame( dst, i )) ) {
		FrameSample *sample = dst->sample->frames[i - 1];
		// input and filters
		movitFrameDescriptor( "-", f, &sample->videoFilters, currentDescriptor, &projectProfile );
		// transition
		if ( sample->transitionFrame.frame && !sample->transitionFrame.videoTransitionFilter.isNull() ) {
			// filters applied on first transition frame, if any
			currentDescriptor.append( "--" + sample->transitionFrame.videoTransitionFilter->getDescriptorFirst( pts, f, &projectProfile ) );
			movitFrameDescriptor( "->", sample->transitionFrame.frame, &sample->transitionFrame.videoFilters, currentDescriptor, &projectProfile );
			// filters applied on second transition frame, if any
			currentDescriptor.append( "-->" + sample->transitionFrame.videoTransitionFilter->getDescriptorSecond( pts, sample->transitionFrame.frame, &projectProfile ) );
			currentDescriptor.append( "-<" + sample->transitionFrame.videoTransitionFilter->getDescriptor( pts, sample->transitionFrame.frame, &projectProfile ) );
		}
		// overlay
		if ( (i - 1) > start )
			currentDescriptor.append( GLOverlay().getDescriptor( pts, f, &projectProfile ) );
		ow = f->glWidth;
		oh = f->glHeight;
	}
	// background
	currentDescriptor.append( movitBackground.getDescriptor( pts, NULL, &projectProfile ) );
	// output
	if (outputResize.width() > 0) {
		currentDescriptor.append( QString("Resized output %1 %2").arg( outputResize.width() ).arg( outputResize.height() ) );
	}
	else {
		currentDescriptor.append( QString("OUTPUT %1 %2").arg( ow ).arg( oh ) );
	}

	// rebuild the chain if neccessary
	if ( currentDescriptor !=  movitChain.descriptor ) {
		for ( int k = 0; k < currentDescriptor.count(); k++ )
			printf("%s\n", currentDescriptor[k].toLocal8Bit().data());
		movitChain.descriptor = currentDescriptor;
		movitChain.reset();
		movitChain.chain = new EffectChain( projectProfile.getVideoSAR() * projectProfile.getVideoWidth(), projectProfile.getVideoHeight(), movitPool );

		i = start;
		Effect *last, *current = NULL;
		
		while ( (f = getNextFrame( dst, i )) ) {
			last = current;
			// input and filters
			MovitBranch *branch;
			FrameSample *sample = dst->sample->frames[i - 1];
			current = movitFrameBuild( f, &sample->videoFilters, &branch );
			// transition
			if ( sample->transitionFrame.frame && !sample->transitionFrame.videoTransitionFilter.isNull() ) {
				QList<Effect*> el = sample->transitionFrame.videoTransitionFilter->getMovitEffects();
				
				// filters applied on first transition frame, if any
				QList<Effect*> first = sample->transitionFrame.videoTransitionFilter->getMovitEffectsFirst();
				for ( int l = 0; l < first.count(); ++l )
					current = movitChain.chain->add_effect( first.at( l ) );
				
				MovitBranch *branchTrans;
				Effect *currentTrans = movitFrameBuild( sample->transitionFrame.frame, &sample->transitionFrame.videoFilters, &branchTrans );
				// filters applied on second transition frame, if any
				QList<Effect*> second = sample->transitionFrame.videoTransitionFilter->getMovitEffectsSecond();
				for ( int l = 0; l < second.count(); ++l )
					currentTrans = movitChain.chain->add_effect( second.at( l ) );
				
				branchTrans->filters.append( new MovitFilter( el ) );
				for ( int l = 0; l < el.count(); ++l )
					current = movitChain.chain->add_effect( el.at( l ), current, currentTrans );
			}
			// overlay
			if ( last ) {
				GLOverlay *overlay = new GLOverlay();
				QList<Effect*> el = overlay->getMovitEffects();
				branch->overlay = new MovitFilter( el, overlay );
				for ( int l = 0; l < el.count(); ++l )
					current = movitChain.chain->add_effect( el.at( l ), last, current );
			}
		}
		// background
		QList<Effect*> el = movitBackground.getMovitEffects();
		movitChain.chain->add_effect( el[0] );
		// output resizer
		if (outputResize.width() > 0) {
			Effect *e = new ResampleEffect();
			e->set_int( "width", outputResize.width() );
			e->set_int( "height", outputResize.height() );
			movitChain.chain->add_effect( e );
		}
		// output
		movitChain.chain->set_dither_bits( 8 );
		ImageFormat output_format;
		output_format.color_space = COLORSPACE_sRGB;
		output_format.gamma_curve = GAMMA_REC_709;
		movitChain.chain->add_output( output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED );
		movitChain.chain->finalize();
	}

	// update inputs data and filters parameters
	i = start, j = 0;
	int w = projectProfile.getVideoWidth();
	int h = projectProfile.getVideoHeight();
	while ( (f = getNextFrame( dst, i )) ) {
		f->glWidth = f->profile.getVideoWidth();
		f->glHeight = f->profile.getVideoHeight();
		f->glSAR = f->profile.getVideoSAR();
		f->glOVD = 0;
		f->glOVDTransformList.clear();
		
		// input and filters
		MovitBranch *branch = movitChain.branches[ j++ ];
		branch->input->process( f, &gl );
		int vf = 0;
		FrameSample *sample = dst->sample->frames[i - 1];
		for ( int k = 0; k < branch->filters.count(); ++k ) { 
			if ( !branch->filters[k]->filter )
				sample->videoFilters[vf++]->process( branch->filters[k]->effects, pts, f, &projectProfile );
			else
				branch->filters[k]->filter->process( branch->filters[k]->effects, pts, f, &projectProfile );
		}
		// transition
		if ( sample->transitionFrame.frame && !sample->transitionFrame.videoTransitionFilter.isNull() ) {
			sample->transitionFrame.frame->glWidth = sample->transitionFrame.frame->profile.getVideoWidth();
			sample->transitionFrame.frame->glHeight = sample->transitionFrame.frame->profile.getVideoHeight();
			sample->transitionFrame.frame->glSAR = sample->transitionFrame.frame->profile.getVideoSAR();
			MovitBranch *branchTrans = movitChain.branches[ j++ ];
			branchTrans->input->process( sample->transitionFrame.frame, &gl );
			int tvf = 0;
			int k;
			for ( k = 0; k < branchTrans->filters.count() - 1; ++k ) { 
				if ( !branchTrans->filters[k]->filter )
					sample->transitionFrame.videoFilters[tvf++]->process( branchTrans->filters[k]->effects, pts, sample->transitionFrame.frame, &projectProfile );
				else
					branchTrans->filters[k]->filter->process( branchTrans->filters[k]->effects, pts, sample->transitionFrame.frame, &projectProfile );
			}
			sample->transitionFrame.videoTransitionFilter->process( branchTrans->filters[k]->effects, pts, f, sample->transitionFrame.frame, &projectProfile );
		}
		// overlay
		if ( branch->overlay && branch->overlay->filter )
			branch->overlay->filter->process( branch->overlay->effects, pts, f, f, &projectProfile );
		
		w = f->glWidth;
		h = f->glHeight;
	}

	// render
	waitFence();
	// output resizer
	if (outputResize.width() > 0) {
		w = outputResize.width();
		h = outputResize.height();
	}
	FBO *fbo = gl.getFBO( w, h, GL_RGBA );
	movitChain.chain->render_to_fbo( fbo->fbo(), w, h );
	
	dst->glWidth = w;
	dst->glHeight = h;
	dst->glSAR = projectProfile.getVideoSAR();
	if ( !update ) {
		dst->setVideoFrame( Frame::GLTEXTURE, w, h, dst->glSAR,
						projectProfile.getVideoInterlaced(), projectProfile.getVideoTopFieldFirst(),
						pts, projectProfile.getVideoFrameDuration() );
	}
	dst->setFBO( fbo );
	dst->setFence( gl.getFence() );
	composerFence = gl.getFence();
	glFlush();
	
	//qDebug() << "elapsed" << time.elapsed();
}
Ejemplo n.º 29
0
int main(void) {
    srand(time(NULL));

    //Create init object
    Init init = Init();

    //Initialize glfw
    init.glfw(4, 1);
    //Open a window
    GLFWwindow *window = init.window(400, 400);

    //Print window info
    init.printWindowInfo(window);

    //Make opened window current context
    glfwMakeContextCurrent(window);

    init.glew();

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);

    glEnable(GL_CULL_FACE);


    // Nvidia cards require a vertex array to cooperate.
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    //Set up the initial state.
    unsigned int w = 32, h = 32, d = 32;
    State *prevState = new State(w, h, d);

    VelocityGrid *velocities = new VelocityGrid(w, h, d);
    prevState->setVelocityGrid(velocities);

    // init level set
    LevelSet *ls = factory::levelSet::ball(w, h, d);
    prevState->setLevelSet(ls);

    delete ls;

    // init simulator
    Simulator sim(*prevState, 0.1f);
    //    BubbleMaxExporter bubbleExporter;
    
    // Dark black background
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    //Load in shaders
    static ShaderProgram colorCubeProg("../vertShader.vert", "../colorCube.frag");
    static ShaderProgram rayCasterProg("../vertShader.vert", "../rayCaster.frag");
    static ShaderProgram bubbleProg("../bubbleVertShader.vert", "../bubbleFragShader.frag");

    static const GLfloat vertexBufferData[] = {
            -1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            -1.0f, 1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
            -1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, 1.0f,
            -1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f
    };

    static const GLuint triangleBufferData[] = {
            // xy plane (z = -1)
            0, 1, 3,
            3, 2, 0,
            // xz plane (y = -1)
            0, 5, 1,
            0, 4, 5,
            // yz plane (x = -1)
            0, 2, 4,
            2, 6, 4,
            // xy plane (z = 1)
            4, 7, 5,
            4, 6, 7,
            // xz plane (y = 1)
            2, 7, 6,
            2, 3, 7,
            // yz plane (x = 1)
            1, 5, 3,
            3, 5, 7
    };

    std::vector<GLfloat> g_bubble_buffer_data;

    //Create vertex buffer
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexBufferData), vertexBufferData, GL_STATIC_DRAW);



    GLuint triangleBuffer;
    glGenBuffers(1, &triangleBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(triangleBufferData), triangleBufferData, GL_STATIC_DRAW);

    // Create bubble buffer
    GLuint bubbleBuffer;
    glGenBuffers(1, &bubbleBuffer);

    // Create framebuffer
    FBO *framebuffer = new FBO(width, height);

    GLuint volumeTextureId;
    glGenTextures(1, &volumeTextureId);
    glBindTexture(GL_TEXTURE_3D, volumeTextureId);

    //Object which encapsulates a texture + The destruction of a texture.
    Texture3D tex3D(w, h, d);
    double lastTime = glfwGetTime();
    int nbFrames = 0;

    float deltaT = 0.1; //First time step

    glfwSwapInterval(1);
    int i = 0;
    do {


        framebuffer->activate();

        // common for both render passes.
        sim.step(deltaT);

        // deltaT = sim.getDeltaT();

        glm::mat4 matrix = glm::mat4(1.0f);
        matrix = glm::translate(matrix, glm::vec3(0.0f, 0.0f, 2.0f));
        matrix = glm::rotate(matrix, -3.1415926535f / 4.0f, glm::vec3(1.0f, 0.0f, 0.0f));
        matrix = glm::rotate(matrix, 0.1415926535f / 4.0f * (float) glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));

        // Render back face of the cube.
        colorCubeProg();
        glCullFace(GL_FRONT);

        {
            GLuint tLocation = glGetUniformLocation(colorCubeProg, "time");
            glUniform1f(tLocation, glfwGetTime());

            GLuint mvLocation = glGetUniformLocation(colorCubeProg, "mvMatrix");
            glUniformMatrix4fv(mvLocation, 1, false, glm::value_ptr(matrix));
        }

        glClear(GL_COLOR_BUFFER_BIT);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleBuffer);
    //Triangle coordinates
    glVertexAttribPointer(
            0,                  // Location 0
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            0,                  // stride
            (void *) 0            // array buffer offset
    );

        glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_INT, 0);
        glDisableVertexAttribArray(0);

        // Do the ray casting.
        glBindFramebuffer(GL_FRAMEBUFFER, 0); // bind the screen
        glCullFace(GL_BACK);
        rayCasterProg();

        {
            GLuint tLocation = glGetUniformLocation(rayCasterProg, "time");
            glUniform1f(tLocation, glfwGetTime());

            GLuint mvLocation = glGetUniformLocation(rayCasterProg, "mvMatrix");
            glUniformMatrix4fv(mvLocation, 1, false, glm::value_ptr(matrix));

            GLuint windowSizeLocation = glGetUniformLocation(rayCasterProg, "windowSize");
            glUniform2f(windowSizeLocation, width, height);
        }

        glClear(GL_COLOR_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, *(framebuffer->getTexture()));

        GLuint textureLocation = glGetUniformLocation(rayCasterProg, "backfaceTexture");
        glUniform1i(textureLocation, 0);

        State *currentState = sim.getCurrentState();

        std::vector<glm::vec3> vertexList;
        std::vector<std::vector<int> > faceIndices;
        // copy desired quantities to texture
        for (unsigned int k = 0; k < d; ++k) {
            for (unsigned int j = 0; j < h; ++j) {
                for (unsigned int i = 0; i < w; ++i) {

                    // velocity
                    //tex3D.set(i,j,k,0, 0.5 + 0.5*currentState.getVelocityGrid()->u->get(i,j,k));
                    //tex3D.set(i,j,1, 0.5 + 0.5*currentState.getVelocityGrid()->v->get(i,j));
                    //tex3D.set(i,j,2, 0.5 + currentState.getCellTypeGrid()->get(i, j));
                    //tex3D.set(i,j,2, 0.5);
                    //tex3D.set(i,j,3, 1.0f);

                    // divergence
                    //tex3D.set(i,j,0, fabs(sim.getDivergenceGrid()->get(i,j)));
                    //tex3D.set(i,j,1, fabs(sim.getDivergenceGrid()->get(i,j)));
                    //tex3D.set(i,j,2, fabs(sim.getDivergenceGrid()->get(i,j)));
                    //tex3D.set(i,j,3, 1.0f);

                    // type
                    // tex3D.set(i,j,k, 0, currentState.getCellTypeGrid()->get(i,j, k) == CellType::FLUID ? 1.0 : 0.0);
                    // tex3D.set(i,j,k, 1, currentState.getCellTypeGrid()->get(i,j, k) == CellType::FLUID ? 1.0 : 0.0);
                    // tex3D.set(i,j,k, 2, currentState.getCellTypeGrid()->get(i,j, k) == CellType::SOLID ? 1.0 : 0.0);
                    // tex3D.set(i,j,k, 3, 1.0f);

                    if(currentState->getSignedDistanceGrid()->isValid(i+1,j,k) &&
                        currentState->getSignedDistanceGrid()->isValid(i,j+1,k) &&
                        currentState->getSignedDistanceGrid()->isValid(i+1,j+1,k) &&
                        currentState->getSignedDistanceGrid()->isValid(i,j,k+1) &&
                        currentState->getSignedDistanceGrid()->isValid(i+1,j,k+1) &&
                        currentState->getSignedDistanceGrid()->isValid(i,j+1,k+1) &&
                        currentState->getSignedDistanceGrid()->isValid(i+1,j+1,k+1)){

                        marchingCubes::GRIDCELL gridcell;
                        gridcell.p[0] = glm::vec3(i,j,k);
                        gridcell.p[1] = glm::vec3(i,j+1,k);
                        gridcell.p[2] = glm::vec3(i+1,j+1,k);
                        gridcell.p[3] = glm::vec3(i+1,j,k);
                        gridcell.p[4] = glm::vec3(i,j,k+1);
                        gridcell.p[5] = glm::vec3(i,j+1,k+1);
                        gridcell.p[6] = glm::vec3(i+1,j+1,k+1);
                        gridcell.p[7] = glm::vec3(i+1,j,k+1);

                        gridcell.val[0] = currentState->getSignedDistanceGrid()->get(i, j, k);
                        gridcell.val[1] = currentState->getSignedDistanceGrid()->get(i, j+1, k);
                        gridcell.val[2] = currentState->getSignedDistanceGrid()->get(i+1, j+1, k);
                        gridcell.val[3] = currentState->getSignedDistanceGrid()->get(i+1, j, k);
                        gridcell.val[4] = currentState->getSignedDistanceGrid()->get(i, j, k+1);
                        gridcell.val[5] = currentState->getSignedDistanceGrid()->get(i, j+1, k+1);
                        gridcell.val[6] = currentState->getSignedDistanceGrid()->get(i+1, j+1, k+1);
                        gridcell.val[7] = currentState->getSignedDistanceGrid()->get(i+1, j, k+1);

                        //std::cout << gridcell.val[0] << std::endl;

                        marchingCubes::TRIANGLE *triangles = new marchingCubes::TRIANGLE[5];
                        int numTriangles = marchingCubes::PolygoniseCube(gridcell, 0.0, triangles);
                        for(int i = 0; i < numTriangles; i++){
                            int startIndex = vertexList.size()+1;
                            for(int j = 0; j < 3; j++){
                                //std::cout << triangles[i].p[j].x << " " << triangles[i].p[j].y << " " << triangles[i].p[j].z << std::endl;
                            }
                            vertexList.push_back(triangles[i].p[0]);
                            vertexList.push_back(triangles[i].p[1]);
                            vertexList.push_back(triangles[i].p[2]);

                            std::vector<int> indices = {
                                    startIndex,
                                    startIndex+1,
                                    startIndex+2
                            };

                            faceIndices.push_back(indices);
                        }

                        delete[] triangles;
                    }
                    //signed dist
                    float dist = currentState->getSignedDistanceGrid()->get(i, j, k);
                    float solid = currentState->getCellTypeGrid()->get(i, j, k) == CellType::SOLID ? 1.0f : 0.0f;
                    dist = (glm::clamp(dist + solid, -1.0f, 1.0f) + 1) / 2;

                    tex3D.set(i, j, k, 0, solid);
                    tex3D.set(i, j, k, 1, 0.0f); // not used
                    tex3D.set(i, j, k, 2, dist);
                    tex3D.set(i, j, k, 3, 1.0f);
                    //closest point
                    // tex3D.set(i,j,0, currentState.getClosestPointGrid()->get(i,j).x / 70.0);
                    // tex3D.set(i,j,1, currentState.getClosestPointGrid()->get(i,j).y / 70.0);
                    // tex3D.set(i,j,2, 0.0f);
                    // tex3D.set(i,j,3, 1.0f);
                }
            }
        }

        printObjToFile("exported_" + std::to_string(i) + ".obj", vertexList, faceIndices);
        std::ofstream fileStream("exportedState_" + std::to_string(i) + ".pf", std::ios::binary);
        currentState->write(fileStream);
        fileStream.close();


        // activate and upload texture to gpu
        tex3D(GL_TEXTURE1);
        GLuint volumeTextureLocation = glGetUniformLocation(rayCasterProg, "volumeTexture");
        glUniform1i(volumeTextureLocation, 1);

        glEnableVertexAttribArray(0);
        glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_INT, 0);
        glDisableVertexAttribArray(0);

        FBO::deactivate();

        

        ////////////////// Start drawing bubbles //////////////////////
        
        // Draw bubbles
        const std::vector<Bubble> bubbles = currentState->getBubbles();
        g_bubble_buffer_data.clear();
        std::cout << "frame=" << i << ", nBubbles=" << bubbles.size() << std::endl;
        for (int i = 0; i < bubbles.size(); i++) {
          Bubble b = bubbles.at(i);

          //          std::cout << "bubble pos " << b.position.x << ", " << b.position.y << std::endl << b.radius << std::endl;
            
          g_bubble_buffer_data.push_back(b.position.x / (float)w * 2.0 - 1.0);
          g_bubble_buffer_data.push_back(b.position.y / (float)h * 2.0 - 1.0);
          g_bubble_buffer_data.push_back(b.position.z / (float)d * 2.0 - 1.0);
          g_bubble_buffer_data.push_back(b.radius);
        }

           
        glBindBuffer(GL_ARRAY_BUFFER, bubbleBuffer);    
        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * g_bubble_buffer_data.size(), &g_bubble_buffer_data[0], GL_DYNAMIC_DRAW);
        
                
        
        bubbleProg();
        glEnable(GL_PROGRAM_POINT_SIZE);

        {
            GLuint tLocation = glGetUniformLocation(colorCubeProg, "time");
            glUniform1f(tLocation, glfwGetTime());

            GLuint mvLocation = glGetUniformLocation(colorCubeProg, "mvMatrix");
            glUniformMatrix4fv(mvLocation, 1, false, glm::value_ptr(matrix));
        }

        //        glEnable (GL_BLEND);
        //        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                
        glPointSize(4.0);
        
        if (g_bubble_buffer_data.size() > 0) {
          glEnable(GL_PROGRAM_POINT_SIZE);
          glEnableVertexAttribArray(0);
          glVertexAttribPointer(
                                0,                  //Location 0
                                4,                  // size
                                GL_FLOAT,           // type
                                GL_FALSE,           // normalized?
                                0,                  // stride
                                (void*)0            // array buffer offset
                                );
          
          glDrawArrays(GL_POINTS, 0, 4 * g_bubble_buffer_data.size()); // 3 indices starting at 0 -> 1 triangle
          glDisableVertexAttribArray(0);
        }
        ////////////////// End drawing bubbles //////////////////////
        




        glfwPollEvents();
        glfwSwapBuffers(window);
        double currentTime = glfwGetTime();
        nbFrames++;
        if (currentTime - lastTime >= 1.0) { // If last prinf() was more than 1 sec ago
            // printf and reset timer
            std::string title = std::to_string(1000.0 / double(nbFrames)) + "ms/frame        " + std::to_string(deltaT) + "  dt";
            glfwSetWindowTitle(window, title.c_str());
            nbFrames = 0;
            lastTime += 1.0;
        }
        i++;
        
        //        bubbleExporter.update(i, sim.getBubbleTracker());
        //        bubbleExporter.exportSnapshot(i, "bubbles_" + std::to_string(i) + ".mx");

        /*        if (i > 600) {
          bubbleExporter.exportBubbles("bubbles.mx");
          break;
          }*/
    } // Check if the ESC key was pressed or the window was closed
    while (!glfwWindowShouldClose(window));

    std::cout << "Cleaning up!" << std::endl;
    // Close OpenGL window and terminate GLFW
    glfwDestroyWindow(window);
    glfwTerminate();
    glDeleteBuffers(1, &vertexbuffer);

    glDeleteVertexArrays(1, &VertexArrayID);
    exit(EXIT_SUCCESS);
}
Ejemplo n.º 30
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
}