What is the best glMatrixMode() for using GLM? - c++

my next question(or problem) in line is that when i load a model with glm, im able to see through parts of the model for example: if there were two mountains one in front of the other, i could see through the nearer mountain.
i would show a picture but it wouldnt be understandable since the texture doesnt work.
heres that problem here:
OLDER STUFF:vvvvvvvvvvvvvvvvvvvvvvv
all im wondering is: what is the best Matrix mode for using glm?
i have been used to GL_PROJECTION but its giving me too many problems when loading my model
and with GL_MODELVIEW im not able to move the camera back
i am also wondering: if i use GL_MODELVIEW, then how can i move the "camera" in the scene? is there a way to maybe setup one since ima have to eventually?
EDIT: alright heres some code to give you guys some kind of vision:
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <assert.h>
#include <vector>
#include <glm/glm.h>
#include <glm/glmint.h>
#include "Item.hpp"
#include "Player.hpp"
///GOLD WAVE
using namespace std;
///GLOBAL VARIABLES
vector<sf::Sprite> SpriteList;
vector<GLMmodel*> ModelList;
vector<GLuint> _texture;
vector<Item*> DefItemList;
Player *pPlayer=new Player();
sf::RenderWindow GameWind(sf::VideoMode(800,600,32),"Carperon Game Window",sf::Style::Titlebar);
sf::View GameView(sf::FloatRect(0,0,25,18.75));//65x45 and 8x 0,0,65,45
///PROTOTYPE FUNCTIONS
void SFMLcreate();
void SFMLdraw();
void GLMcreate();
void GLdraw();
GLuint LoadTexture();
void GLiniti();
void ITEMdefault();
///////////////////////////////////STOP PROTOTYPES//////////////////////////////
//////////////////////////////////FUNCTIONS//////////////////////////////////
int main()
{
GLiniti();
SFMLcreate();
GLMcreate();
ITEMdefault();
sf::Event EventMain;
vector<sf::Sprite> ShowingBag;
sf::Image isbItem[45],iseItem[6];
sf::Sprite sbItem[45],seItem[6];
int BagSlotX[45] {0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30,0,15,30};
int BagSlotY[45] {0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30,0,0,0,15,15,15,30,30,30};
int EquipSlotY[6] {0,15,30,0,15,30};
bool BagUpdate = true;
int click = 0;
///MAIN PLAYER
pPlayer->PlayerCreate("Molma");
pPlayer->EquipFill(DefItemList[0]);
pPlayer->AddItem(DefItemList[1]);
pPlayer->AddItem(DefItemList[2]);
pPlayer->AddItem(DefItemList[3]);
pPlayer->AddItem(DefItemList[4]);
while(GameWind.IsOpened())
{
while(GameWind.GetEvent(EventMain))
{
//If its closed
if(EventMain.Type==sf::Event::Closed)
{
//Close the whole thing!
//GameWind.Close();
GameWind.Close();
}
}
float MouseX = (GameWind.GetInput().GetMouseX()/32.f);
float MouseY = (GameWind.GetInput().GetMouseY()/32.f);
if(GameWind.GetInput().IsKeyDown(sf::Key::Escape))
{
GameWind.Close();
//GameWind.Close();
}
/////////////////////////////BEGIN INPUT/////////////////////////////////////////////////
if(GameWind.GetInput().IsKeyDown(sf::Key::Return))
{
pPlayer->RandHealth();
BagUpdate = true;
}
if(GameWind.GetInput().IsKeyDown(sf::Key::Z))
{
pPlayer->GetHit();
}
if(GameWind.GetInput().IsMouseButtonDown(sf::Mouse::Right)&&click<=0)
{
for(int a=0;a<pPlayer->Bag.size();++a)
{
if(MouseX>((17.f+(BagSlotX[a]))/16.f)&&MouseX<(((32.f+(BagSlotX[a]))/16.f))&&MouseY>((60.f+(BagSlotY[a]))/16.f)&&MouseY<(((75.f+(BagSlotY[a]))/16.f)))
{
pPlayer->ItemUse(pPlayer->Bag[a],a);
BagUpdate = true;
click=20;
//cout << "Item used!" << endl;
}
}
for(int b=0;b<6;++b)
{
if(MouseX>2.f/16.f&&MouseX<17.f/16.f&&MouseY>((60.f+(EquipSlotY[b]))/16.f)&&MouseY<((75.f+(EquipSlotY[b]))/16.f)&&pPlayer->EqSpot[b]->get_Type()!="Blank Spot")
{
pPlayer->Unequip(pPlayer->EqSpot[b],DefItemList[0],b);
BagUpdate = true;
click=20;
}
}
}
///////////////////////////////END INPUT/////////////////////////////////////////////////
//////////////////////////////AUTO FUNCTIONS//////////////////////////////////////////////
pPlayer->Guarding();
pPlayer->HitTiming();
if(BagUpdate)
{
for(int a=0;a<pPlayer->Bag.size();++a)
{
isbItem[a].LoadFromFile("Graphics/Items.png");
sbItem[a].SetImage(isbItem[a]);
sbItem[a].SetPosition(((17.f+(BagSlotX[a]))/16.f),((60.f+(BagSlotY[a]))/16.f));
}
for(int b=0;b<6;++b)
{
iseItem[b].LoadFromFile("Graphics/Items.png");
seItem[b].SetImage(iseItem[b]);
seItem[b].SetPosition(2.f/16.f,((60.f+(EquipSlotY[b]))/16.f));
}
BagUpdate=false;
}
if(click>0)
{
click-=1;
}
SpriteList[22].SetPosition(MouseX,MouseY);
GameWind.SetView(GameView);
GLdraw();
SFMLdraw();
for(int a=((pPlayer->get_BagShow())*9);a<((pPlayer->get_BagShow()*9)+9);++a)//18-27=A
{
if(a<pPlayer->Bag.size())
{
sbItem[a].Resize(15.f/16.f,15.f/16.f);
sbItem[a].SetSubRect(sf::IntRect((pPlayer->Bag[a]->get_Index()*15),0,((pPlayer->Bag[a]->get_Index()*15)+15),15));
GameWind.Draw(sbItem[a]);
//cout << "Items Drawn! Position: " << BagSlotX[a] << "," << BagSlotY[a] << "Item: " << a << endl;
//image pos resize subrect
}
}
for(int b=((pPlayer->get_EquipShow())*3);b<((pPlayer->get_EquipShow()*3)+3);++b)
{
seItem[b].Resize(15.f/16.f,15.f/16.f);
seItem[b].SetSubRect(sf::IntRect((pPlayer->EqSpot[b]->get_Index()*15),0,((pPlayer->EqSpot[b]->get_Index()*15)+15),15));
GameWind.Draw(seItem[b]);
}
GameWind.Draw(SpriteList[16]);
GameWind.Draw(SpriteList[20]);
GameWind.Draw(SpriteList[21]);
GameWind.Draw(SpriteList[22]);
GameWind.Display();
GameWind.SetFramerateLimit(60);
}
return EXIT_SUCCESS;
}
void SFMLcreate()
{
sf::Image iStatBack,iStatWindow,ipHealth,ipEnergy,ipStr,ipDex,ipInt,ipEnd,ipCrit,ipSwd,ipAxe,ipBow,ipStar,ipWand,ipStaff,ipBag,ipEquip,ipSkills,ipNumHP,ipNumEP,ipGuard,ipRank,ipRankXP,iCursor;
sf::Sprite StatBack,StatWindow,pHealth,pEnergy,pStr,pDex,pInt,pEnd,pCrit,pSwd,pAxe,pBow,pStar,pWand,pStaff,pBag,pEquip,pSkills,pNumHP,pNumEP,pGuard,pRank,pRankXP,Cursor;
sf::Font MainFont;
//LoadFromFile
iStatBack.LoadFromFile("Graphics/Player Stats/Stats Back.png");
iStatWindow.LoadFromFile("Graphics/Player Stats/StatWindow2.png");
ipHealth.LoadFromFile("Graphics/Player Stats/Health.png");
ipEnergy.LoadFromFile("Graphics/Player Stats/Energy.png");
ipStr.LoadFromFile("Graphics/Player Stats/Strength.png");
ipDex.LoadFromFile("Graphics/Player Stats/Dexterity.png");
ipInt.LoadFromFile("Graphics/Player Stats/Intellegence.png");
ipEnd.LoadFromFile("Graphics/Player Stats/Endurance.png");
ipCrit.LoadFromFile("Graphics/Player Stats/Critical.png");
ipSwd.LoadFromFile("Graphics/Player Stats/Sword Mast.png");
ipAxe.LoadFromFile("Graphics/Player Stats/Axe Mast.png");
ipBow.LoadFromFile("Graphics/Player Stats/Bow Mast.png");
ipStar.LoadFromFile("Graphics/Player Stats/Star Mast.png");
ipWand.LoadFromFile("Graphics/Player Stats/Wand Mast.png");
ipStaff.LoadFromFile("Graphics/Player Stats/Staff Mast.png");
ipBag.LoadFromFile("Graphics/Player Stats/Bag.png");
ipEquip.LoadFromFile("Graphics/Player Stats/Bag.png");
ipSkills.LoadFromFile("Graphics/Player Stats/Skill.png");
ipNumHP.LoadFromFile("Graphics/Player Stats/Number HE.png");
ipNumEP.LoadFromFile("Graphics/Player Stats/Number HE.png");
ipGuard.LoadFromFile("Graphics/Player Stats/Guard.png");
ipRank.LoadFromFile("Graphics/Player Stats/Rank.png");
ipRankXP.LoadFromFile("Graphics/Player Stats/RankXP.png");
iCursor.LoadFromFile("Graphics/Cursor.png");
//SetSmooth()
ipStr.SetSmooth(false);
ipDex.SetSmooth(false);
ipInt.SetSmooth(false);
ipEnd.SetSmooth(false);
ipCrit.SetSmooth(false);
ipSwd.SetSmooth(false);
ipAxe.SetSmooth(false);
ipBow.SetSmooth(false);
ipStar.SetSmooth(false);
ipWand.SetSmooth(false);
ipStaff.SetSmooth(false);
ipSkills.SetSmooth(false);
ipHealth.SetSmooth(false);
ipEnergy.SetSmooth(false);
ipGuard.SetSmooth(false);
ipNumHP.SetSmooth(false);
ipNumEP.SetSmooth(false);
ipRankXP.SetSmooth(false);
ipRank.SetSmooth(false);
//SetImage!!
StatBack.SetImage(iStatBack);
StatWindow.SetImage(iStatWindow);
pHealth.SetImage(ipHealth);
pEnergy.SetImage(ipEnergy);
pStr.SetImage(ipStr);
pDex.SetImage(ipDex);
pInt.SetImage(ipInt);
pEnd.SetImage(ipEnd);
pCrit.SetImage(ipCrit);
pSwd.SetImage(ipSwd);
pAxe.SetImage(ipAxe);
pBow.SetImage(ipBow);
pStar.SetImage(ipStar);
pWand.SetImage(ipWand);
pStaff.SetImage(ipStaff);
pBag.SetImage(ipBag);
pEquip.SetImage(ipEquip);
pSkills.SetImage(ipSkills);
pNumHP.SetImage(ipNumHP);
pNumEP.SetImage(ipNumEP);
pGuard.SetImage(ipGuard);
pRank.SetImage(ipRank);
pRankXP.SetImage(ipRankXP);
Cursor.SetImage(iCursor);
//SetPosition(x,y)!!
StatBack.SetPosition(0,0);
StatWindow.SetPosition(-5.f/16.f,-5.f/16.f);
pHealth.SetPosition(5.f/16.f,23.25f/16.f);
pEnergy.SetPosition(5.f/16.f,31.5f/16.f);
pStr.SetPosition(59.f/16.f,23.f/16.f);
pDex.SetPosition(59.f/16.f,35.f/16.f);
pInt.SetPosition(59.f/16.f,47.f/16.f);
pEnd.SetPosition(3.f/16.f,37.f/16.f);
pCrit.SetPosition(32.f/16.f,37.f/16.f);
pSwd.SetPosition(63.f/16.f,21.f/16.f);
pAxe.SetPosition(63.f/16.f,29.f/16.f);
pBow.SetPosition(63.f/16.f,33.f/16.f);
pStar.SetPosition(63.f/16.f,41.f/16.f);
pWand.SetPosition(63.f/16.f,45.f/16.f);
pStaff.SetPosition(63.f/16.f,53.f/16.f);
pBag.SetPosition(2.f/16.f,60.f/16.f);
pEquip.SetPosition(2.f/16.f,60.f/16.f);
pSkills.SetPosition(71.f/16.f,61.f/16.f);
pNumHP.SetPosition(4.f/16.f,22.f/16.f);
pNumEP.SetPosition(4.f/16.f,30.f/16.f);
pGuard.SetPosition(4.f/16.f,22.5f/16.f);
pRank.SetPosition(41.5f/16.f,25.f/16.f);
pRankXP.SetPosition(39.5f/16.f,23.f/16.f);
//VECTOR STORE
SpriteList.push_back(StatWindow);
SpriteList.push_back(pHealth);
SpriteList.push_back(pEnergy);
SpriteList.push_back(pStr);
SpriteList.push_back(pDex);
SpriteList.push_back(pInt);
SpriteList.push_back(pEnd);
SpriteList.push_back(pCrit);
SpriteList.push_back(pSwd);
SpriteList.push_back(pAxe);
SpriteList.push_back(pBow);
SpriteList.push_back(pStar);
SpriteList.push_back(pWand);
SpriteList.push_back(pStaff);
SpriteList.push_back(pBag);
SpriteList.push_back(pEquip);
SpriteList.push_back(pSkills);
SpriteList.push_back(pNumHP);
SpriteList.push_back(pNumEP);
SpriteList.push_back(pGuard);
SpriteList.push_back(pRank);
SpriteList.push_back(pRankXP);
SpriteList.push_back(Cursor);
}
void SFMLdraw()
{
//////////////////////////////STAT RESIZE/SUBRECT///////////////////////////////////////
SpriteList[1].SetSubRect(sf::IntRect(0,0,120,12)); //30,3
SpriteList[2].SetSubRect(sf::IntRect(0,0,120,12)); //30,3
SpriteList[3].SetSubRect(sf::IntRect(pPlayer->get_Str()*28,0,(pPlayer->get_Str()*28)+28,7)); //28,7
SpriteList[4].SetSubRect(sf::IntRect(pPlayer->get_Dex()*28,0,(pPlayer->get_Dex()*28)+28,7)); //28,7
SpriteList[5].SetSubRect(sf::IntRect(pPlayer->get_Int()*28,0,(pPlayer->get_Int()*28)+28,7)); //28,7
SpriteList[6].SetSubRect(sf::IntRect(pPlayer->get_End()*28,0,(pPlayer->get_End()*28)+28,7)); //28,7
SpriteList[7].SetSubRect(sf::IntRect(pPlayer->get_Crit()*28,0,(pPlayer->get_Crit()*28)+28,7)); //28,7
SpriteList[8].SetSubRect(sf::IntRect(pPlayer->get_Sword()*18,0,(pPlayer->get_Sword()*18)+18,3)); //18,3
SpriteList[9].SetSubRect(sf::IntRect(pPlayer->get_Axe()*18,0,(pPlayer->get_Axe()*18)+18,3)); //18,3
SpriteList[10].SetSubRect(sf::IntRect(pPlayer->get_Bow()*18,0,(pPlayer->get_Bow()*18)+18,3)); //18,3
SpriteList[11].SetSubRect(sf::IntRect(pPlayer->get_Star()*18,0,(pPlayer->get_Star()*18)+18,3)); //18,3
SpriteList[12].SetSubRect(sf::IntRect(pPlayer->get_Wand()*18,0,(pPlayer->get_Wand()*18)+18,3)); //18,3
SpriteList[13].SetSubRect(sf::IntRect(pPlayer->get_Staff()*18,0,(pPlayer->get_Staff()*18)+18,3)); //18,3
SpriteList[14].SetSubRect(sf::IntRect((pPlayer->get_BagShow()*60)+120,0,(pPlayer->get_BagShow()*60)+180,48));
SpriteList[15].SetSubRect(sf::IntRect(pPlayer->get_EquipShow()*60,0,(pPlayer->get_EquipShow()*60)+60,48));
SpriteList[16].SetSubRect(sf::IntRect(pPlayer->get_SkillShow()*30,0,(pPlayer->get_SkillShow()*30)+30,64));
SpriteList[17].SetSubRect(sf::IntRect(pPlayer->get_Health()*7,0,(pPlayer->get_Health()*7)+7,5));
SpriteList[18].SetSubRect(sf::IntRect(pPlayer->get_Energy()*7,0,(pPlayer->get_Energy()*7)+7,5));
SpriteList[19].SetSubRect(sf::IntRect(0,0,128,20));
SpriteList[20].SetSubRect(sf::IntRect(pPlayer->get_Rank()*14,0,(pPlayer->get_Rank()*14)+14,6));//10
SpriteList[21].SetSubRect(sf::IntRect(pPlayer->get_tRankXPN()*18,0,(pPlayer->get_tRankXPN()*18)+18,10));//16
/////////////////////RESIZE PART
SpriteList[0].Resize(410.f/16.f,310.f/16.f);
SpriteList[1].Resize(pPlayer->get_tHealth()/64.f,12.f/64.f);
SpriteList[2].Resize(pPlayer->get_tEnergy()/64.f,12.f/64.f);
SpriteList[3].Resize(28.f/16.f,7.f/16.f);
SpriteList[4].Resize(28.f/16.f,7.f/16.f);
SpriteList[5].Resize(28.f/16.f,7.f/16.f);
SpriteList[6].Resize(28.f/16.f,7.f/16.f);
SpriteList[7].Resize(28.f/16.f,7.f/16.f);
SpriteList[8].Resize(18.f/16.f,3.f/16.f);
SpriteList[9].Resize(18.f/16.f,3.f/16.f);
SpriteList[10].Resize(18.f/16.f,3.f/16.f);
SpriteList[11].Resize(18.f/16.f,3.f/16.f);
SpriteList[12].Resize(18.f/16.f,3.f/16.f);
SpriteList[13].Resize(18.f/16.f,3.f/16.f);
SpriteList[14].Resize(60.f/16.f,48.f/16.f);
SpriteList[15].Resize(60.f/16.f,48.f/16.f);
SpriteList[16].Resize(30.f/16.f,64.f/16.f);
SpriteList[17].Resize(7.f/16.f,5.f/16.f);
SpriteList[18].Resize(7.f/16.f,5.f/16.f);
SpriteList[19].Resize(pPlayer->get_tGuard()/64.f,20.f/64.f);
SpriteList[20].Resize(14.f/16.f,6.f/16.f);
SpriteList[21].Resize(18.f/16.f,10.f/16.f);
SpriteList[22].Resize(15.f/16.f,15.f/16.f);
///////////////////////////////////END RESIZE/SUBRECT!!!////////////////////////////////
////////////////////////////////////DONT TOUCH/////////////////////////////////////////
///////////////////////////////NOW YOU CAN TOUCH//////////////////////////////////////////
//////////////////////////////DRAW STARTS///////////////////////////////////////////////
GameWind.Draw(SpriteList[0]);
GameWind.Draw(SpriteList[19]);
GameWind.Draw(SpriteList[1]);
GameWind.Draw(SpriteList[17]);
GameWind.Draw(SpriteList[2]);
GameWind.Draw(SpriteList[18]);
GameWind.Draw(SpriteList[3]);
GameWind.Draw(SpriteList[4]);
GameWind.Draw(SpriteList[5]);
GameWind.Draw(SpriteList[6]);
GameWind.Draw(SpriteList[7]);
GameWind.Draw(SpriteList[8]);
GameWind.Draw(SpriteList[9]);
GameWind.Draw(SpriteList[10]);
GameWind.Draw(SpriteList[11]);
GameWind.Draw(SpriteList[12]);
GameWind.Draw(SpriteList[13]);
GameWind.Draw(SpriteList[14]);
GameWind.Draw(SpriteList[15]);
}
void GLMcreate()
{
GLMmodel* World = glmReadOBJ("3Dobject/WorldMap3Dv1.obj");
glmUnitize(World);
glmScale(World,1);
}
void GLdraw()
{
GameWind.SetActive();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
////////AMBIENT LIGHT
GLfloat AmbientColor[] = {0.05f,0.05f,0.2f,1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,AmbientColor);
////////POSITIONED LIGHT
GLfloat LightColor0[] = {0.5f,0.5f,0.5f,1.0f};
GLfloat LightPos0[] = {4.0f,4.0f,0.0f,1.0f};
glLightfv(GL_LIGHT0,GL_DIFFUSE,LightColor0);
glLightfv(GL_LIGHT0,GL_POSITION,LightPos0);
////////DIRECTED LIGHT
GLfloat LightColor1[] = {0.9f,0.9f,0.6f,1.0f};
/////Coming from direction (x,y,z)
GLfloat LightPos1[] = {-1.0f,0.5f,0.5f,0.0f};
glLightfv(GL_LIGHT1,GL_DIFFUSE,LightColor1);
glLightfv(GL_LIGHT1,GL_POSITION,LightPos1);
///DRAWING MODELS
}
void GLiniti()
{
GameWind.PreserveOpenGLStates(true);
GameWind.ShowMouseCursor(false);
glClearDepth(1.f);
glClearColor(0.2f,0.2f,0.8f,1.f);
/////z buffer
glEnable(GL_POLYGON_STIPPLE);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_FRONT);
glFrontFace(GL_CW);
glShadeModel(GL_SMOOTH);
glDepthMask(GL_TRUE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glDepthFunc(GL_LEQUAL);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50.f,(double)800 / (double)600,200.f,0.f);
glTranslatef(0.f, 0.f, -10.0f);
}
GLuint LoadTexture(sf::Image image)
{
GLuint Texture;
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,image.GetWidth(),image.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE,image.GetPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
return Texture;
}
void ITEMdefault()
{
Blank *BlankSpot=new Blank();
BlankSpot->ItemCreate(0,0,0,0,0,0,0);
///TEST ITEMS
Weapon *sword=new Weapon();
sword->ItemCreate(0,0,0,sf::Randomizer::Random(0,5),1,0,sf::Randomizer::Random(1,4));
Armor *sword2=new Armor();
sword2->ItemCreate(0,0,0,sf::Randomizer::Random(0,5),2,0,sf::Randomizer::Random(1,4));
Necklace *sword3=new Necklace();
sword3->ItemCreate(0,0,0,sf::Randomizer::Random(0,5),3,0,sf::Randomizer::Random(1,4));
Consume *hppotion=new Consume();
hppotion->ItemCreate(0,0,0,6,83,0,6);
DefItemList.push_back(BlankSpot);
DefItemList.push_back(sword);
DefItemList.push_back(sword2);
DefItemList.push_back(sword3);
DefItemList.push_back(hppotion);
}

