I'm still n00bie so forgive bad practices:
Main.cpp: the code is also heavily commented because this was a hack n' slash testing module
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
// Include GLEW
#include <GL/glew.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
// value_ptr
#include <glm/gtc/type_ptr.hpp>
using namespace glm;
#include "Common/shader.hpp"
#include "Common/texture.hpp"
#include "Common/controls.hpp"
#include "Common/objloader.hpp"
#include "Common/vboindexer.hpp"
#pragma comment(lib,"sfml-window-d")
#pragma comment(lib,"sfml-graphics-d")
#pragma comment(lib,"sfml-audio-d")
#pragma comment(lib,"sfml-network-d")
#pragma comment(lib,"sfml-system-d")
#pragma comment(lib,"assimp")
#pragma comment(lib,"OPENGL32")
#pragma comment(lib,"GLU32")
#pragma comment(lib,"glew64d")
#include <assimp/texture.h>
#include <assimp/scene.h>
#include <assimp/mesh.h>
#include <assimp/importer.hpp>
#include <assimp/PostProcess.h>
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Audio.hpp>
#include <SFML/System.hpp>
#include <SFML/Network.hpp>
#include <iostream>
struct LightProperties
{
//vec3 direction;
vec3 position;
vec3 LightColor ;
float LightPower;
};
/*
find some way to render all objects with the same VBO/mesh at once
right now we create new VBO and bind it regardless that the VBO's are identical if the object has the same mesh.
I prupose a mesh data member/ class that contains a vbo, when loading a mesh for an object( as this will be abstracted a LOT once the
script engine is incorporated with this) it is done through a factory class containing strings and a vector of
all loaded models, thusly if :
class obj
{
mesh* msh;
string meshname
}a,b;
mesh * MESH=MeshManager.LoadMesh(a.meshname);
a.setMesh(MESH);
mesh * MESH2=MeshManager.LoadMesh(b.meshname);
b.setMesh(MESH2);
mesh * MeshManager::loadmesh(string name)
{
if(name already loaded)
return mesh[name];
else
return LoadMeshFromFile(name);
}
if and b load the same mesh no more buffers are allocated
(we can do the same thing for Textures!
even with the next peice!:)
we can go further:
class mesh :public Drawable
{
bool VBOBound;
void draw()
{
if(!VBOBound)
BindVBO();
glDraw(...);
}
};
then we can just sort the renderers rendering list by the meshes they contain
e.g of runtime:
mesh's a,b,c used in a scene repeatedly
Completely unsorted:
draw:
a binds new VBO
b binds new VBO
c binds new VBO
a binds new VBO
b binds new VBO
c binds new VBO
a binds new VBO
b binds new VBO
c binds new VBO
a binds new VBO
b binds new VBO
c binds new VBO
that's 12 VBO binds for 12 objects with only 3 meshes
medium unsorted:
draw:
a binds new VBO
b binds new VBO
c binds new VBO
c doesn't bind new VBO
c doesn't bind new VBO
a binds new VBO
a doesn't binds new VBO
b binds new VBO
c binds new VBO
b binds new VBO
a binds new VBO
b binds new VBO
that's 9 VBO binds for 12 objects with only 3 meshes
where as sorted:
draw:
a binds new VBO
a doesn't binds new VBO
a doesn't binds new VBO
a doesn't binds new VBO
b binds new VBO
b doesn't binds new VBO
b doesn't binds new VBO
b doesn't binds new VBO
c binds new VBO
c doesn't bind new VBO
c doesn't bind new VBO
c doesn't bind new VBO
that's 3 VBO binds for 12 objects with only 3 meshes
that's a third less than a medium scenario
*/
struct Vertex
{
vec3 m_pos;
vec2 m_tex;
vec3 m_normal; //not yet...
vec3 m_tangent;//not yet...
Vertex() {}
Vertex(const vec3& pos, const vec2& tex, const vec3& normal, const vec3& Tangent):
m_pos(pos), m_tex(tex),m_normal(normal), m_tangent(Tangent)
{
}
};
struct ObjectMaterial
{
vec3 MaterialAmbientColor;
vec3 MaterialSpecularColor;
Texture* MeshTexture;
Texture* MeshNormal;
ObjectMaterial()
{
MeshTexture=(MeshNormal=nullptr);
MaterialAmbientColor=vec3(.1f);
MaterialSpecularColor=vec3(.1f);
}
};
struct Mesh
{
private:
friend class MeshManager;
GLuint vertexbuffer;
GLuint uvbuffer;
GLuint normalbuffer;
GLuint tangentbuffer;
GLuint indexbuffer;
bool VBOBound;
bool VBOReleased;
ObjectMaterial ObjMat;
std::vector<unsigned short> indices;
std::vector<glm::vec3> indexed_vertices;
std::vector<glm::vec2> indexed_uvs;
std::vector<glm::vec3> indexed_normals;
std::vector<glm::vec3> tangents;
std::vector<glm::vec3> bitangents;
std::string MeshName;
GLsizei indecessize;
public:
ObjectMaterial& GetObjMat()
{
return ObjMat;
}
void InitVBO()
{
//Generate a buffer for the vertices
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), indexed_vertices.data(), GL_STATIC_DRAW);
//Generate a buffer for the UV coordinates
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW);
//Generate a buffer for the normals
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW);
//Generate a buffer for the tangents
//glGenBuffers(1, &tangentbuffer);
//glBindBuffer(GL_ARRAY_BUFFER, tangentbuffer);
//glBufferData(GL_ARRAY_BUFFER, tangents.size() * sizeof(glm::vec3), &tangents[0], GL_STATIC_DRAW);
//Generate a buffer for the bitangents
//glGenBuffers(1, &bitangentbuffer);
//glBindBuffer(GL_ARRAY_BUFFER, bitangentbuffer);
//glBufferData(GL_ARRAY_BUFFER, bitangents.size() * sizeof(glm::vec3), &bitangents[0], GL_STATIC_DRAW);
// Generate a buffer for the indices
glGenBuffers(1, &indexbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0] , GL_STATIC_DRAW);
}
void BindVBO()
{
if(!VBOBound)
{
VBOBound=true;
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
}
//for now
VBOBound=false;
}
void UnbindVBO()
{//this is called once the mesh has been drawn once or more and another mesh is about to be drawn
VBOBound=false;
}
void UnboundVBO()
{
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
void ReleaseVBO()
{
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
glDeleteBuffers(1, &normalbuffer);
glDeleteBuffers(1, &indexbuffer);
VBOReleased=true;
}
bool LoadFromFile(std::string filename)
{
if(loadAssImp(filename, indices, indexed_vertices, indexed_uvs, indexed_normals,tangents,bitangents,&ObjMat.MeshTexture,&ObjMat.MeshNormal))
{
InitVBO();
MeshName=filename;
indecessize=static_cast<GLsizei>(indices.size());
indices.clear();
indexed_vertices.clear();
indexed_uvs.clear();
indexed_normals.clear();
return true;
}
return false;
}
void Draw()
{
if(!VBOBound)
BindVBO();
glDrawElements(
GL_TRIANGLES, // mode
indecessize, // count
GL_UNSIGNED_SHORT, // type
(void*)0 // element array buffer offset
);
}
Mesh()
{
VBOBound=false;
// InitVBO();
VBOReleased=false;
ObjMat.MeshTexture=nullptr;
}
~Mesh()
{
if(ObjMat.MeshTexture!=nullptr)
delete ObjMat.MeshTexture;
}
};
class MeshManager
{
private:
std::vector<std::pair<Mesh*,std::string>> LoadedMeshes;
public:
//friend class Mesh;
Mesh* LoadMeshFromFile(std::string Filename)
{
//was mesh loaded before?:
for(int i=0;i<LoadedMeshes.size();i++)
{
if(LoadedMeshes[i].second==Filename)
return LoadedMeshes[i].first;
}
//the mesh wasn't loaded before as the filename wasn't found
//loadAssImp(Filename.c_str(),LoadedMeshes.back().first.indices,LoadedMeshes.back().first.indexed_vertices,
// LoadedMeshes.back().first.indexed_uvs,LoadedMeshes.back().first.indexed_normals);
LoadedMeshes.push_back(std::make_pair(new Mesh(),Filename));
LoadedMeshes.back().first->LoadFromFile(Filename);
return LoadedMeshes.back().first;
}
void ReleaseAllVBOs()
{
Destroy();
/*
for(int i=0;i<LoadedMeshes.size();++i)
{
if(!LoadedMeshes[i].first->VBOReleased)
LoadedMeshes[i].first->ReleaseVBO();
}*/
}
void Destroy()
{
for(int i=0;i<LoadedMeshes.size();++i)
{
if(!LoadedMeshes[i].first->VBOReleased)
LoadedMeshes[i].first->ReleaseVBO();
delete LoadedMeshes[i].first;
}
}
};
class DrawableBase
{
public:
virtual void Draw() =0;
};
class BasicDrawable :public DrawableBase
{
private:
Mesh* ObjectMesh;
glm::mat4 ModelMatrix;
ObjectMaterial ObjectMat;
public:
glm::mat4& GetModelMatrix()
{
return ModelMatrix;
}
ObjectMaterial& GetObjMat()
{
return ObjectMesh->GetObjMat();
}
void SetMesh(Mesh* mesh)
{
ObjectMesh=mesh;
}
Mesh* GetMesh()
{
return ObjectMesh;
}
void Draw()
{
ObjectMesh->Draw();
}
void Translate(glm::vec3& by)
{
ModelMatrix=glm::translate(ModelMatrix,by);
}
void SetTranslation(glm::vec3& to)
{
ModelMatrix=glm::translate(glm::mat4(0.5f),to);
}
void Rotate(float angle,glm::vec3& vector)
{
ModelMatrix=glm::rotate<glm::lowp_float>(ModelMatrix,angle,vector);
}
void SetRotation(float angle,glm::vec3& vector)
{
ModelMatrix=glm::rotate<glm::lowp_float>(glm::mat4(0.5f),angle,vector);
}
void Scale(glm::vec3& by)
{
ModelMatrix=glm::scale(ModelMatrix,by);
}
void SetScale(glm::vec3& to)
{
ModelMatrix=glm::scale(glm::mat4(1.0f),to);
}
BasicDrawable()
{
ModelMatrix=glm::mat4(1.0f);
}
}Bob;
std::vector<BasicDrawable*> Objects;
#define Text(notstring) std::string(#notstring)
int main( void )
{
std::cout<<std::string(Text(hello))<<std::endl;
sf::ContextSettings Cs;
Cs.antialiasingLevel=0;
Cs.depthBits=8;
Cs.majorVersion=4;
Cs.minorVersion=4;
Cs.stencilBits=8;
sf::RenderWindow MainWindow = sf::RenderWindow(sf::VideoMode(1024,768),"test",sf::Style::Default,Cs);
float FoV=45.0f;
mat4 ProjectionMatrix = glm::perspective(FoV, 1024.0f / 768.0f, 0.001f, 100.0f);
if(MainWindow.setActive(true))
std::cout<<"What?"<<std::endl;
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
//sf::RenderTexture RT;
//RT.create(1024,768,true);
//if(RT.setActive())
// std::cout<<"What22?"<<std::endl;
//sf::Mouse::setPosition(sf::Vector2i(1024/2, 768/2));
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
// Cull triangles which normal is not towards the camera
glEnable(GL_CULL_FACE);
//GLuint VertexArrayID;
//glGenVertexArrays(1, &VertexArrayID);
//glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "StandardShading.vert", "StandardShading.frag" );
//sf::Shader VertexShader;
//VertexShader.loadFromFile("StandardShading.vertexshader",sf::Shader::Vertex);
// Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "ProjectionMatrix");
GLuint ViewMatrixID = glGetUniformLocation(programID, "ViewMatrix");
GLuint ModelMatrixID = glGetUniformLocation(programID, "ModelMatrix");
// Load the texture
GLuint Texture = loadTexture("uvmap.DDS");
// Get a handle for our "myTextureSampler" uniform
GLuint TextureID = glGetUniformLocation(programID, "myTextureSampler");
// Read our .obj file
// Load it into a VBO
MeshManager G_MeshManager;
//Bob.SetMesh(G_MeshManager.LoadMeshFromFile("suzanne.obj"));
sf::Clock mc;
Bob.SetMesh(G_MeshManager.LoadMeshFromFile("suzanne.obj"));
//Bob.GetMesh()->LoadFromFile("suzanne.obj");
Objects.push_back(&Bob);
BasicDrawable Bob2;
Bob2.SetMesh(G_MeshManager.LoadMeshFromFile("cube.obj"));
//Bob2.SetMesh(new Mesh());
//Bob2.GetMesh()->LoadFromFile("suzanne.obj");
Objects.push_back(&Bob2);
BasicDrawable Bob3;
Bob3.SetMesh(G_MeshManager.LoadMeshFromFile("Sphere.obj"));
Objects.push_back(&Bob3);
BasicDrawable Bob4;
Bob4.SetMesh(G_MeshManager.LoadMeshFromFile("Sphere.obj"));
Objects.push_back(&Bob4);
std::cout<<mc.restart().asSeconds()<<std::endl;
BasicDrawable Bob5;
Bob5.SetMesh(G_MeshManager.LoadMeshFromFile("bigbox.obj"));
Objects.push_back(&Bob5);
// Get a handle for our "LightPosition" uniform
glUseProgram(programID);
GLuint LightPositionID = glGetUniformLocation(programID, "Light.position");
GLuint LightColorID = glGetUniformLocation(programID, "Light.Color");
GLuint LightPowerID = glGetUniformLocation(programID, "Light.Power");
//GLuint Bobmat2MaterialAmbientColorID = glGetUniformLocation(programID, "CurrentObjectsMaterial.MaterialAmbientColor");
//GLuint Bobmat2MaterialSpecularColorID = glGetUniformLocation(programID, "CurrentObjectsMaterial.MaterialSpecularColor");
GLuint BobmatMaterialAmbientColorID = glGetUniformLocation(programID, "CurrentObjectsMaterial.MaterialAmbientColor");
GLuint BobmatMaterialSpecularColorID = glGetUniformLocation(programID, "CurrentObjectsMaterial.MaterialSpecularColor");
Bob.GetObjMat().MaterialAmbientColor=vec3(0.1f,0.1f,0.1f);
Bob.GetObjMat().MaterialSpecularColor=vec3(0.0f,0.0f,.0f);
//ObjectMaterial Bobmat2;
Bob2.GetObjMat().MaterialAmbientColor=vec3(0.1f,0.1f,0.1f);
Bob2.GetObjMat().MaterialSpecularColor=vec3(0.0f,0.0f,.0f);
Bob4.GetObjMat().MaterialAmbientColor=vec3(0.1f,0.1f,0.1f);
Bob4.GetObjMat().MaterialSpecularColor=vec3(0.0f,0.0f,.0f);
Bob3.GetObjMat().MaterialAmbientColor=vec3(0.0f,0.0f,.0f);
Bob3.GetObjMat().MaterialSpecularColor=vec3(0.0f,0.0f,.0f);
Bob5.GetObjMat().MaterialAmbientColor=vec3(0.1f,0.1f,0.1f);
Bob5.GetObjMat().MaterialSpecularColor=vec3(0.1f,0.1f,.1f);
//Bobmat
// For speed computation
sf::Clock clock;
float lastTime = clock.getElapsedTime().asSeconds();
int nbFrames = 0;
glm::vec3 LightPos(0,0,-1);
LightProperties LPT;
LPT.LightColor=vec3(0.5f,0.5f,0.5f);
LPT.LightPower=50;
glUniform3f(LightColorID,LPT.LightColor.x,LPT.LightColor.y,LPT.LightColor.z);
glUniform1f(LightPowerID,LPT.LightPower);
LPT.position=LightPos;
computeMatricesFromInputs();
Bob3.Scale(vec3(10));
for(int i=0;i<Objects.size();++i)
Objects[i]->SetTranslation(glm::vec3(i,0,-2));
Bob4.SetTranslation(glm::vec3(1,0,-2));
Bob5.SetTranslation(glm::vec3(0,-1,0));
//Bob5.SetScale(glm::vec3(1.5,1.5,1.5));
Bob5.SetTranslation(glm::vec3(0,-1,0));
vec3 Scale(1);
//int UseFXaa=1;
//GLuint UseFXaaHandle=glGetUniformLocation(programID, "UseFXaa");
// glUniform1i(UseFXaaHandle,UseFXaa);
sf::Font font;
font.loadFromFile("font.ttf");
sf::Text text;
text.setString("hello bitches!");
text.setFont(font);
text.setCharacterSize(80);
text.setPosition(170.f, 150.f);
text.setColor(sf::Color::White);
//sf::Sprite tex(RT.getTexture());
do{
// Measure speed
float currentTime = clock.getElapsedTime().asSeconds();
nbFrames++;
if ( currentTime - lastTime >= 1.0 )
{ // If last prinf() was more than 1sec ago
// printf and reset
//printf("%f ms/frame\n", 1000.0/double(nbFrames));
std::cout<<"FPS: "<<nbFrames<<std::endl;
nbFrames = 0;
lastTime += 1.0;
}
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//RT.clear(sf::Color(0,0,100,255));
//MainWindow.clear(sf::Color(0.0f, 0.0f, 0.4f, 0.0f));
MainWindow.clear(sf::Color(0,0,100,255));
// Use our shader
glUseProgram(programID);
// Compute the MVP matrix from keyboard and mouse input
// computeMatricesFromInputs();
//glm::mat4 ProjectionMatrix = getProjectionMatrix();
//glm::mat4 ViewMatrix = getViewMatrix();
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, glm::value_ptr(getViewMatrix()));
//light movement
computeMatricesFromInputs();
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W))
{
LPT.position.y+=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S))
{
LPT.position.y-=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A))
{
LPT.position.x-=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D))
{
LPT.position.x+=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Z))
{
LPT.position.z-=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::X))
{
LPT.position.z+=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Q))
{
Scale-=0.001;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::E))
{
Scale+=0.001;
}
Bob3.SetTranslation(LPT.position);
Bob3.Scale(Scale);
}
{
vec3 cammove=vec3(0);
cammove*=getCamDir()*0.001f;
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::I))
{
cammove+=getCamDir()*0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::K))
{
cammove-=getCamDir()*0.001f;
}
// cammove.y=0;
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::U))
{
cammove.y+=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::O))
{
cammove.y-=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::J))
{
cammove.x-=0.001f;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::L))
{
cammove.x+=0.001f;
}
getCamPos()+=cammove;
}
glUniform3f(LightPositionID,LPT.position.x,LPT.position.y,LPT.position.z);
// Bind our texture in Texture Unit 0
for(int i=0;i<Objects.size();++i)
{
if(Objects[i]->GetObjMat().MeshTexture!=nullptr)
Objects[i]->GetObjMat().MeshTexture->Bind(GL_TEXTURE0);
else
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,Texture );
}
glUniform1i(TextureID, 0);
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniform3f(BobmatMaterialAmbientColorID,Objects[i]->GetObjMat().MaterialAmbientColor.x,Objects[i]->GetObjMat().MaterialAmbientColor.y,Objects[i]->GetObjMat().MaterialAmbientColor.z);
glUniform3f(BobmatMaterialSpecularColorID,Objects[i]->GetObjMat().MaterialSpecularColor.x,Objects[i]->GetObjMat().MaterialSpecularColor.y,Objects[i]->GetObjMat().MaterialSpecularColor.z);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE,glm::value_ptr(Objects[i]->GetModelMatrix()));
Objects[i]->Draw();
}
//glUniform3fv(LightID,4,(float*)&LightPos);
// 1st attribute buffer : vertices
// 2nd attribute buffer : UVs
// Swap buffers
//glPushAttrib(GL_ELEMENT_ARRAY_BUFFER);
//glPushAttrib(GL_ARRAY_BUFFER);
//
glBindBuffer(GL_ARRAY_BUFFER,0);
MainWindow.pushGLStates();
MainWindow.resetGLStates();
MainWindow.draw(text);
MainWindow.popGLStates();
//
//glPopAttrib();
//glPopAttrib();
MainWindow.display();
} // Check if the ESC key was pressed or the window was closed
while( !sf::Keyboard::isKeyPressed( sf::Keyboard::Key::Escape )&&MainWindow.isOpen() );
system("pause");
MainWindow.close();
G_MeshManager.ReleaseAllVBOs();
glDeleteProgram(programID);
glDeleteTextures(1, &Texture);
return 0;
}
Controls.cpp (keep in mind this is mostly temporary, an in no way represents my coding style as i'm working
from a tutorial)
// Include GLFW
//#include <GL/glfw.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include "controls.hpp"
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Audio.hpp>
#include <SFML/System.hpp>
#include <SFML/Network.hpp>
glm::mat4 ViewMatrix;
glm::vec3 position = glm::vec3( 0, 0, 5 );
glm::vec3 direction= glm::vec3( 0, 0, 5 );
glm::mat4& getViewMatrix(){
return ViewMatrix;
}
glm::vec3& getCamPos()
{
return position;
}
glm::vec3& getCamDir()
{
return direction;
}
// Initial position : on +Z
// Initial horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// Initial vertical angle : none
float verticalAngle = 0.0f;
// Initial Field of View
float speed = 3.0f; // 3 units / second
float mouseSpeed = 0.005f;
void computeMatricesFromInputs(){
// glfwGetTime is called only once, the first time this function is called]
// Get mouse position
int xpos, ypos;
//glfwGetMousePos(&xpos, &ypos);
xpos=sf::Mouse::getPosition().x;
ypos=sf::Mouse::getPosition().y;
// Reset mouse position for next frame
sf::Mouse::setPosition(sf::Vector2i(1024/2, 768/2));
// Compute new orientation
horizontalAngle += mouseSpeed * float(1024/2 - xpos );
verticalAngle += mouseSpeed * float( 768/2 - ypos );
// Direction : Spherical coordinates to Cartesian coordinates conversion
direction=vec3(
cos(verticalAngle) * sin(horizontalAngle),
sin(verticalAngle),
cos(verticalAngle) * cos(horizontalAngle)
);
// Right vector
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.141592f/2.0f),
0,
cos(horizontalAngle - 3.141592f/2.0f)
);
// Up vector
glm::vec3 up = glm::cross( right, direction );
// Camera matrix
ViewMatrix = glm::lookAt(
position, // Camera is here
position+direction, // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
// For the next frame, the "last time" will be "now"
}
Controls.hpp
#ifndef CONTROLS_HPP
#define CONTROLS_HPP
void computeMatricesFromInputs();
glm::mat4& getViewMatrix();
glm::vec3& getCamPos();
glm::vec3& getCamDir();
#endif
objloader.hpp ( i know, it should be in a source file
)
#ifndef OBJLOADER_H
#define OBJLOADER_H
bool loadOBJ(
const char * path,
std::vector<glm::vec3> & out_vertices,
std::vector<glm::vec2> & out_uvs,
std::vector<glm::vec3> & out_normals
);
#include <vector>
#include <stdio.h>
#include <string>
#include <cstring>
#include <glm/glm.hpp>
#include "texture.hpp"
#include <assimp/Importer.hpp> // C++ importer interface
#include <assimp/scene.h> // Output data structure
#include <assimp/postprocess.h> // Post processing flags
#include <iostream>
bool loadAssImp(
std::string path,
std::vector<unsigned short> & indices,
std::vector<glm::vec3> & vertices,
std::vector<glm::vec2> & uvs,
std::vector<glm::vec3> & normals,
std::vector<glm::vec3> & tangents,
std::vector<glm::vec3> & bitangents,
Texture** MeshDiffuseTexture,
Texture** MeshNormalTexture
){
bool Ret=false;
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate |
aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices |aiProcess_OptimizeMeshes |
aiProcess_CalcTangentSpace |aiProcess_OptimizeGraph| aiProcess_ImproveCacheLocality);
if( !scene) {
std::cout<<"could not load scene: "<<path<<std::endl;
return Ret;
}
Ret=true;
//
//Meshs stuff
//
//for(int U=0;U<scene->mNumMeshes;U++)
{
aiMesh* mesh = scene->mMeshes[0];
// Fill vertices positions
vertices.reserve(mesh->mNumVertices);
for(unsigned int i=0; i<mesh->mNumVertices; i++){
aiVector3D pos = mesh->mVertices[i];
vertices.push_back(glm::vec3(pos.x, pos.y, pos.z));
}
// Fill vertices texture coordinates
uvs.reserve(mesh->mNumVertices);
aiVector3D Zero3D(0,0,0);
for(unsigned int i=0; i<mesh->mNumVertices; i++)
{
aiVector3D UVW = mesh->HasTextureCoords(0) ? (mesh->mTextureCoords[0][i]) : Zero3D ; // Assume only 1 set of UV coords; AssImp supports 8 UV sets.
uvs.push_back(glm::vec2(UVW.x, UVW.y));
//Fill tangents and bitangents
if(mesh->HasTangentsAndBitangents())
{
tangents.push_back(glm::vec3(mesh->mTangents[i].x,mesh->mTangents[i].y,mesh->mTangents[i].z));
bitangents.push_back(glm::vec3(mesh->mBitangents[i].x,mesh->mBitangents[i].y,mesh->mBitangents[i].z));
}
}
// Fill vertices normals
normals.reserve(mesh->mNumVertices);
for(unsigned int i=0; i<mesh->mNumVertices; i++){
aiVector3D n = mesh->mNormals[i];
normals.push_back(glm::vec3(n.x, n.y, n.z));
}
// Fill face indices
indices.reserve(3*mesh->mNumFaces);
for (unsigned int i=0; i<mesh->mNumFaces; i++){
// Assume the model has only triangles AS WE TRIANGULATE MESH AS A POST PROCESS
indices.push_back(mesh->mFaces[i].mIndices[0]);
indices.push_back(mesh->mFaces[i].mIndices[1]);
indices.push_back(mesh->mFaces[i].mIndices[2]);
}
}
//
/// Texture stuff
//
//MeshTexture=new Texture(GL_TEXTURE_2D,
for (unsigned int G = 1 ; G < scene->mNumMaterials ; G++)
{
const aiMaterial* pMaterial = scene->mMaterials[G];
if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
aiString Path;
if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
std::string FullPath;// ="C:/Users/DragonStorm-Coder/Documents/Visual Studio 2012/Projects/GameModules/TestRendererStart/TestRendererStart/";
FullPath =Path.data;
*MeshDiffuseTexture = new Texture(GL_TEXTURE_2D, FullPath.c_str());
Texture* t= *MeshDiffuseTexture;
if (!t->Load()) {
delete *MeshDiffuseTexture;
*MeshDiffuseTexture = nullptr;
Ret = false;
}
else {
//Texture loaded
}
}
}
if (pMaterial->GetTextureCount(aiTextureType_NORMALS) > 0) {
aiString Path;
if (pMaterial->GetTexture(aiTextureType_NORMALS, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
std::string FullPath;// ="C:/Users/DragonStorm-Coder/Documents/Visual Studio 2012/Projects/GameModules/TestRendererStart/TestRendererStart/";
FullPath =Path.data;
*MeshDiffuseTexture = new Texture(GL_TEXTURE_2D, FullPath.c_str());
Texture* t= *MeshDiffuseTexture;
if (!t->Load()) {
delete *MeshDiffuseTexture;
*MeshDiffuseTexture = nullptr;
Ret = false;
}
else {
//Texture loaded
}
}
}
}
// The "scene" pointer will be deleted automatically by "importer"
return Ret;
}
#endif
Shader.cpp
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#include <stdlib.h>
#include <string.h>
#include <GL/glew.h>
#include "shader.hpp"
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open()){
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}else{
//printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
//getchar();
std::cout<<"couldn't open: "<<vertex_file_path<<std::endl;
return 0;
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSourceARB(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShaderARB(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSourceARB(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShaderARB(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> ProgramErrorMessage(InfoLogLength+1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
Shader.hpp
#ifndef SHADER_HPP
#define SHADER_HPP
#include <glm/glm.hpp>
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path);
#endif
Texture.hpp
#ifndef TEXTURE_HPP
#define TEXTURE_HPP
#include <GL/glew.h>
#include <SFML/Graphics.hpp>
GLuint loadTexture(const std::string imagepath);
GLuint loadDDS(const std::string imagepath);
class Texture
{
private:
std::string m_fileName;
GLenum m_textureTarget;
GLuint m_textureObj;
sf::Image Image;
public:
Texture(GLenum TextureTarget, const std::string& FileName)
{
m_textureTarget = TextureTarget;
m_fileName = FileName;
}
bool Load()
{
sf::Image Image;
if (!Image.loadFromFile(m_fileName))
return false;
glGenTextures(1, &m_textureObj);
glBindTexture(m_textureTarget, m_textureObj);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Image.getSize().x, Image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, Image.getPixelsPtr());
// Nice trilinear filtering.
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_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
void Bind(GLenum TextureUnit)
{
glActiveTexture(TextureUnit);
glBindTexture(GL_TEXTURE_2D, m_textureObj);
}
};
#endif
Texture.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glew.h>
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Audio.hpp>
//#include <SFML/System.hpp>
#include <SFML/Network.hpp>
#include <iostream>
#include <fstream>
#ifdef LoadImage
#undef LoadImage
#endif
/*
GLuint loadBMP_custom(const char * imagepath){
printf("Reading image %s\n", imagepath);
// Data read from the header of the BMP file
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
unsigned int width, height;
// Actual RGB data
unsigned char * data;
// Open the file
FILE * file = fopen(imagepath,"rb");
if (!file) {printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar(); return 0;}
// Read the header, i.e. the 54 first bytes
// If less than 54 bytes are read, problem
if ( fread(header, 1, 54, file)!=54 ){
printf("Not a correct BMP file\n");
return 0;
}
// A BMP files always begins with "BM"
if ( header[0]!='B' || header[1]!='M' ){
printf("Not a correct BMP file\n");
return 0;
}
// Make sure this is a 24bpp file
if ( *(int*)&(header[0x1E])!=0 ) {printf("Not a correct BMP file\n"); return 0;}
if ( *(int*)&(header[0x1C])!=24 ) {printf("Not a correct BMP file\n"); return 0;}
// Read the information about the image
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
// Some BMP files are misformatted, guess missing information
if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
if (dataPos==0) dataPos=54; // The BMP header is done that way
// Create a buffer
data = new unsigned char [imageSize];
// Read the actual data from the file into the buffer
fread(data,1,imageSize,file);
// Everything is in memory now, the file wan be closed
fclose (file);
// Create one OpenGL texture
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
// OpenGL has now copied the data. Free our own version
delete [] data;
// Poor filtering, or ...
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// ... nice trilinear filtering.
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_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
// Return the ID of the texture we just created
return textureID;
}
*/
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
GLuint loadDDS(std::string imagepath){
unsigned char header[128];
//std::fstream in(imagepath,std::ios::in |std::ios::binary);
std::basic_fstream<unsigned char> in(imagepath,std::ios::in |std::ios::binary);
//std::string header;
if (!in.is_open()){
//printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar();
std::cout<<"couldn't load DDS file: "<<imagepath<<std::endl;
return 0;
}
for(int i=0;i<128;++i)
{
in.get(header[i]);
}
char filecode[4];
std::fstream in2(imagepath,std::ios::in |std::ios::binary);
in2.get(&filecode[0],4);
in2.close();
if (std::string(filecode).find("DDS")==std::string::npos) {
std::cout<<"Not a Valid DDS"<<imagepath<<std::endl;
return 0;
}
unsigned int height = *(unsigned int*)&(header[12]);
unsigned int width = *(unsigned int*)&(header[16]);
unsigned int linearSize = *(unsigned int*)&(header[20]);
unsigned int mipMapCount = *(unsigned int*)&(header[28]);
unsigned int fourCC = *(unsigned int*)&(header[84]);
unsigned char * buffer;
unsigned int bufsize;
bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
buffer = new unsigned char[bufsize];
for(int i=0;i<bufsize;++i)
in.get(buffer[i]);
in.close();
//fread(buffer, 1, bufsize, fp);
//fclose(fp);
unsigned int components = (fourCC == FOURCC_DXT1) ? 3 : 4;
unsigned int format;
switch(fourCC)
{
case FOURCC_DXT1:
format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case FOURCC_DXT3:
format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case FOURCC_DXT5:
format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
default:
delete[] buffer;
return 0;
}
// Create one OpenGL texture
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
unsigned int offset = 0;
for (unsigned int level = 0; level < mipMapCount && (width || height); ++level)
{
unsigned int size = ((width+3)/4)*((height+3)/4)*blockSize;
glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height,
0, size, buffer + offset);
offset += size;
width /= 2;
height /= 2;
// Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.
if(width < 1) width = 1;
if(height < 1) height = 1;
}
delete [] buffer;
return textureID;
}
GLuint LoadImage(const std::string imagepath)
{
sf::Image Image;
if (!Image.loadFromFile(imagepath))// if the file can't be opened by sfml try and open it as a DDS
{
std::cout<<"Image is not in DDS format or one that is supported by SFML"<<std::endl;
return 0;
}
// Create one OpenGL texture
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Image.getSize().x, Image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, Image.getPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//None:BiLin Near(off),far(off)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//None:BiLin Near(off),far(on)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//None:BiLin Near(on),far(off)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//None:BiLin Near(on),far(on)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//standard:BiLin Near(off),far(off)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
//standard:BiLin Near(off),far(on)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
//standard:BiLin Near(on),far(off)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
//standard:BiLin Near(on),far(on)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
//Trilinear:BiLin Near(off),far(off)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
//Trilinear:BiLin Near(off),far(on)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
//Trilinear:BiLin Near(on),far(on)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
//Trilinear:BiLin Near(on),far(off)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
//Anisotropic full:
GLfloat fLargest;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
//Anisotropic off
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
glGenerateMipmap(GL_TEXTURE_2D);
// Return the ID of the texture we just created
return textureID;
}
GLuint loadTexture(const std::string imagepath){
// Read the file
std::string temp=imagepath.substr(imagepath.find(".")+1);
if(temp=="DDS"||temp=="dds")
return loadDDS(imagepath);
return LoadImage(imagepath);
}
Then all that's left is my shader code, and that's clearly not responsible
Thanks to anyone willing to help, I chose SFML for the purpose of OGL integration, but I probably should of first done this example/test program before writing most of my framework