Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // lab_2_3.cpp : Defines the entry point for the console application.
- //
- #include <iostream>
- #include <GL/glew.h>
- #include <GLFW/glfw3.h>
- #include <chrono>
- #include <glm/glm.hpp>
- #include <glm/gtc/matrix_transform.hpp>
- #include <glm/gtx/transform.hpp>
- #include <glm/vec3.hpp>
- #include <glm/vec4.hpp>
- #include <glm/mat4x4.hpp>
- #include <soil.h>
- using namespace std;
- using namespace glm;
- #pragma comment(lib, "glfw3.lib")
- #pragma comment(lib, "glew32.lib")
- #pragma comment(lib, "opengl32.lib")
- // Матрица модели : единичная матрица (Модель находится в начале координат)
- mat4 ModelMatrix = mat4(1.0f);
- GLFWwindow* g_window;
- GLuint g_shaderProgram;
- GLint g_uMVP;
- GLint g_uMV;
- // Текстуры
- const int countTextures = 2;
- GLuint texIDs[countTextures];
- struct Texture
- {
- const GLchar* fileName; // Имя файла с картинкой
- const GLchar* uniformMapName; // Имя юниформа
- GLint mapLocation; // Идентификатор юниформа
- GLint texUnit;
- Texture(const GLchar* fileName, const GLchar* uniformMapName, GLint texUnit)
- {
- this->fileName = fileName;
- this->uniformMapName = uniformMapName;
- this->texUnit = texUnit;
- }
- };
- Texture textures[countTextures] =
- {
- Texture("C:\\Users\\margo\\source\\repos\\OpenGLDemo2\\x64\\Debug\\1.png", "u_map1", 0),
- Texture("C:\\Users\\margo\\source\\repos\\OpenGLDemo2\\x64\\Debug\\2.png", "u_map2", 1)
- };
- class Model
- {
- public:
- GLuint vbo;
- GLuint ibo;
- GLuint vao;
- GLsizei indexCount;
- };
- Model g_model;
- void generateTexture(const GLchar* file_name, GLint texID)
- {
- GLint texW, texH;
- GLint channels;
- unsigned char* image = SOIL_load_image(file_name, &texW, &texH, &channels, SOIL_LOAD_RGBA);
- cout << SOIL_last_result();
- // Привязка текстуры к цели текстуирования
- glBindTexture(GL_TEXTURE_2D, texID);
- // Задаем изображение текстуры
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texW, texH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
- SOIL_free_image_data(image);
- 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_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- }
- void initTextures()
- {
- // Генерируем id для текстур и сохраняем их в массив
- glGenTextures(2, texIDs);
- for (int i = 0; i < countTextures; i++)
- {
- generateTexture(textures[i].fileName, texIDs[i]);
- textures[i].mapLocation = glGetUniformLocation(g_shaderProgram, textures[i].uniformMapName);
- }
- }
- GLuint createShader(const GLchar* code, GLenum type)
- {
- GLuint result = glCreateShader(type);
- glShaderSource(result, 1, &code, NULL);
- glCompileShader(result);
- GLint compiled;
- glGetShaderiv(result, GL_COMPILE_STATUS, &compiled);
- if (!compiled)
- {
- GLint infoLen = 0;
- glGetShaderiv(result, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen > 0)
- {
- char* infoLog = new char[infoLen];
- glGetShaderInfoLog(result, infoLen, NULL, infoLog);
- cout << "Shader compilation error" << endl << infoLog << endl;
- }
- glDeleteShader(result);
- return 0;
- }
- return result;
- }
- GLuint createProgram(GLuint vsh, GLuint fsh)
- {
- GLuint result = glCreateProgram();
- glAttachShader(result, vsh);
- glAttachShader(result, fsh);
- glLinkProgram(result);
- GLint linked;
- glGetProgramiv(result, GL_LINK_STATUS, &linked);
- if (!linked)
- {
- GLint infoLen = 0;
- glGetProgramiv(result, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen > 0)
- {
- char* infoLog = (char*)alloca(infoLen);
- glGetProgramInfoLog(result, infoLen, NULL, infoLog);
- cout << "Shader program linking error" << endl << infoLog << endl;
- }
- glDeleteProgram(result);
- return 0;
- }
- return result;
- }
- bool createShaderProgram()
- {
- g_shaderProgram = 0;
- const GLchar vsh[] =
- "#version 330\n"
- ""
- "layout(location = 0) in vec2 a_position;"
- "layout(location = 1) in vec2 a_texCoord;"
- ""
- "uniform mat4 u_mv;"
- "uniform mat4 u_mvp;"
- ""
- "out vec3 v_position;"
- "out vec3 v_normal;"
- "out vec2 v_texCoord;"
- ""
- "void main()"
- "{"
- " v_texCoord = a_texCoord;"
- " vec3 position = vec3(a_position[0], sin(a_position[0]*10)*sin(a_position[1]*10)/5, a_position[1]);"
- " v_position = (u_mv * vec4(position, 1.0)).xyz;"
- " v_normal = normalize(transpose(inverse(mat3(u_mv)))*vec3(-cos(10*a_position[0])*sin(10*a_position[1]), "
- " 1.0, -cos(10*a_position[1])*sin(10*a_position[0])));"
- " gl_Position = u_mvp * vec4(position, 1.0);"
- "}"
- ;
- const GLchar fsh[] =
- "#version 330\n"
- ""
- "in vec3 v_position;"
- "in vec3 v_normal;"
- "in vec2 v_texCoord;"
- ""
- "layout(location = 0) out vec4 o_color;"
- ""
- "uniform sampler2D u_map1;"
- "uniform sampler2D u_map2;"
- ""
- "void main()"
- "{"
- " const int br_coef = 20;" // Коэффициент светильности
- " vec3 u_l = vec3(10.0, 10.0, 0.0);" // Положение источника света
- " vec3 n = normalize(v_normal);" // Нормирование нормали
- " vec3 l = normalize(v_position - u_l);" // Поток света
- " float a = dot(-l, n);" // Угол между нормалью и лучом света
- " float d = max(a, 0.1);" // Диффузное освещение
- " vec3 r = reflect(l, n);" // Вектор отражения
- " vec3 e = normalize(-v_position);" // Вектор, направленный в сторону наблюдателя
- " float s = pow(max(dot(r, e), 0.0), br_coef) * int(a >= 0);" // Уничтожение зеркального блика
- "vec4 texel = mix(texture(u_map1, v_texCoord), texture(u_map2, v_texCoord), 0.5);"
- " o_color = vec4(d*texel.xyz + s*vec3(1.0), 1.0);" // Цвет поверхности
- /*"o_color = vec4(texel.xyz, 1.0);"*/
- "}"
- ;
- GLuint vertexShader, fragmentShader;
- vertexShader = createShader(vsh, GL_VERTEX_SHADER);
- fragmentShader = createShader(fsh, GL_FRAGMENT_SHADER);
- g_shaderProgram = createProgram(vertexShader, fragmentShader);
- g_uMVP = glGetUniformLocation(g_shaderProgram, "u_mvp");
- g_uMV = glGetUniformLocation(g_shaderProgram, "u_mv");
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- initTextures();
- return g_shaderProgram != 0;
- }
- bool createModel()
- {
- GLint const m = 100;
- GLfloat vertices[(m + 1) * (m + 1) * 4];
- int k = 0;
- for (int i = 0; i <= m; i++)
- {
- for (int j = 0; j <= m; j += 1)
- {
- vertices[k++] = float(j) / m;
- vertices[k++] = float(i) / m;
- vertices[k++] = float(j) / m;
- vertices[k++] = float(i) / m;
- }
- }
- GLuint indices[m * m * 6];
- k = 0;
- for (int i = 0; i < m; i++)
- {
- for (int j = 0; j < m; j++)
- {
- indices[k++] = (m + 1) * i + j;
- indices[k++] = (m + 1) * i + j + 1;
- indices[k++] = (m + 1) * i + j + m + 2;
- indices[k++] = (m + 1) * i + j + m + 2;
- indices[k++] = (m + 1) * i + j + m + 1;
- indices[k++] = (m + 1) * i + j;
- }
- }
- glGenVertexArrays(1, &g_model.vao);
- glBindVertexArray(g_model.vao);
- glGenBuffers(1, &g_model.vbo);
- glBindBuffer(GL_ARRAY_BUFFER, g_model.vbo);
- glBufferData(GL_ARRAY_BUFFER, (m + 1) * (m + 1) * 4 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
- glGenBuffers(1, &g_model.ibo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_model.ibo);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, m * m * 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);
- g_model.indexCount = m * m * 6;
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (const GLvoid*)0);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (const GLvoid*)(2 * sizeof(GLfloat)));
- return g_model.vbo != 0 && g_model.ibo != 0 && g_model.vao != 0;
- }
- bool init()
- {
- // Set initial color of color buffer to white.
- glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- return createShaderProgram() && createModel();
- }
- void reshape(GLFWwindow* window, int width, int height)
- {
- glViewport(0, 0, width, height);
- }
- void draw(GLfloat delta_draw)
- {
- // Clear color buffer.
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glUseProgram(g_shaderProgram);
- glBindVertexArray(g_model.vao);
- GLfloat near = 0.1;
- GLfloat far = 100.;
- // Проекционная матрица
- mat4 Projection = perspective(
- radians(60.0f), // Угол обзора
- 4.0f / 3.0f, // Соотншение сторон окна
- near, // Ближняя плоскость отсечения
- far // Дальняя плоскость отсечения
- );
- // Коеффициент удаленности камеры
- float scale_coef = 0.5f;
- mat4 View = lookAt(
- vec3(3, 3, 3) * scale_coef, // Координаты камеры
- vec3(0, 0, 0), // Направление камеры в начало координат
- vec3(0, 1, 0) // Координаты наблюдателя
- );
- if (glfwGetKey(g_window, GLFW_KEY_LEFT) || glfwGetKey(g_window, GLFW_KEY_RIGHT)) {
- ModelMatrix = rotate(ModelMatrix, delta_draw, vec3(1.0, 0.0, 0.0));
- }
- else if (glfwGetKey(g_window, GLFW_KEY_UP) || glfwGetKey(g_window, GLFW_KEY_DOWN)) {
- ModelMatrix = rotate(ModelMatrix, delta_draw, vec3(0.0, 1.0, 0.0));
- }
- else if (glfwGetKey(g_window, GLFW_KEY_Q) || glfwGetKey(g_window, GLFW_KEY_E)) {
- ModelMatrix = rotate(ModelMatrix, delta_draw, vec3(0.0, 0.0, 1.0));
- }
- // Матрица MV
- mat4 mv = View * ModelMatrix;
- // Матрица MVP
- mat4 mvp = Projection * mv;
- glUniformMatrix4fv(g_uMV, 1, GL_FALSE, &mv[0][0]);
- glUniformMatrix4fv(g_uMVP, 1, GL_FALSE, &mvp[0][0]);
- for (int i = 0; i < countTextures; i++)
- {
- glActiveTexture(GL_TEXTURE0 + textures[i].texUnit);
- glBindTexture(GL_TEXTURE_2D, texIDs[i]);
- glUniform1i(textures[i].mapLocation, textures[i].texUnit);
- }
- glDrawElements(GL_TRIANGLES, g_model.indexCount, GL_UNSIGNED_INT, NULL);
- }
- void cleanup()
- {
- if (g_shaderProgram != 0)
- glDeleteProgram(g_shaderProgram);
- if (g_model.vbo != 0)
- glDeleteBuffers(1, &g_model.vbo);
- if (g_model.ibo != 0)
- glDeleteBuffers(1, &g_model.ibo);
- if (g_model.vao != 0)
- glDeleteVertexArrays(1, &g_model.vao);
- glDeleteTextures(countTextures, texIDs);
- }
- bool initOpenGL()
- {
- // Initialize GLFW functions.
- if (!glfwInit())
- {
- cout << "Failed to initialize GLFW" << endl;
- return false;
- }
- // Request OpenGL 3.3 without obsoleted functions.
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- // Create window.
- g_window = glfwCreateWindow(800, 600, "OpenGL Test", NULL, NULL);
- if (g_window == NULL)
- {
- cout << "Failed to open GLFW window" << endl;
- glfwTerminate();
- return false;
- }
- // Initialize OpenGL context with.
- glfwMakeContextCurrent(g_window);
- // Set internal GLEW variable to activate OpenGL core profile.
- glewExperimental = true;
- // Initialize GLEW functions.
- if (glewInit() != GLEW_OK)
- {
- cout << "Failed to initialize GLEW" << endl;
- return false;
- }
- // Ensure we can capture the escape key being pressed.
- glfwSetInputMode(g_window, GLFW_STICKY_KEYS, GL_TRUE);
- // Set callback for framebuffer resizing event.
- glfwSetFramebufferSizeCallback(g_window, reshape);
- return true;
- }
- void tearDownOpenGL()
- {
- // Terminate GLFW.
- glfwTerminate();
- }
- int main()
- {
- // Initialize OpenGL
- if (!initOpenGL())
- return -1;
- // Initialize graphical resources.
- bool isOk = init();
- if (isOk)
- {
- GLfloat lastTime = glfwGetTime();
- // Main loop until window closed or escape pressed.
- while (glfwGetKey(g_window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(g_window) == 0)
- {
- GLfloat currentTime = glfwGetTime();
- GLfloat deltaTime = GLfloat(currentTime - lastTime);
- lastTime = currentTime;
- GLfloat delta = 0.0;
- // Угол поворота
- GLfloat angle = 100.0;
- // Обработка нажатий
- if (glfwGetKey(g_window, GLFW_KEY_LEFT) || glfwGetKey(g_window, GLFW_KEY_UP) || glfwGetKey(g_window, GLFW_KEY_Q)) {
- delta = radians(angle) * deltaTime;
- }
- else if (glfwGetKey(g_window, GLFW_KEY_RIGHT) || glfwGetKey(g_window, GLFW_KEY_DOWN) || glfwGetKey(g_window, GLFW_KEY_E)) {
- delta = -radians(angle) * deltaTime;
- }
- // Draw scene.
- draw(delta);
- // Swap buffers.
- glfwSwapBuffers(g_window);
- // Poll window events.
- glfwPollEvents();
- }
- }
- // Cleanup graphical resources.
- cleanup();
- // Tear down OpenGL.
- tearDownOpenGL();
- return isOk ? 0 : -1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement