Exemple #1
0
void RenderManager::render(const QString& object_name, bool wireframe) {
	for (auto it = objects[object_name].begin(); it != objects[object_name].end(); ++it) {
		GLuint texId = it.key();
		
		// vaoを作成
		it->createVAO();

		if (texId > 0) {
			// テクスチャなら、バインドする
			glBindTexture(GL_TEXTURE_2D, texId);
			glUniform1i(glGetUniformLocation(program, "textureEnabled"), 1);
			glUniform1i(glGetUniformLocation(program, "tex0"), 0);
		} else {
			glUniform1i(glGetUniformLocation(program, "textureEnabled"), 0);
		}

		if (wireframe) {
			glUniform1i(glGetUniformLocation(program, "wireframeEnalbed"), 1);
		} else {
			glUniform1i(glGetUniformLocation(program, "wireframeEnalbed"), 0);
		}

		// 描画
		glBindVertexArray(it->vao);
		glDrawArrays(GL_TRIANGLES, 0, it->vertices.size());

		glBindVertexArray(0);
	}
}
void SceneRenderer::renderModel(GeoModel3D model)
{
	GLuint vaoID;
	GLuint sampler_loc = 4;
	std::vector<GLModel3DData> modelData = model.retrieveMeshes();

	for (std::vector<GLModel3DData>::iterator m = modelData.begin(); m != modelData.end(); m++)
	{
		try
		{
			vaoID = object_vao_map.at(m->getMeshID());
		}
		catch (std::out_of_range ex)
		{
			// if errors here ensure to create VAOs
			createVAO(model);
			vaoID = object_vao_map.at(m->getMeshID());
		}
		glBindVertexArray(vaoID); // Bind our Vertex Array Object

		glActiveTexture(GL_TEXTURE0);
		shader->BindAttribLocation(sampler_loc, "texture1");
		glBindTexture(GL_TEXTURE_2D, m->texture);

		tinyobj::mesh_t mesh = m->getMeshData();
		glDrawElements(GL_TRIANGLES, mesh.indices.size(), GL_UNSIGNED_INT, 0);
	}
}
Exemple #3
0
void VAOManager::regenerateInstancedVAO()
{
    cleanInstanceVAOs();

    enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS };
    for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
    {
        video::E_VERTEX_TYPE tp = IrrVT[i];
        if (!vbo[tp] || !ibo[tp])
            continue;
        GLuint vao = createVAO(vbo[tp], ibo[tp], tp);
        glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeThreeTex]);
        VAOInstanceUtil<InstanceDataThreeTex>::SetVertexAttrib();
        InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeThreeTex)] = vao;

        vao = createVAO(vbo[tp], ibo[tp], tp);
        glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeFourTex]);
        VAOInstanceUtil<InstanceDataFourTex>::SetVertexAttrib();
        InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeFourTex)] = vao;

        vao = createVAO(vbo[tp], ibo[tp], tp);
        glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeShadow]);
        VAOInstanceUtil<InstanceDataSingleTex>::SetVertexAttrib();
        InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeShadow)] = vao;

        vao = createVAO(vbo[tp], ibo[tp], tp);
        glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeRSM]);
        VAOInstanceUtil<InstanceDataSingleTex>::SetVertexAttrib();
        InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeRSM)] = vao;

        vao = createVAO(vbo[tp], ibo[tp], tp);
        glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeGlow]);
        VAOInstanceUtil<GlowInstanceData>::SetVertexAttrib();
        InstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(tp, InstanceTypeGlow)] = vao;

        glBindVertexArray(0);
    }



}
void AppManager::init(){
    /* Initialize the library */
    if (glfwInit() != GL_TRUE) {
        THROW_EXCEPTION("Failed to initialize GLFW");
    }
    glfwSetErrorCallback(error_callback);
    
    createOpenGLContext();
    setOpenGLStates();
    createFBO();
    createProgram();
    createVAO();
    
    applyInitial();
}
void STKMeshSceneNode::updatevbo()
{
    for (unsigned i = 0; i < Mesh->getMeshBufferCount(); ++i)
    {
        scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
        if (!mb)
            continue;
        GLMesh &mesh = GLmeshes[i];
        glDeleteBuffers(1, &(mesh.vertex_buffer));
        glDeleteBuffers(1, &(mesh.index_buffer));
        glDeleteVertexArrays(1, &(mesh.vao));

        fillLocalBuffer(mesh, mb);
        mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
    }
}
void STKMeshSceneNode::updateGL()
{
    if (isGLInitialized)
        return;
    for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
    {
        scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
        if (!mb)
            continue;
        GLMesh &mesh = GLmeshes[i];

        irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
        video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
        video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);


        if (!rnd->isTransparent())
        {
            Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
            Material* material2 = NULL;
            if (mb->getMaterial().getTexture(1) != NULL)
                material2 = material_manager->getMaterialFor(mb->getMaterial().getTexture(1), mb);
            Material::ShaderType MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType(), material, material2);
            if (!immediate_draw)
                InitTextures(mesh, MatType);
        }
        else if (!immediate_draw)
            InitTexturesTransparent(mesh);

        if (!immediate_draw && irr_driver->hasARB_base_instance())
        {
            std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb);
            mesh.vaoBaseVertex = p.first;
            mesh.vaoOffset = p.second;
        }
        else
        {
            fillLocalBuffer(mesh, mb);
            mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
            glBindVertexArray(0);
        }
    }
    isGLInitialized = true;
}
void RenderManager::render(const QString& object_name) {
	for (auto it = objects[object_name].begin(); it != objects[object_name].end(); ++it) {
		GLuint texId = it.key();
		
		// vaoを作成
		it->createVAO();

		if (texId > 0) {
			// テクスチャなら、バインドする
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, texId);
			glUniform1i(glGetUniformLocation(programs["pass1"], "textureEnabled"), 1);
			glUniform1i(glGetUniformLocation(programs["pass1"], "tex0"), 0);
		} else {
			glUniform1i(glGetUniformLocation(programs["pass1"], "textureEnabled"), 0);
		}

		if (it->lighting) {
			glUniform1i(glGetUniformLocation(programs["pass1"], "lighting"), 1);
		}
		else {
			glUniform1i(glGetUniformLocation(programs["pass1"], "lighting"), 0);
		}

		if (useShadow) {
			glUniform1i(glGetUniformLocation(programs["pass1"], "useShadow"), 1);
			if (softShadow) {
				glUniform1i(glGetUniformLocation(programs["pass1"], "softShadow"), 1);
			}
			else {
				glUniform1i(glGetUniformLocation(programs["pass1"], "softShadow"), 0);
			}
		} else {
			glUniform1i(glGetUniformLocation(programs["pass1"], "useShadow"), 0);
		}

		// 描画
		glBindVertexArray(it->vao);
		glDrawArrays(GL_TRIANGLES, 0, it->vertices.size());

		glBindVertexArray(0);
	}
}
Exemple #8
0
/**
 * This function is called once before the first call to paintGL() or resizeGL().
 */
void GLWidget3D::initializeGL()
{
	// init glew
	GLenum err = glewInit();
	if (err != GLEW_OK) {
		qDebug() << "Error: " << glewGetErrorString(err);
	}

	// load shaders
	Shader shader;
	program = shader.createProgram("shaders/vertex.glsl", "shaders/fragment.glsl");
	glUseProgram(program);

	// set the clear color for the screen
	qglClearColor(QColor(113, 112, 117));

	// load a triangle model
	OBJLoader::load("models/triangle.obj", vertices);
	createVAO(vertices, vao);
}
Exemple #9
0
void VBORenderManager::renderVAO(RenderSt& renderSt,bool cleanVertex){
	//printf("renderVAO numVert %d texNum %d vao %d numVertVert %d\n",renderSt.numVertex,renderSt.texNum,renderSt.vao,renderSt.vertices.size());
	// 1. Create if necessary
	if(renderSt.numVertex!=renderSt.vertices.size()&&renderSt.vertices.size()>0){
		if(renderSt.numVertex!=-1){
			cleanVAO(renderSt.vbo,renderSt.vao);
		}
		// generate vao/vbo
		createVAO(renderSt.vertices,renderSt.vbo,renderSt.vao,renderSt.numVertex);
		if(cleanVertex)
			renderSt.vertices.clear();
	}
	// 2. Render
	// 2.1 TEX
	int mode=renderSt.shaderMode;
	if((mode&mode_TexArray)==mode_TexArray){
		// MULTI TEX
		mode=mode&(~mode_TexArray);//remove tex array bit
		glActiveTexture(GL_TEXTURE8);

		glBindTexture(GL_TEXTURE_2D,0); 
		glBindTexture(GL_TEXTURE_2D_ARRAY, renderSt.texNum);
		glActiveTexture(GL_TEXTURE0);
		glUniform1i (glGetUniformLocation (program, "tex_3D"), 8);
	}else{
		glBindTexture(GL_TEXTURE_2D, renderSt.texNum);
	}
	// 2.2 mode
	//if(renderSt.texNum==0){
		//glUniform1i (glGetUniformLocation (program, "mode"), 1|(renderSt.shaderMode&0xFF00));//MODE: same modifiers but just color (renderSt.shaderMode&0xFF00)
	//}else{
		glUniform1i (glGetUniformLocation (program, "mode"), mode);
	//}

	glUniform1i (glGetUniformLocation (program, "tex0"), 0);//tex0: 0

	glBindVertexArray(renderSt.vao);
	glDrawArrays(renderSt.geometryType,0,renderSt.numVertex);
	glBindVertexArray(0);
}
void GraphicModel::loadDatafromFile(char * filename)
{
	FileHandle fh;
	FileError ferror;
	PackageHeader * pkH = new PackageHeader();
	ChunkHeader * CDM = new ChunkHeader();
	ChunkHeader * VBO = new ChunkHeader();
	ChunkHeader * TRI = new ChunkHeader();
	ChunkHeader * TEXRGB = new ChunkHeader();
	CDM_Header * ModelHeader = new CDM_Header();

	////////////////////////////////////READ PACKAGE//////////////////////////////

	ferror = File::open(fh,filename,FILE_READ);
	assert(ferror == FILE_SUCCESS);

	ferror= File::read(fh,pkH,sizeof(PackageHeader));
	assert(ferror == FILE_SUCCESS);

	if (pkH->numChunks > 0)
	{
		ferror= File::read(fh,CDM,sizeof(ChunkHeader));
		assert(ferror == FILE_SUCCESS);

		ferror= File::read(fh,ModelHeader,sizeof(CDM_Header));
		assert(ferror == FILE_SUCCESS);
	}

	if (pkH->numChunks > 1)
	{
		////////////////////////////////////VBOS///////////////////////////////////////
		ferror= File::read(fh,VBO,sizeof(ChunkHeader));
		assert(ferror == FILE_SUCCESS);

		int totalsize = VBO->chunkSize/ sizeof(FBX_Vertex_vsn);
		this->model_vert.reserve(totalsize);
		FBX_Vertex_vsn * tempRead = new FBX_Vertex_vsn();

		for (int i=0; i< totalsize; i++)
		{
			ferror= File::read(fh,tempRead,sizeof(FBX_Vertex_vsn));

			this->model_vert.push_back(*tempRead);
		}

	}

	if (pkH->numChunks > 2)
	{
		/////////////////////////////////TRIANGLE LIST///////////////////////////////

		ferror= File::read(fh,TRI,sizeof(ChunkHeader));
		assert(ferror == FILE_SUCCESS);

		int totalsize = TRI->chunkSize/ sizeof(VBO_Trilist);
		this->model_trilist.reserve(totalsize);
		VBO_Trilist * tempRead = new VBO_Trilist();

		for (int i=0; i< totalsize; i++)
		{
			ferror= File::read(fh,tempRead,sizeof(VBO_Trilist));

			this->model_trilist.push_back(*tempRead);
		};

	}

	//////////////////////////////CREATE VAO with TRILIST and VBOs////////////////////////
	createVAO();
	

	if (pkH->numChunks > 3 && ModelHeader->incTex)
	{
		////////////////////////////////////TEXTURE//////////////////////////////////////
		ferror= File::read(fh,TEXRGB,sizeof(ChunkHeader));
		assert(ferror == FILE_SUCCESS);

		TEX_Header * texHeader = new TEX_Header();
		ferror = File::read(fh, texHeader,sizeof(TEX_Header));
		
		assert(ferror == FILE_SUCCESS);
		
		int size = TEXRGB->chunkSize - sizeof(TEX_Header);
		char * texBuffer = (char *)malloc(size);

		ferror = File::read(fh, texBuffer,size);

		assert(ferror == FILE_SUCCESS);

		ferror = File::close(fh);

		loadTexturefromBuffer(texBuffer,*texHeader);

		free (texBuffer);
	}
	else
	{
		//loadTexture(texName)
	}


	delete	pkH;
	delete  CDM;		
	delete  VBO;		
	delete  TRI;		
	delete  TEXRGB;		
	delete	ModelHeader;
}
Exemple #11
0
void initvaostate(GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
	switch (irr_driver->getPhase())
	{
	case SOLID_NORMAL_AND_DEPTH_PASS:
		if (mesh.vao_first_pass)
			return;
		if (type == irr_driver->getShader(ES_NORMAL_MAP))
		{
			mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::NormalMapShader::attrib_position, MeshShader::NormalMapShader::attrib_texcoord, -1, -1, MeshShader::NormalMapShader::attrib_tangent, MeshShader::NormalMapShader::attrib_bitangent, -1, mesh.Stride);
		}
		else if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
		{
			mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::ObjectPass1Shader::attrib_position, MeshShader::ObjectRefPass1Shader::attrib_texcoord, -1, MeshShader::ObjectPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride);
		}
		else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
		{
			mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::GrassPass1Shader::attrib_position, MeshShader::GrassPass1Shader::attrib_texcoord, -1, MeshShader::GrassPass1Shader::attrib_normal, -1, -1, MeshShader::GrassPass1Shader::attrib_color, mesh.Stride);
		}
		else
		{
			mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::ObjectPass1Shader::attrib_position, -1, -1, MeshShader::ObjectPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride);
		}
		return;
	case SOLID_LIT_PASS:
		if (mesh.vao_second_pass)
			return;
		if (type == irr_driver->getShader(ES_SPHERE_MAP))
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::SphereMapShader::attrib_position, -1, -1, MeshShader::SphereMapShader::attrib_normal, -1, -1, -1, mesh.Stride);
		}
		else if (type == irr_driver->getShader(ES_SPLATTING))
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::SplattingShader::attrib_position, MeshShader::SplattingShader::attrib_texcoord, MeshShader::SplattingShader::attrib_second_texcoord, -1, -1, -1, -1, mesh.Stride);
		}
		else if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::ObjectRefPass2Shader::attrib_position, MeshShader::ObjectRefPass2Shader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
		}
		else if (type == irr_driver->getShader(ES_OBJECTPASS_RIMLIT))
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::ObjectRimLimitShader::attrib_position, MeshShader::ObjectRimLimitShader::attrib_texcoord, -1, MeshShader::ObjectRimLimitShader::attrib_normal, -1, -1, -1, mesh.Stride);
		}
		else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::GrassPass2Shader::attrib_position, MeshShader::GrassPass2Shader::attrib_texcoord, -1, -1, -1, -1, MeshShader::GrassPass2Shader::attrib_color, mesh.Stride);
		}
		else if (type == irr_driver->getShader(ES_OBJECT_UNLIT))
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::ObjectUnlitShader::attrib_position, MeshShader::ObjectUnlitShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
		}
        else if (type == irr_driver->getShader(ES_CAUSTICS))
        {
            mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
                MeshShader::CausticsShader::attrib_position, MeshShader::CausticsShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
        }
		else if (mesh.textures[1])
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::DetailledObjectPass2Shader::attrib_position, MeshShader::DetailledObjectPass2Shader::attrib_texcoord, MeshShader::DetailledObjectPass2Shader::attrib_second_texcoord, -1, -1, -1, -1, mesh.Stride);
		}
		else if (!mesh.textures[0])
		{
		  mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
			  MeshShader::UntexturedObjectShader::attrib_position, -1, -1, -1, -1, -1, MeshShader::UntexturedObjectShader::attrib_color, mesh.Stride);
		}
		else
		{
			mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::ObjectPass2Shader::attrib_position, MeshShader::ObjectPass2Shader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
		}
		return;
	case GLOW_PASS:
		if (mesh.vao_glow_pass)
			return;
		mesh.vao_glow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::ColorizeShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride);
		return;
	case TRANSPARENT_PASS:
		if (mesh.vao_first_pass)
			return;
		if (type == irr_driver->getShader(ES_BUBBLES))
		{
			mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::BubbleShader::attrib_position, MeshShader::BubbleShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
		}
        else if (World::getWorld()->getTrack()->isFogEnabled())
        {
            mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
                MeshShader::TransparentFogShader::attrib_position, MeshShader::TransparentFogShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
        }
		else
		{
			mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
				MeshShader::TransparentShader::attrib_position, MeshShader::TransparentShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
		}
		return;
	case DISPLACEMENT_PASS:
		if (mesh.vao_displace_pass)
			return;
        mesh.vao_displace_mask_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::DisplaceShader::attrib_position,-1, -1, -1, -1, -1, -1, mesh.Stride);
		mesh.vao_displace_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::DisplaceShader::attrib_position, MeshShader::DisplaceShader::attrib_texcoord, MeshShader::DisplaceShader::attrib_second_texcoord, -1, -1, -1, -1, mesh.Stride);
		return;
    case SHADOW_PASS:
        if (mesh.vao_shadow_pass)
            return;
        if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
        {
            mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::RefShadowShader::attrib_position, MeshShader::RefShadowShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
        }
        /*else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
        {
            mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::GrassShadowShader::attrib_position, MeshShader::GrassShadowShader::attrib_texcoord, -1, -1, -1, -1, MeshShader::GrassShadowShader::attrib_color, mesh.Stride);
        }*/
        else
        {
            mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::ShadowShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride);
        }
        return;
	}
}
Exemple #12
0
/**
 * Load an OBJ file and create the corresponding VAO.
 */
