// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <common/shader.cpp>
#include <common/texture.cpp>
#include <common/controls.cpp>
#include <common/objloader.cpp>
//#include <common/vboindexer.cpp>
#include <QDebug>
void initGL();
struct BufferData{
GLuint vertexbuffer;
GLuint uvbuffer;
GLuint normalbuffer;
};
struct dataAboutOneModel{
std::vector<glm::vec3> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;
GLuint Texture;
GLuint TextureID;
const char *texturePath;
const char *modelPath;
BufferData BufferModel;
std::vector<GLuint> TexturesAvailable;
std::vector<GLuint> TexturesIDAvailable;
std::vector<std::string> PathToTexturesAvailable;
int CurrectTextureNum;
};
std::vector<std::string> ModelFilenames;
std::vector<std::string> TexutureFilenames;
dataAboutOneModel modelTmp;
BufferData bufferTmp;
GLuint programID;
std::vector<dataAboutOneModel> dataAboutModels;
std::vector<BufferData> BuffersData;
void ActivateBuffer(int numModel);
void initModel(dataAboutOneModel &model);
void loopGLinit(GLuint & programID,GLuint & MatrixID,GLuint & ModelMatrixID, GLuint & ViewMatrixID, GLuint & LightID);
void VertexBind();
void InitArrayPathModelTexture(std::vector<std::string> &ModelFilenamesInit,std::vector<std::string> &TexutureFilenamesInit);
GLuint VertexArrayID;
GLuint MatrixID;
GLuint ViewMatrixID;
GLuint ModelMatrixID;
int main( void )
{
initGL();
InitArrayPathModelTexture(ModelFilenames,TexutureFilenames);
for(int i = 0; i < ModelFilenames.size();i++){
modelTmp.texturePath = TexutureFilenames[i].c_str();
modelTmp.modelPath = ModelFilenames[i].c_str();
initModel(modelTmp);
}
dataAboutModels[0].TexturesAvailable.push_back(dataAboutModels[0].Texture);
dataAboutModels[0].TexturesIDAvailable.push_back(dataAboutModels[0].TextureID);
dataAboutModels[0].TextureID = glGetUniformLocation(programID, "myTextureSampler");
dataAboutModels[0].Texture = loadDDS(TexutureFilenames[1].c_str());
dataAboutModels[0].TexturesAvailable.push_back(dataAboutModels[0].Texture);
dataAboutModels[0].TexturesIDAvailable.push_back(dataAboutModels[0].TextureID);
for(int i = 0 ; i <dataAboutModels.size();i++ )
ActivateBuffer(i);
GLuint LightID = glGetUniformLocation(programID, "LightPosition_worldspace");
glUseProgram(programID);
do{
loopGLinit(programID,MatrixID,ModelMatrixID,ViewMatrixID,LightID);
VertexBind();
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO and shader
for(int i = 0 ; i < BuffersData.size(); i++){
glDeleteBuffers(1, &BuffersData[i].vertexbuffer);
glDeleteBuffers(1, &BuffersData[i].uvbuffer);
glDeleteBuffers(1, &BuffersData[i].normalbuffer);
}
glDeleteProgram(programID);
for(int i = 0 ; i <dataAboutModels.size();i++ )
glDeleteTextures(1, &dataAboutModels[i].Texture);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
void AddAvailableTextures(){
}
void InitArrayPathModelTexture(std::vector<std::string> &ModelFilenamesInit, std::vector<string> &TexutureFilenamesInit){
// TexutureFilenamesInit.push_back("/home/user/DG_Pult_02/Textures/null.dds");
// ModelFilenamesInit.push_back("/home/user/openGL/Generator_Tris01.obj");
/* XML rewrite */
TexutureFilenamesInit.push_back("/home/user/DG_Pult_02/Textures/DG_Pult_Menu_A.dds");
ModelFilenamesInit.push_back("/home/user/DG_Pult_02/Mesh/DG_Pult_Menu.obj");
TexutureFilenamesInit.push_back("/home/user/DG_Pult_02/Textures/null.dds");
ModelFilenamesInit.push_back("/home/user/DG_Pult_02/Mesh/DG_Pult_Body.obj");
TexutureFilenamesInit.push_back("/home/user/DG_Pult_02/Textures/null_button.dds");
ModelFilenamesInit.push_back("/home/user/DG_Pult_02/Mesh/DG_Pult_Button_1.obj");
TexutureFilenamesInit.push_back("/home/user/DG_Pult_02/Textures/null_button.dds");
ModelFilenamesInit.push_back("/home/user/DG_Pult_02/Mesh/DG_Pult_Button_2.obj");
TexutureFilenamesInit.push_back("/home/user/DG_Pult_02/Textures/null_button.dds");
ModelFilenamesInit.push_back("/home/user/DG_Pult_02/Mesh/DG_Pult_Button_3.obj");
/*
Подгрузка текстур и моделей - код различается только путями файлов.
*/
}
void initModel(dataAboutOneModel &model){
model.TextureID = glGetUniformLocation(programID, "myTextureSampler");
model.Texture = loadDDS(model.texturePath);
bool res = loadOBJ(model.modelPath, model.vertices, model.uvs, model.normals);
if(res==true)
dataAboutModels.push_back(model);
else
qDebug() << "Incorrect path *.obj file.";
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
programID = LoadShaders( "/home/user/openGL/StandardShading.vertexshader", "/home/user/openGL/StandardShading.fragmentshader" );
MatrixID = glGetUniformLocation(programID, "MVP");
ViewMatrixID = glGetUniformLocation(programID, "V");
ModelMatrixID = glGetUniformLocation(programID, "M");
}
void VertexBind(){
for(int i = 0; i < BuffersData.size();i++){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, dataAboutModels[i].Texture);
glUniform1i(dataAboutModels[i].TextureID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, BuffersData[i].vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, BuffersData[i].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, BuffersData[i].normalbuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, dataAboutModels[i].vertices.size() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
}
void loopGLinit(GLuint & programID,GLuint & MatrixID,GLuint & ModelMatrixID, GLuint & ViewMatrixID, GLuint & LightID){
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
// Compute the MVP matrix from keyboard and mouse input
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glm::vec3 lightPos = glm::vec3(4,4,4);
glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
}
void ActivateBuffer(int numModel){
dataAboutOneModel modelTmpAB = dataAboutModels[numModel];
glGenBuffers(1, &bufferTmp.vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, bufferTmp.vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, modelTmpAB.vertices.size() * sizeof(glm::vec3), &modelTmpAB.vertices[0], GL_STATIC_DRAW);
//bufferTmp.uvbuffer;
glGenBuffers(1, &bufferTmp.uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, bufferTmp.uvbuffer);
glBufferData(GL_ARRAY_BUFFER, modelTmpAB.uvs.size() * sizeof(glm::vec2), &modelTmpAB.uvs[0], GL_STATIC_DRAW);
//bufferTmp.normalbuffer;
glGenBuffers(1, &bufferTmp.normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, bufferTmp.normalbuffer);
glBufferData(GL_ARRAY_BUFFER, modelTmpAB.normals.size() * sizeof(glm::vec3), &modelTmpAB.normals[0], GL_STATIC_DRAW);
BuffersData.push_back(bufferTmp);
}
void initGL(){
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return ;
}
glfwWindowHint(GLFW_SAMPLES, 32);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Пульт управления", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return ;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return ;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Hide the mouse and enable unlimited mouvement
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set the mouse at the center of the screen
glfwPollEvents();
// glfwSetCursorPos(window, 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);
}
void nextTexture(){
qDebug() << "NextTexture";
if(dataAboutModels[0].TexturesAvailable.size() > 1){
if( dataAboutModels[0].CurrectTextureNum < dataAboutModels[0].TexturesAvailable.size()){
dataAboutModels[0].Texture = dataAboutModels[0].TexturesAvailable[dataAboutModels[0].CurrectTextureNum];
dataAboutModels[0].TextureID = dataAboutModels[0].TexturesAvailable[dataAboutModels[0].CurrectTextureNum];
dataAboutModels[0].CurrectTextureNum++;
}else{
dataAboutModels[0].CurrectTextureNum =0;
nextTexture();
}
}
}
</code>
Фрагментный шейдер:
<code>
#version 330 core
// Interpolated values from the vertex shaders
in vec2 UV;
in vec3 Position_worldspace;
in vec3 Normal_cameraspace;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;
// Ouput data
out vec3 color;
// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;
uniform mat4 MV;
uniform vec3 LightPosition_worldspace;
void main(){
// Light emission properties
// You probably want to put them as uniforms
vec3 LightColor = vec3(1,1,1);
float LightPower = 50.0f;
// Material properties
vec3 MaterialDiffuseColor = texture( myTextureSampler, UV ).rgb;
vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * MaterialDiffuseColor;
vec3 MaterialSpecularColor = vec3(0.3,0.3,0.3);
// Distance to the light
float distance = length( LightPosition_worldspace - Position_worldspace );
// Normal of the computed fragment, in camera space
vec3 n = normalize( Normal_cameraspace );
// Direction of the light (from the fragment to the light)
vec3 l = normalize( LightDirection_cameraspace );
// Cosine of the angle between the normal and the light direction,
// clamped above 0
// - light is at the vertical of the triangle -> 1
// - light is perpendicular to the triangle -> 0
// - light is behind the triangle -> 0
float cosTheta = clamp( dot( n,l ), 0 ,1 );
// Eye vector (towards the camera)
vec3 E = normalize(EyeDirection_cameraspace);
// Direction in which the triangle reflects the light
vec3 R = reflect(-l,n);
// Cosine of the angle between the Eye vector and the Reflect vector,
// clamped to 0
// - Looking into the reflection -> 1
// - Looking elsewhere -> < 1
float cosAlpha = clamp( dot( E,R ), 0,1 );
color =
// Ambient : simulates indirect lighting
MaterialAmbientColor +
// Diffuse : "color" of the object
MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) +
// Specular : reflective highlight, like a mirror
MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance);
}