There is not one certain matrix mode you switch OpenGL too. I explained it already in this post OpenGL: What is MatrixMode? , which I'll simple copy here:
OpenGL uses several matrices to transform geometry and associated data. Those matrices are:
Modelview – places object geometry in the global, unprojected space
Proection – projects global coordinates into clip space; you may think of it as kind of a lens
Texture – adjusts texture coordinates before; mostly used to implement texture projection (i.e. projecting a texture as if it was a slide in a projector)
Color – adjusts the vertex colors. Seldomly touched at all
All these matrices are used all the time. Since they follow all the same rules OpenGL has only one set of matrix manipulation functions: glPushMatrix, glPopMatrix, glLoadIdentity, glLoadMatrix, glMultMatrix, glTranslate, glRotate, glScale, glOrtho, glFrustum.
glMatrixMode selects on which matrix those operations act upon. Say you wanted to write some C++ namespacing wrapper, it could look like this:
namespace OpenGL {
// A single template class for easy OpenGL matrix mode association
template<GLenum mat> class Matrix
{
public:
void LoadIdentity() const
{ glMatrixMode(mat); glLoadIdentity(); }
void Translate(GLfloat x, GLfloat y, GLfloat z) const
{ glMatrixMode(mat); glTranslatef(x,y,z); }
void Translate(GLdouble x, GLdouble y, GLdouble z) const
{ glMatrixMode(mat); glTranslated(x,y,z); }
void Rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) const
{ glMatrixMode(mat); glRotatef(angle, x, y, z); }
void Rotate(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) const
{ glMatrixMode(mat); glRotated(angle, x, y, z); }
// And all the other matrix manipulation functions
// using overloading to select proper OpenGL variant depending on
// function parameters, and all the other C++ whiz.
// ...
};
//
const Matrix<GL_MODELVIEW> Modelview;
const Matrix<GL_PROJECTION> Projection;
const Matrix<GL_TEXTURE> Texture;
const Matrix<GL_COLOR> Color;
}
Later on in a C++ program you could write then
void draw_something()
{
OpenGL::Projection::LoadIdentity();
OpenGL::Projection::Frustum(...);
OpenGL::Modelview::LoadIdentity();
OpenGL::Modelview::Translate(...);
// drawing commands
}
Unfortunately C++ can't template namespaces, or apply using (or with) on instances (other languages have this), otherwise I'd had written something like (invalid C++)
void draw_something_else()
{
using namespace OpenGL;
with(Projection) { // glMatrixMode(GL_PROJECTION);
LoadIdentity(); // glLoadIdentity();
Frustum(...); // glFrustum(...);
}
with(Modelview) { // glMatrixMode(GL_MODELVIEW);
LoadIdentity(); // glLoadIdentity();
Translate(...); // glTranslatef(...);
}
}
I think this last snipped of (pseudo-)code makes it clear: glMatrixMode is kind of a with statement of OpenGL.
All the matrices are used during rendering!

You move the camera by using glTranslate().

Related

OpenGL 3D-raypicking with high poly meshes

How to implement 3d raypicking in an 3d scene with models that contain high poly meshes?
It takes too much time to iterate over all triangles to perform a triangle-line-intersection test. I know that there exist methods like octree etc. and it should be possible to use these for the models in the scene, but I do not know how I should use these concepts at mesh-level. But if you use an octree at mesh-level, how should one cover problems with polygons, that exceed the boundaries of the octree volumes?
Do you have any advice which method is suitable or recommended for 3d ray-intersections with high poly models for real-time OpenGl applications?
For ray picking rendered objects (like by mouse) the best option is to use the already rendered buffers as there is very little cost of reading them in comparison to ray intersection tests on complex scene. The idea is to render each pick-able rendered object to separate buffer per each info you need about them for example like this:
Depth buffer
this will give you the 3D position of the ray intersection with object.
Stencil buffer
if each object rendered to stencil with its ID (or its index in object list) then you can get the picked object directly.
any other
there are also secondary color attachments and FBO's out there. So you can add any other stuff like normal vector or what ever you need.
If coded right all of this will reduce performance only slightly (even not at all) as you do not need to compute anything its just a single write per fragment per buffer.
The picking itself is easy you just read the corresponding pixel from all the buffers you need and convert to wanted format.
Here simple C++/VCL example using fixed pipeline (no shaders)...
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include "gl_simple.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
void matrix_mul_vector(double *c,double *a,double *b,double w=1.0)
{
double q[3];
q[0]=(a[ 0]*b[0])+(a[ 4]*b[1])+(a[ 8]*b[2])+(a[12]*w);
q[1]=(a[ 1]*b[0])+(a[ 5]*b[1])+(a[ 9]*b[2])+(a[13]*w);
q[2]=(a[ 2]*b[0])+(a[ 6]*b[1])+(a[10]*b[2])+(a[14]*w);
for(int i=0;i<3;i++) c[i]=q[i];
}
//---------------------------------------------------------------------------
class glMouse
{
public:
int sx,sy; // framebuffer position [pixels]
double pos[3]; // [GCS] ray end coordinate (or z_far)
double beg[3]; // [GCS] ray start (z_near)
double dir[3]; // [GCS] ray direction
double depth; // [GCS] perpendicular distance to camera
WORD id; // selected object id
double x0,y0,xs,ys,zFar,zNear; // viewport and projection
double *eye; // camera direct matrix pointer
double fx,fy; // perspective scales
glMouse(){ eye=NULL; for (int i=0;i<3;i++) { pos[i]=0.0; beg[i]=0.0; dir[i]=0.0; } id=0; x0=0.0; y0=0.0; xs=0.0; ys=0.0; fx=0.0; fy=0.0; depth=0.0; }
glMouse(glMouse& a){ *this=a; };
~glMouse(){};
glMouse* operator = (const glMouse *a) { *this=*a; return this; };
// glMouse* operator = (const glMouse &a) { ...copy... return this; };
void resize(double _x0,double _y0,double _xs,double _ys,double *_eye)
{
double per[16];
x0=_x0; y0=_y0; xs=_xs; ys=_ys; eye=_eye;
glGetDoublev(GL_PROJECTION_MATRIX,per);
zFar =0.5*per[14]*(1.0-((per[10]-1.0)/(per[10]+1.0)));
zNear=zFar*(per[10]+1.0)/(per[10]-1.0);
fx=per[0];
fy=per[5];
}
void pick(double x,double y) // test screen x,y [pixels] position
{
int i;
double l;
GLfloat _z;
GLint _id;
sx=x; sy=ys-1.0-y;
// read depth z and linearize
glReadPixels(sx,sy,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&_z); // read depth value
depth=_z; // logarithmic
depth=(2.0*depth)-1.0; // logarithmic NDC
depth=(2.0*zNear)/(zFar+zNear-(depth*(zFar-zNear))); // linear <0,1>
depth=zNear + depth*(zFar-zNear); // linear <zNear,zFar>
// read object ID
glReadPixels(sx,sy,1,1,GL_STENCIL_INDEX,GL_INT,&_id); // read stencil value
id=_id;
// win [pixel] -> GL NDC <-1,+1>
x= (2.0*(x-x0)/xs)-1.0;
y=1.0-(2.0*(y-y0)/ys);
// ray start GL camera [LCS]
beg[2]=-zNear;
beg[1]=(-beg[2]/fy)*y;
beg[0]=(-beg[2]/fx)*x;
// ray direction GL camera [LCS]
for (l=0.0,i=0;i<3;i++) l+=beg[i]*beg[i]; l=1.0/sqrt(l);
for (i=0;i<3;i++) dir[0]=beg[0]*l;
// ray end GL camera [LCS]
pos[2]=-depth;
pos[1]=(-pos[2]/fy)*y;
pos[0]=(-pos[2]/fx)*x;
// convert to [GCS]
matrix_mul_vector(beg,eye,beg);
matrix_mul_vector(pos,eye,pos);
matrix_mul_vector(dir,eye,dir,0.0);
}
};
//---------------------------------------------------------------------------
// camera & mouse
double eye[16],ieye[16]; // direct view,inverse view and perspective matrices
glMouse mouse;
// objects
struct object
{
WORD id; // unique non zero ID
double m[16]; // direct model matrix
object(){}; object(object& a){ *this=a; }; ~object(){}; object* operator = (const object *a) { *this=*a; return this; }; /*object* operator = (const object &a) { ...copy... return this; };*/
};
const int objs=7;
object obj[objs];
// textures
GLuint txr=-1;
//---------------------------------------------------------------------------
void matrix_inv(double *a,double *b) // a[16] = Inverse(b[16])
{
double x,y,z;
// transpose of rotation matrix
a[ 0]=b[ 0];
a[ 5]=b[ 5];
a[10]=b[10];
x=b[1]; a[1]=b[4]; a[4]=x;
x=b[2]; a[2]=b[8]; a[8]=x;
x=b[6]; a[6]=b[9]; a[9]=x;
// copy projection part
a[ 3]=b[ 3];
a[ 7]=b[ 7];
a[11]=b[11];
a[15]=b[15];
// convert origin: new_pos = - new_rotation_matrix * old_pos
x=(a[ 0]*b[12])+(a[ 4]*b[13])+(a[ 8]*b[14]);
y=(a[ 1]*b[12])+(a[ 5]*b[13])+(a[ 9]*b[14]);
z=(a[ 2]*b[12])+(a[ 6]*b[13])+(a[10]*b[14]);
a[12]=-x;
a[13]=-y;
a[14]=-z;
}
//---------------------------------------------------------------------------
void gl_draw()
{
int i; object *o;
double a;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFFFF); // Write to stencil buffer
glStencilFunc(GL_ALWAYS,0,0xFFFF); // Set any stencil to 0
for (o=obj,i=0;i<objs;i++,o++)
{
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(ieye);
glMultMatrixd(o->m);
glStencilFunc(GL_ALWAYS,o->id,0xFFFF); // Set any stencil to object ID
vao_draw();
}
glStencilFunc(GL_ALWAYS,0,0xFFFF); // Set any stencil to 0
glDisable(GL_STENCIL_TEST); // no need fot testing
// render mouse
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(ieye);
a=0.1*mouse.depth;
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3d(mouse.pos[0]+a,mouse.pos[1],mouse.pos[2]);
glVertex3d(mouse.pos[0]-a,mouse.pos[1],mouse.pos[2]);
glVertex3d(mouse.pos[0],mouse.pos[1]+a,mouse.pos[2]);
glVertex3d(mouse.pos[0],mouse.pos[1]-a,mouse.pos[2]);
glVertex3d(mouse.pos[0],mouse.pos[1],mouse.pos[2]+a);
glVertex3d(mouse.pos[0],mouse.pos[1],mouse.pos[2]-a);
glEnd();
Form1->Caption=AnsiString().sprintf("%.3lf , %.3lf , %.3lf : %u",mouse.pos[0],mouse.pos[1],mouse.pos[2],mouse.id);
// debug buffer views
if ((Form1->ck_depth->Checked)||(Form1->ck_stencil->Checked))
{
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,txr);
GLfloat *f=new GLfloat[xs*ys],z;
if (Form1->ck_depth ->Checked)
{
glReadPixels(0,0,xs,ys,GL_DEPTH_COMPONENT,GL_FLOAT,f);
for (i=0;i<xs*ys;i++) f[i]=1.0-(2.0*mouse.zNear)/(mouse.zFar+mouse.zNear-(((2.0*f[i])-1.0)*(mouse.zFar-mouse.zNear)));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xs, ys, 0, GL_RED, GL_FLOAT, f);
}
if (Form1->ck_stencil->Checked)
{
glReadPixels(0,0,xs,ys,GL_STENCIL_INDEX,GL_FLOAT,f);
for (i=0;i<xs*ys;i++) f[i]/=float(objs);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xs, ys, 0, GL_GREEN, GL_FLOAT, f);
}
delete[] f;
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glTexCoord2f(1.0,0.0); glVertex2f(+1.0,-1.0);
glTexCoord2f(1.0,1.0); glVertex2f(+1.0,+1.0);
glTexCoord2f(0.0,1.0); glVertex2f(-1.0,+1.0);
glTexCoord2f(0.0,0.0); glVertex2f(-1.0,-1.0);
glEnd();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
}
glFlush();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
int i;
object *o;
gl_init(Handle);
vao_init();
// init textures
glGenTextures(1,&txr);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,txr);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
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);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_COPY);
glDisable(GL_TEXTURE_2D);
// init objects
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-1.5,4.7,-8.0);
for (o=obj,i=0;i<objs;i++,o++)
{
o->id=i+1; // unique non zero ID
glGetDoublev(GL_MODELVIEW_MATRIX,o->m);
glRotatef(360.0/float(objs),0.0,0.0,1.0);
glTranslatef(-3.0,0.0,0.0);
}
for (o=obj,i=0;i<objs;i++,o++)
{
glLoadMatrixd(o->m);
glRotatef(180.0*Random(),Random(),Random(),Random());
glGetDoublev(GL_MODELVIEW_MATRIX,o->m);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
glDeleteTextures(1,&txr);
gl_exit();
vao_exit();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
gl_resize(ClientWidth,ClientHeight);
// obtain/init matrices
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0,0,-15.0);
glGetDoublev(GL_MODELVIEW_MATRIX,ieye);
matrix_inv(eye,ieye);
mouse.resize(0,0,xs,ys,eye);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
gl_draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
gl_draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
{
GLfloat dz=2.0;
if (WheelDelta<0) dz=-dz;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(ieye);
glTranslatef(0,0,dz);
glGetDoublev(GL_MODELVIEW_MATRIX,ieye);
matrix_inv(eye,ieye);
gl_draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
mouse.pick(X,Y);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ck_depthClick(TObject *Sender)
{
gl_draw();
}
//---------------------------------------------------------------------------
Here preview of from left RGB,Depth,Stencil:
Here captured GIF:
the first 3 numbers are the 3D position of picked pixel in [GCS] and the last number in caption is the picked ID where 0 means no object.
The example is using gl_simple,h from here:
simple complete GL+VAO/VBO+GLSL+shaders example in C++
You can ignore the VCL stuff as its not important just port the events to your environment...
So what to do:
rendering
You need add stencil buffer to your GL window pixel format so in my case I just add:
pfd.cStencilBits = 16;
into gl_init() function from gl_simple.h. Also add its bit into glClear and set each objects stencil to its ID Like I did in gl_draw().
picking
I wrote a small glMouse class that do all the heavy lifting. On each change of perspective, view, or viewport call its glMouse::resize function. That will prepare all the constants needed for the computations later. Beware it needs direct camera/view matrix !!!
Now on each mouse movement (or click or whatever) call the glMouse::pick function and then use the results like id which will return the ID picked object was rendered with or pos which is the 3D coordinate in global world coordinates ([GCS]) of the ray object intersection.
The function just read the depth and stencil buffers. Linearize depth like here:
depth buffer got by glReadPixels is always 1
and compute the ray beg,dir,pos,depth in [GCS].
Normal
You got 2 options either render your normal as another buffer which is the simplest and most precise. Or read depths of 2 or more neighboring pixels around picked one compute their 3D positions. From that using cross product compute you normal(s) and average if needed. But this can lead to artifacts on edges.
As mentioned in the comments to boost accuracy you should use linear depth buffer instead of linearized logarithmic like this:
Linear depth buffer
Btw I used the same technique in here (in GDI based SW isometric render):
Improving performance of click detection on a staggered column isometric grid
[Edit1] 8bit stencil buffer
Well these days the reliable stencil bitwidth is only 8bit which limits the number of ids to 255. That is in most cases not enough. A workaround is to render the indexes as colors then store the frame into CPU memory and then render colors normaly. Then when needed using the stored frame for picking. Rendering to texture or color attachment is also a possibility.
[Edit2] some related links
objects moving with mouse
objects moving and orienting with mouse
Use an Octree. Make sure it fits in whole of your mesh.
Also, it sounds like you are assigning each to poly to just one leaf/bucket, which is not right. Assign polys to all leafs/buckets they appear in.

opengl how to make fire move smoothly and without a hole

I'm rendering fire in opengl using freeglut, I created a particlesystem with emmiter and forcefield and they are working well.
I'm going to put the fire in an old train in a university project, I used textured spheres to simulate it.
The code is going to be long , I'm very sorry but all is relevant, here it is :
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <SOIL/SOIL.h>
#include <glm/glm.hpp>
#include <deque> using namespace std;
typedef glm::vec3 Vector3;
struct Force { private :
float strength;
Vector3 orentation; public :
Force(const Vector3 &v,const float &s)
:strength(s),orentation(v)
{
}
Force(const Force &f)
:strength(f.strength),orentation(f.orentation)
{
}
float getStrength() const
{
return strength;
}
Vector3 getOrentation() const
{
return orentation;
} };
class Particle { public :
Vector3 velocity,position;
const float mass;
float *deltatime;
float lifebegin;
Particle(const Vector3 &pos,const float &m,float *dt,const float &life)
:velocity(Vector3()),position(pos),mass(m),deltatime(dt),lifebegin(life)
{
}
void applyforce(const Force &f)
{
Vector3 force=f.getOrentation()*f.getStrength();
Vector3 accleration=force/mass;
velocity+=accleration*(*deltatime);
proceedintime();
}
void proceedintime()
{
position+=velocity*(*deltatime);
}
virtual void draw()const=0;
virtual bool collide(Particle *p)const=0;
virtual ~Particle()
{
} }; class TexturedParticle : public Particle { protected :
unsigned int textureid; public:
TexturedParticle(const Vector3 &pos,const float &m,float *dt,const float &life,const unsigned int &tex)
:Particle(pos,m,dt,life),textureid(tex)
{
}
virtual ~TexturedParticle()
{
}
}; class Emmiter; class ForceField;
class ParticleSystem {
friend class Emmiter;
friend class ForceField; private :
deque<Particle*> particles;
float elapsedtime;
float *deltatime;
float LifeOfParticles;
unsigned short particlesperframe; public :
ParticleSystem(const float &life,float *dt)
:elapsedtime(0),deltatime(dt),LifeOfParticles(life)
{
}
void deleteparticles()
{
float div=fmod(elapsedtime,LifeOfParticles);
if(div==0)
{
deque<Particle*>::const_iterator begin=particles.begin();
deque<Particle*>::const_iterator end=particles.end();
for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
delete (*it);
particles.clear();
}
}
void drawparticl1es()
{
deque<Particle*>::const_iterator begin=particles.begin();
deque<Particle*>::const_iterator end=particles.end();
for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
{
(*it)->proceedintime();
(*it)->draw();
}
elapsedtime+=(*deltatime);
} };
class Emmiter { public :
unsigned short ParticlesPerSecond;
Vector3 position;
ParticleSystem *ps;
unsigned char count;
float *deltatime;
Particle *(*emitfunc)(const Emmiter &em);
Emmiter(const unsigned short &parpersec,const Vector3 &pos,ParticleSystem *p,const unsigned char &c)
:ParticlesPerSecond(parpersec),position(pos),ps(p),count(c)
{
}
unsigned short particlesperframe()const
{
return ParticlesPerSecond*(*deltatime);
}
void emitparticles()const
{
unsigned short numpars=particlesperframe();
Particle *p=0;
for(unsigned char i=0;i<count;i++)
{
for(unsigned short j=0;j<numpars;j++)
{
p=emitfunc(*this);
p->lifebegin=ps->elapsedtime;
ps[i].particles.push_back(p);
}
}
} }; class ForceField { private :
Vector3 center;
float radius,MaxAcceleration;
unsigned char count;
ParticleSystem *pars; public:
ForceField(const Vector3 &cen,const float &r,const float &mf,ParticleSystem *ps,const unsigned char &c);
void applyforceonparticle(Particle *p)const;
void applyforceonsystems()const; };
ForceField::ForceField(const Vector3 &cen,const float &r,const float
&mf,ParticleSystem *ps,const unsigned char &c)
:center(cen),radius(r),MaxAcceleration(mf),count(c),pars(ps) {
}
void ForceField::applyforceonsystems() const {
for(unsigned char i=0;i<count;i++)
{
ParticleSystem p=pars[i];
for(deque<Particle*>::const_iterator it=p.particles.begin();it!=p.particles.end();it++)
{
applyforceonparticle(*it);
}
} }
void ForceField::applyforceonparticle(Particle *p) const {
Vector3 orentation=center-p->position;
float strength=1-orentation.length()/radius;
if(strength<=0)
return;
p->applyforce(Force(orentation,strength*MaxAcceleration*p->mass)); }
class BallParticle:public TexturedParticle { public :
float radius;
BallParticle(const Vector3 &pos,const float &r,const float &m,float *dt,const float &life,const unsigned int &tex)
:TexturedParticle(pos,m,dt,life,tex),radius(r)
{
}
void draw() const
{
glPushMatrix();
glBindTexture(GL_TEXTURE_2D,textureid);
glTranslatef(position.x, position.y, position.z);
glutSolidSphere(radius,10,10);
glPopMatrix();
}
bool collide(Particle *p) const
{
BallParticle *b=dynamic_cast<BallParticle*>(p);
return (b)&&((b->position-position).length()<=b->radius+radius);
} }; using namespace std;
float deltatime; float oldtime; float newtime; GLuint texture;
ParticleSystem pars(1,&deltatime); Emmiter
emmiter(100,Vector3(0,0,0),&pars,1); ForceField
f(Vector3(0,0.5f,0),0.5f,0.1f,&pars,1);
float myrand(const float &min,const float &max) {
return min+(max-min)*(float(rand())/float(RAND_MAX)); }
Particle *emitfunction(const Emmiter &em) {
float x=em.position.x,y=em.position.y;
BallParticle *b=new BallParticle(Vector3(myrand(x-1,x+1),myrand(y-1,y+1),em.position.z),1,2,&deltatime,0.0f,texture);
b->velocity=Vector3(0,1,0);
return b; }
GLuint GetTextId(const char *texture_name) {
return(SOIL_load_OGL_texture(
texture_name,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO
));
}
/* GLUT callback Handlers */ void resize(int width, int height) {
glViewport(0, 0, width, height);
/*glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,(4/3.0f),2,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camera.LookAt();*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,(float)width/(float)height,0.1f,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( 0, 0, 10, 0, 0, 0, 0, 1, 0 ); }
void display() {
glClear(GL_COLOR_BUFFER_BIT);
newtime=glutGet(GLUT_ELAPSED_TIME)/1000;
deltatime=newtime-oldtime;
oldtime=newtime;
pars.drawparticl1es();
glutSwapBuffers(); } void idle() {
emmiter.emitparticles();
f.applyforceonsystems();
pars.deleteparticles();
glutPostRedisplay(); }
void init() {
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 0.0f };
const GLfloat light_diffuse[] = { 1, 0.5f, 0.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
const GLfloat mat_emissive[]={1,0.5f,0,1};
glClearColor(0, 0, 0, 0);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
glMaterialfv(GL_FRONT,GL_EMISSION,mat_emissive);
//glShadeModel(GL_SMOOTH);
//glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE); }
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(300,200);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Fire");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutIdleFunc(idle);
init();
oldtime=glutGet(GLUT_ELAPSED_TIME)/1000;
emmiter.emitfunc=&emitfunction;
emmiter.deltatime=&deltatime;
texture=GetTextId("/home/abd/graphics/fire2.jpg");
glutMainLoop();
return EXIT_SUCCESS;
}
and here is the texture I'm using :
The fire looks somewhat good but I'm still having an empty hole in the middle, also the particles don't move smoothly.
I tried these things :
1-change the strength and radius of the forcefield: didn't work.
2-increasing the number of particles per second : didn't work, still see the hole.
3-I made my particles bigger: well it made the fire look better and the hole almost disappeared(almost, it somewhat goes and come) but I get strange curves around the fire and it's still not moving smoothly.
4-I have double buffering and I made a call to glutPostRedisplay in the idle function , they still don't move smoothly, I tried removing the hint for PERSPECTIVE NICEST and SMOOTH_SHADING_MODEL, I'm using glutSolidSphere which uses new opengl capabilities and I have Nvidia GT9400 with updated driver to the last version, and still they don't move smoothly.
So what to do to solve these two problems ?
PS
because this is for a university project, I don't want code, "where is the mistake" is enough, I can solve it after I know it.
An algorithm is ok but not code.
EDIT
here's a screenshot of the output :
As you can see, there is a small hole in the middle and curves around the fire.
at a first glance it looks like you have to play a bit with the glBlendFunc
https://www.opengl.org/sdk/docs/man2/xhtml/glBlendFunc.xml
here's a nice viewer of what those parameters do
http://www.andersriggelsen.dk/glblendfunc.php

Box2D: Using debugdraw in Helloworld.cpp or a similar basic program?

I'm trying to create a Box2D program, but I need to enable debugdraw to see what's going on. I was thinking in using the Helloworld program included with the Box2D library as a template. Unfortunately, it doesn't use debugdraw, and I can't seem to be able to implement it. Testbed uses it, but it's a bit convoluted and too poorly explained to be used as a template. So could anyone here share an example of Helloworld.cpp (or a similar basic program that uses Box2D) using debugdraw (preferably implemented like in Testbed)?
I'm using VS2013, if that matters.
Thanks and regards.
In case you haven't figured this out already (and for future viewers), the core Box2D library does not have a debug drawing feature that can simply be "enabled." It's a physics engine, not a rendering engine.
That said, you don't have to do everything from scratch. The Testbed has an implementation of debug drawing, and you can make a test that can be run there. Box2D also provides a sort of drawing template, in case you want to implement your own rendering code. Essentially, there are a few callbacks where you can put your code for, say, polygon rendering. Each frame, for each polygon, Box2D will call that callback and your polygon will be rendered on screen!
You asked for a simple example, so here's one using GLFW for windowing and bare-bones OpenGL for what rendering is needed. There are lots of tutorials out there for these, but you don't really need to know anything about them to understand the code.
Main.cpp:
#define GLEW_STATIC
#include <GLFW\glfw3.h>
#include <Box2D\Box2D.h>
#include "Physics.h"
int main() {
// Initialize window (this is GLFW-specific)
GLFWwindow* window;
if (!glfwInit()) return 1;
window = glfwCreateWindow(960, 540, "Box2D Debug Draw", NULL, NULL);
if (!window) {
glfwTerminate();
return 2;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
DebugDraw debugDraw; // Declare an instance of our DebugDraw class so we can actually use it
// Set up Box2D world, bodies, etc. (you should be familiar with most of this)
int velocityIterations = 8;
int positionIterations = 3;
b2World* world;
b2Body* groundBody;
b2Body* testBody;
{
b2Vec2 gravity(0.0f, -10.0f);
world = new b2World(gravity);
world->SetDebugDraw(&debugDraw); // YOU NEED THIS SO BOX2D KNOWS WHERE TO LOOK FOR DRAWING CALLBACKS
debugDraw.SetFlags(b2Draw::e_shapeBit);
}
{
b2BodyDef gbDef;
gbDef.position.Set(0.0f, -10.0f);
groundBody = world->CreateBody(&gbDef);
b2PolygonShape gbShape;
gbShape.SetAsBox(50.0f, 10.0f);
groundBody->CreateFixture(&gbShape, 0.0f);
}
{
b2BodyDef tbDef;
tbDef.type = b2_dynamicBody;
tbDef.position.Set(0.0f, 10.0f);
testBody = world->CreateBody(&tbDef);
b2PolygonShape tbShape;
tbShape.SetAsBox(1.0f, 1.0f);
b2FixtureDef tbFix;
tbFix.shape = &tbShape;
tbFix.density = 1.0f;
tbFix.friction = 0.3f;
testBody->CreateFixture(&tbFix);
}
// Loop until user exits
b2Timer timer;
float last = timer.GetMilliseconds();
while (!glfwWindowShouldClose(window)) {
float now = timer.GetMilliseconds();
world->Step((now - last) / 1000, 8, 3); // Step simulation forward by amount of time since last step
last = now;
glClear(GL_COLOR_BUFFER_BIT); // Clear screen
glPushMatrix(); // Push matrix so we can revert after doing some transformations
glScalef(40.0f / 960.0f, 40.0f / 540.0f, 1.0f); // Zoom out
glTranslatef(0.0f, -5.0f, 0.0f); // Pan up
world->DrawDebugData(); // CALL THE DRAWING CALLBACKS WE SET UP IN PHYSICS CLASS
glPopMatrix(); // Revert transformations
glfwSwapBuffers(window); // Push updated buffers to window
glfwPollEvents(); // Poll user events so OS doesn't think app is frozen
}
// Garbage collection
delete world;
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Physics.h:
#ifndef PHYSICS
#define PHYSICS
#include <Box2D\Box2D.h>
class DebugDraw : public b2Draw { // b2Draw has all the virtual functions that we need to override here
public:
// We won't be implementing all of these, but if we don't declare them here we'll get an override error
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
void DrawTransform(const b2Transform& xf);
};
#endif
Physics.cpp:
#include <GL\glew.h>
#include "Physics.h"
void DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) {
// Standard OpenGL rendering stuff
glColor4f(color.r, color.g, color.b, color.a);
glBegin(GL_POLYGON);
for (int i = 0; i < vertexCount; i++) {
glVertex2f(vertices[i].x, vertices[i].y);
}
glEnd();
}
// We just need to have these to prevent override errors, they don't actually do anything right now
void DebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) {}
void DebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) {}
void DebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) {}
void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) {}
void DebugDraw::DrawTransform(const b2Transform& xf) {}

OpenGL program keeps crashing around glDrawArrays()

I am trying to make a function that displays a GLuint texture. This is what I made so far. It should output a white quad, but it just crashes:
position2 Q_pos[4]={{0,0},
{1,0},
{1,1},
{0,1}};
void blit_texture(GLuint texture,Point mid_pt,Point Scale=Point(1,1,1),
Point rotate_angle=Point(0,0),Point focus_point=Point(0,0))
{
glEnableClientState(GL_VERTEX_ARRAY);
glPushMatrix();
GLtranslate2v(mid_pt);
GLrotate3f(rotate_angle);
GLtranslate2v(focus_point);
glScalef(Scale.x,Scale.y,1);
glColor4f(1,1,1,1);
glVertexPointer( 2, GL_FLOAT, 0, Q_pos );
glDrawArrays( GL_QUADS, 0, 4 );
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
}
I've also made some definitions for points, easier rotating etc...:
#define GLrotate3f(pt) glRotatef(pt.x,1,0,0),glRotatef(pt.y,0,1,0),glRotatef(pt.z,0,0,1)
#define GLtranslate2v(pt) glTranslatef(pt.x,pt.y,0);
#define GLscale2v(pt) glScalef(pt.x,pt.y,0);
class position3
{
public:
float x,y,z;
position3(float X=0,float Y=0,float Z=0){
x=X,y=Y,z=Z;}
void operator=(float num){x=num,y=num,z=num;}
void operator=(position3 pt){
x=pt.x,y=pt.y,z=pt.z;
}
bool operator>(float Min)
{
if (x<Min || y<Min || z<Min) return 0;
return 1;
}
bool operator<(float Max)
{
if (x>Max || y>Max || z>Max) return 0;
return 1;
}
};
class position2
{
public:
float x,y;
position2(float X=0,float Y=0)
{
x=X,y=Y;
}
void operator=(float num){x=num,y=num;}
void operator=(position2 pt){
x=pt.x,y=pt.y;
}
bool operator>(float Min)
{
if (x<Min || y<Min) return 0;
return 1;
}
bool operator<(float Max)
{
if (x>Max || y>Max) return 0;
return 1;
}
};
class color3f
{
public:
float r,g,b;
color3f(float R=0,float G=0,float B=0){
r=R,g=G,b=B;}
void operator=(color3f cl)
{
r=cl.r,g=cl.g,b=cl.b;
}
};
class Point : public position3 , public color3f
{
public:
Point(float X=0,float Y=0,float Z=0,float R=0,float G=0,float B=0)
{
x=X,y=Y,z=Z;
r=R,g=G,b=B;
}
};
If I make it in intermediate mode it works fine, even the texture appears, but when I try to use VAs it can't make a single white quad.
I did a little debugging on it and figured out that if I put exit(42); before the glDrawArrays() call it returns with 42 but if I take it after the glDrawArrays() the program crashes, so it seems that the problem is caused by glDrawArrays().
Here is my initialization:
const int width=640, height=480;
glViewport(0,0,width, height );
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, ((GLfloat)-1), (GLfloat)1);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
Also, is there a method to check if VBOs are supported or not? This because I made a program with them and it worked fine on my pc (with OpenGL 4.2), but when I tried to run it on my friend's computer (with OpenGL 2.1) it crashed.

How to play YUV video in Qt4?

I want to play YUV video sequence by using Qt. Now I am using QPixmap, by using DrawPixel on QPixmap pixel by pixel. However, it can't play the video in real-time. How can I do to improve the speed?
Did you try using the Phonon classes like VideoPlayer?
Take a look at this:
http://doc.qt.io/archives/4.6/phonon-videoplayer.html
Pixel by pixel is about the slowest method to create a picture. It would improve performance a lot if you processed the image data before and used QPixmap's loadFromData() method.
Well, DrawPixel is definetily the worst perfomance solution.
QOpenGLWiget nowadays (Qt 5) could be used for rendering video frames to a texture.
Actually, depending on the video pixel format, it could be either simple texture rendering or a pixel format conversion via shaders with further texture drawing.
The question is old, so I'll leave a sketchy solution just because it took me some time to get to it myself once. So, the simpliest (not best, because lots of optimizations are possible) solution is:
OpenGLDisplayRGB.h
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QScopedPointer>
#include <QException>
/*!
* \brief The OpenGLDisplay class
* Simple OpenGL display, that renders RGBA to texture
*/
class OpenGLDisplayRGB : public QOpenGLWidget, public QOpenGLFunctions
{
Q_OBJECT
public:
explicit OpenGLDisplayRGB(QWidget* parent = nullptr);
~OpenGLDisplayRGB() override;
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void closeEvent(QCloseEvent* e) override;
public:
void DisplayVideoFrame(unsigned char* data, int frameWidth, int frameHeight);
Q_SIGNAL void closed();
private:
struct OpenGLDisplayRGBImpl;
QScopedPointer<OpenGLDisplayRGBImpl> impl;
};
OpenGLDisplayRGB.cpp
#include "OpenGLDisplayRGB.h"
#include <QOpenGLShader>
#include <QOpenGLTexture>
#include <QCoreApplication>
#include <QResizeEvent>
#include <QTimer>
#include <QDebug>
#define ATTRIB_VERTEX 0
#define ATTRIB_TEXTURE 1
namespace
{
//Vertex matrix
static const GLfloat vertexVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
//Texture matrix
static const GLfloat textureVertices[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
}
struct OpenGLDisplayRGB::OpenGLDisplayRGBImpl
{
OpenGLDisplayRGBImpl(QObject* ownerPtr)
: mBufRGB(nullptr)
//, mRepaintTimer(new QTimer(ownerPtr))
, mEnabled(true)
, mShaderProgram(new QOpenGLShaderProgram(ownerPtr))
, mTexture(new QOpenGLTexture(QOpenGLTexture::Target2D))
{ }
unsigned char* mBufRGB;
//QTimer* mRepaintTimer;
bool mEnabled;
QOpenGLShader* mVShader;
QOpenGLShader* mFShader;
QOpenGLShaderProgram* mShaderProgram;
QScopedPointer<QOpenGLTexture> mTexture;
int mTextureUniform;
GLsizei mVideoW, mVideoH;
};
/*************************************************************************/
OpenGLDisplayRGB::OpenGLDisplayRGB(QWidget* parent)
: QOpenGLWidget(parent)
, impl(new OpenGLDisplayRGBImpl(this))
{
setAttribute(Qt::WA_OpaquePaintEvent);
// setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
/*
impl->mRepaintTimer->setInterval(50);
connect(impl->mRepaintTimer, SIGNAL(timeout()), this, SLOT(update()));
impl->mRepaintTimer->start();*/
}
OpenGLDisplayRGB::~OpenGLDisplayRGB()
{
makeCurrent();
}
void OpenGLDisplayRGB::DisplayVideoFrame(unsigned char *data, int frameWidth, int frameHeight)
{
impl->mVideoW = frameWidth;
impl->mVideoH = frameHeight;
impl->mBufRGB = data;
update();
}
void OpenGLDisplayRGB::initializeGL()
{
initializeOpenGLFunctions();
glEnable(GL_DEPTH_TEST);
/* Modern opengl rendering pipeline relies on shaders to handle incoming data.
* Shader: is a small function written in OpenGL Shading Language (GLSL).
* GLSL is the language that makes up all OpenGL shaders.
* The syntax of the specific GLSL language requires the reader to find relevant information. */
impl->mEnabled = impl->mShaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/OpenGL/simple_vertex_shader.v.glsl");
if(!impl->mEnabled)
qDebug() << QString("[Error] Vertex shader failed: %1").arg(impl->mShaderProgram->log());
impl->mShaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/OpenGL/simple_texture_shader.f.glsl");
if(!impl->mEnabled)
qDebug() << QString("[Error] Fragment shader failed: %1").arg(impl->mShaderProgram->log());
// Bind the property vertexIn to the specified location ATTRIB_VERTEX, this property
// has a declaration in the vertex shader source
impl->mShaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX);
// Bind the attribute textureIn to the specified location ATTRIB_TEXTURE, the attribute
// has a declaration in the vertex shader source
impl->mShaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE);
//Link all the shader programs added to
impl->mShaderProgram->link();
//activate all links
impl->mShaderProgram->bind();
// Read the position of the data variable tex_rgb in the shader, the declaration
// of these variables can be seen in
// fragment shader source
impl->mTextureUniform = impl->mShaderProgram->uniformLocation("uSampler");
// Set the value of the vertex matrix of the attribute ATTRIB_VERTEX and format
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices);
// Set the texture matrix value and format of the attribute ATTRIB_TEXTURE
glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
// Enable the ATTRIB_VERTEX attribute data, the default is off
glEnableVertexAttribArray(ATTRIB_VERTEX);
// Enable the ATTRIB_TEXTURE attribute data, the default is off
glEnableVertexAttribArray(ATTRIB_TEXTURE);
impl->mTexture->create();
impl->mTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
impl->mTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
glClearColor (1.0f, 0.0f, 1.0f, 1.0f); // set the background color
}
void OpenGLDisplayRGB::resizeGL(int w, int h)
{
if(h == 0)// prevents being divided by zero
h = 1;// set the height to 1
// Set the viewport
glViewport(0, 0, w, h);
}
void OpenGLDisplayRGB::paintGL()
{
if (!impl->mEnabled || !impl->mBufRGB)
return; //RET
// Load y data texture
// Activate the texture unit GL_TEXTURE0
glActiveTexture(GL_TEXTURE0);
// Use the texture generated from y to generate texture
glBindTexture(GL_TEXTURE_2D, impl->mTexture->textureId());
// Use the memory mBufYuv data to create a real y data texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, impl->mVideoW, impl->mVideoH, 0, GL_RGBA, GL_UNSIGNED_BYTE, impl->mBufRGB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
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);
// Specify y texture to use the new value can only use 0, 1, 2, etc. to represent
// the index of the texture unit, this is the place where opengl is not humanized
//0 corresponds to the texture unit GL_TEXTURE0 1 corresponds to the
// texture unit GL_TEXTURE1 2 corresponds to the texture unit GL_TEXTURE2
glUniform1i(impl->mTextureUniform, 0);
// Use the vertex array way to draw graphics
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void OpenGLDisplayRGB::closeEvent(QCloseEvent *e)
{
emit closed();
e->accept();
}
simple_texture_shader.f.glsl
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void)
{
gl_FragColor = texture2D(uSampler, vTextureCoord);
}
simple_vertex_shader.v.glsl
attribute vec4 vertexIn;
attribute vec2 textureIn;
varying vec2 vTextureCoord;
void main(void)
{
gl_Position = vertexIn;
vTextureCoord = textureIn;
}