void GLWidget3D::loadOBJ(const QString& filename)
{
	OBJLoader::load(filename, vertices);
	createVAO(vertices, vao);
}
Exemple #13
0
    void init()
    {
        vf::skinned_geom_t::vao    = createVAO(ARRAY_SIZE(vf::descSkinnedGeom),  vf::descSkinnedGeom,  0, NULL);
        vf::static_geom_t::vao     = createVAO(ARRAY_SIZE(vf::descStaticGeom),   vf::descStaticGeom,   0, NULL);
        vf::p2_vertex_t::vao       = createVAO(ARRAY_SIZE(vf::fmtdesc_p2),       vf::fmtdesc_p2,       0, NULL);
        vf::p2uv2_vertex_t::vao    = createVAO(ARRAY_SIZE(vf::fmtdesc_p2uv2),    vf::fmtdesc_p2uv2,    0, NULL);
        vf::p2uv3_vertex_t::vao    = createVAO(ARRAY_SIZE(vf::fmtdesc_p2uv3),    vf::fmtdesc_p2uv3,    0, NULL);
        vf::p2cu4_vertex_t::vao    = createVAO(ARRAY_SIZE(vf::fmtdesc_p2cu4),    vf::fmtdesc_p2cu4,    0, NULL);
        vf::p2uv2cu4_vertex_t::vao = createVAO(ARRAY_SIZE(vf::fmtdesc_p2uv2cu4), vf::fmtdesc_p2uv2cu4, 0, NULL);
        vf::p3_vertex_t::vao       = createVAO(ARRAY_SIZE(vf::fmtdesc_p3),       vf::fmtdesc_p3,       0, NULL);
        vf::p3cu4_vertex_t::vao    = createVAO(ARRAY_SIZE(vf::fmtdesc_p3cu4),    vf::fmtdesc_p3cu4,    0, NULL);
        vf::p3uv2cu4_vertex_t::vao = createVAO(ARRAY_SIZE(vf::fmtdesc_p3uv2cu4), vf::fmtdesc_p3uv2cu4, 0, NULL);
        glGenVertexArrays(1, &vf::empty_geom_t::vao);

        prgUI               = res::createProgramFromFiles("UI.vert",         "UI.frag");
        prgRasterCubic      = res::createProgramFromFiles("VG.Cubic.vert",   "VG.Mask.Cubic.frag");
        prgRasterCubicAA    = res::createProgramFromFiles("VG.Cubic.vert",   "VG.Mask.Cubic.AA.frag");
        prgPaintSolid       = res::createProgramFromFiles("VG.Paint.vert",   "VG.Paint.Solid.frag");
        prgPaintLinGradient = res::createProgramFromFiles("VG.Paint.vert",   "VG.Paint.LinearGradient.frag");

        const char* version       = "#version 430\n\n";
        const char* enableColor   = "#define ENABLE_COLOR\n";
        const char* enableTexture = "#define ENABLE_TEXTURE\n";
        const char* enableVGAA    = "#define EDGE_AA 1\n";

        const char* headers[3] = {version};
        size_t numHeaders;

        for (size_t i=0; i<STD_PROGRAM_COUNT; ++i)
        {
            numHeaders = 1;
            if (i&gfx::STD_FEATURE_COLOR)
            {
                headers[numHeaders++] = enableColor;
            }
            if (i&gfx::STD_FEATURE_TEXTURE)
            {
                headers[numHeaders++] = enableTexture;
            }
            stdPrograms[i] = res::createProgramFromFiles("MESH.std.vert", "MESH.std.frag", numHeaders, headers);
        }
        
        headers[1] = enableColor;
        prgLine  = res::createProgramFromFiles("MESH.Line.vert",  "MESH.std.frag", 2, headers);
        prgPoint = res::createProgramFromFiles("MESH.Point.vert", "MESH.std.frag", 2, headers);
        prgRect  = res::createProgramFromFiles("MESH.Rect.vert",  "MESH.std.frag", 2, headers);

        headers[1] = enableVGAA;
        prgNanoVG   = res::createProgramFromFiles("NanoVG.vert",  "NanoVG.frag", 1, headers);
        prgNanoVGAA = res::createProgramFromFiles("NanoVG.vert",  "NanoVG.frag", 2, headers);

        gfx::vertex_element_t ve[2] = {
            {0, 0, 0, GL_FLOAT,         4, GL_FALSE, GL_FALSE},
            {1, 0, 1, GL_UNSIGNED_BYTE, 4, GL_FALSE, GL_TRUE },
        };

        GLuint divs[2] = {1, 1};

        vaoRect = gfx::createVAO(2, ve, 2, divs);

        vgGArena = etlsf_create(VG_BUFFER_SIZE, GFX_MAX_ALLOCS);
        glGenBuffers(1, &buffer);
        glNamedBufferStorageEXT(buffer, VG_BUFFER_SIZE, 0, GL_MAP_WRITE_BIT);

        vg::defaultFont = vg::createFont(anonymousProBTTF, sizeof(anonymousProBTTF), 16);
        vg::nvgDefFont  = nvgCreateFontMem(vg::ctx, "default", anonymousProBTTF, sizeof(anonymousProBTTF), 0);
    }