Initial commit

This commit is contained in:
vlad 2023-03-23 14:26:14 +03:00
commit 9ded69e903
17 changed files with 823 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/cmake-build-debug/

4
CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.22)
project(graphics_labs)
add_subdirectory(lab2)

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# Лабы по компьютерной графике 3 курс 2 семестр
## Lab2
Для сборки нужно выбрать цель Lab2, рабочая директория - lab2. Создана 23 марта 2023 года.

29
lab2/CMakeLists.txt Normal file
View File

@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.22)
project(Lab2)
set(CMAKE_CXX_STANDARD 11)
find_package(glfw3 3.3 REQUIRED)
find_package(GLEW REQUIRED)
find_package(OpenGL REQUIRED)
find_package(glm REQUIRED)
add_executable(
${PROJECT_NAME}
src/main.cpp
src/window/Camera.cpp
src/window/Camera.h
src/window/Window.cpp
src/window/Window.h
src/window/Events.cpp
src/window/Events.h
src/graphics/Mesh.h
src/graphics/Mesh.cpp
src/graphics/Shader.h
src/graphics/Shader.cpp
)
target_link_libraries(${PROJECT_NAME} glfw)
target_link_libraries(${PROJECT_NAME} GLEW::GLEW)
target_link_libraries(${PROJECT_NAME} OpenGL::GL)

10
lab2/res/main.fsh Normal file
View File

@ -0,0 +1,10 @@
#version 330 core
in vec4 a_color;
out vec4 f_color;
void main(){
f_color = a_color;
}

14
lab2/res/main.vsh Normal file
View File

@ -0,0 +1,14 @@
#version 330 core
layout (location = 0) in vec3 v_position;
layout (location = 1) in float light;
out vec4 a_color;
uniform mat4 projview;
void main(){
// gl_Position = vec4(v_position, 1) * projview;
gl_Position = projview * vec4(v_position, 1);
a_color = vec4(0.5, 0, 1, 1) * light;
}

View File

@ -0,0 +1,50 @@
#include "Mesh.h"
#include <GL/glew.h>
Mesh::Mesh(const float* buffer, size_t vertices, const int* attrs) : vertices(vertices){
vertexSize = 0;
for (int i = 0; attrs[i]; i++){
vertexSize += attrs[i];
}
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
if (buffer){
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, buffer, GL_STATIC_DRAW);
} else {
glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STATIC_DRAW);
}
// attributes
int offset = 0;
for (int i = 0; attrs[i]; i++){
int size = attrs[i];
glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float)));
glEnableVertexAttribArray(i);
offset += size;
}
glBindVertexArray(0);
}
Mesh::~Mesh(){
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
}
void Mesh::reload(const float* buffer, size_t vertices){
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, buffer, GL_STATIC_DRAW);
this->vertices = vertices;
}
void Mesh::draw(){
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, vertices);
glBindVertexArray(0);
}

19
lab2/src/graphics/Mesh.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef GRAPHICS_MESH_H_
#define GRAPHICS_MESH_H_
#include <stdlib.h>
class Mesh {
unsigned int vao;
unsigned int vbo;
size_t vertices;
size_t vertexSize;
public:
Mesh(const float* buffer, size_t vertices, const int* attrs);
~Mesh();
void reload(const float* buffer, size_t vertices);
void draw();
};
#endif /* GRAPHICS_MESH_H_ */

View File

@ -0,0 +1,128 @@
#include "Shader.h"
#include <exception>
#include <fstream>
#include <iostream>
#include <sstream>
#include <glm/gtc/type_ptr.hpp>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
Shader::Shader(unsigned int id) : id(id){
}
Shader::~Shader(){
glDeleteProgram(id);
}
void Shader::use(){
glUseProgram(id);
}
void Shader::uniformMatrix(const std::string &name, glm::mat4 matrix){
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(matrix));
}
void Shader::uniform1i(const std::string &name, int x){
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
glUniform1i(transformLoc, x);
}
void Shader::uniform1f(const std::string &name, float x){
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
glUniform1f(transformLoc, x);
}
void Shader::uniform2f(const std::string &name, float x, float y){
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
glUniform2f(transformLoc, x, y);
}
void Shader::uniform3f(const std::string &name, float x, float y, float z){
GLuint transformLoc = glGetUniformLocation(id, name.c_str());
glUniform3f(transformLoc, x,y,z);
}
Shader* Shader::loadShader(const std::string& vertexFile, const std::string& fragmentFile) {
// Reading Files
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try {
vShaderFile.open(vertexFile);
fShaderFile.open(fragmentFile);
std::stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch(std::ifstream::failure& e) {
std::cerr << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
return nullptr;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar* fShaderCode = fragmentCode.c_str();
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, nullptr);
glCompileShader(vertex);
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success){
glGetShaderInfoLog(vertex, 512, nullptr, infoLog);
std::cerr << "SHADER::VERTEX: compilation failed" << std::endl;
std::cerr << infoLog << std::endl;
return nullptr;
}
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, nullptr);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success){
glGetShaderInfoLog(fragment, 512, nullptr, infoLog);
std::cerr << "SHADER::FRAGMENT: compilation failed" << std::endl;
std::cerr << infoLog << std::endl;
return nullptr;
}
// Shader Program
GLuint id = glCreateProgram();
glAttachShader(id, vertex);
glAttachShader(id, fragment);
glLinkProgram(id);
glGetProgramiv(id, GL_LINK_STATUS, &success);
if (!success){
glGetProgramInfoLog(id, 512, nullptr, infoLog);
std::cerr << "SHADER::PROGRAM: linking failed" << std::endl;
std::cerr << infoLog << std::endl;
glDeleteShader(vertex);
glDeleteShader(fragment);
return nullptr;
}
glDeleteShader(vertex);
glDeleteShader(fragment);
return new Shader(id);
}

View File

@ -0,0 +1,25 @@
#ifndef GRAPHICS_SHADER_H_
#define GRAPHICS_SHADER_H_
#include <iostream>
#include <glm/glm.hpp>
class Shader {
public:
unsigned int id;
explicit Shader(unsigned int id);
~Shader();
void use();
void uniformMatrix(const std::string& name, glm::mat4 matrix);
void uniform1i(const std::string& name, int x);
void uniform1f(const std::string& name, float x);
void uniform2f(const std::string& name, float x, float y);
void uniform3f(const std::string& name, float x, float y, float z);
static Shader* loadShader(const std::string& vertexFile, const std::string& fragmentFile);
};
#endif /* GRAPHICS_SHADER_H_ */

184
lab2/src/main.cpp Normal file
View File

@ -0,0 +1,184 @@
#include <iostream>
#include <cmath>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <vector>
#include <ctime>
// GLM
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "window/Window.h"
#include "window/Camera.h"
#include "window/Events.h"
#include "graphics/Mesh.h"
#include "graphics/Shader.h"
#define SPEED_FACTOR 2.5f
static void updateCameraPosition(Camera& cam, float delta) {
static float camX = 0, camY= 0;
if (Events::_cursor_locked){
camY += -Events::deltaY / (float)Window::height * 2;
camX += -Events::deltaX / (float)Window::height * 2;
if (camY < -glm::radians(89.0f)){
camY = -glm::radians(89.0f);
}
if (camY > glm::radians(89.0f)){
camY = glm::radians(89.0f);
}
cam.rotation = glm::mat4(1.0f);
cam.rotate(camY, camX, 0);
}
cam.updateVectors();
glm::vec3 dir(0,0,0);
if (Events::pressed(GLFW_KEY_W)){
dir.x += cam.dir.x;
dir.z += cam.dir.z;
}
if (Events::pressed(GLFW_KEY_S)){
dir.x -= cam.dir.x;
dir.z -= cam.dir.z;
}
if (Events::pressed(GLFW_KEY_D)){
dir.x += cam.right.x;
dir.z += cam.right.z;
}
if (Events::pressed(GLFW_KEY_A)){
dir.x -= cam.right.x;
dir.z -= cam.right.z;
}
if (Events::pressed(GLFW_KEY_SPACE)) {
dir.y = 1;
}
if (Events::pressed(GLFW_KEY_LEFT_SHIFT)) {
dir.y = -1;
}
if (dir.x != 0 || dir.y != 0 || dir.z != 0) {
dir = glm::normalize(dir);
}
cam.position += dir * delta * SPEED_FACTOR;
}
static Mesh* world;
static Shader* shader;
static void drawWorld(Camera& cam) {
auto projview = cam.getProjection() * cam.getView();
shader->use();
// shader->uniformMatrix("pr", cam.getProjection() * cam.getView());
shader->uniformMatrix("projview", projview);
world->draw();
auto model_scale = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.5f));
static float angle = 0.0f;
auto model_translate = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -2));
auto model_rotate = glm::rotate(glm::mat4(1.0f), angle, glm::vec3(0, 1, 0));
angle += 0.001f;
shader->uniformMatrix("projview", projview * model_scale * model_translate * model_rotate);
world->draw();
}
void mainloop(Camera& camera) {
long frame = 0;
float lastTime = Window::getTime();
float delta;
bool devdata = false;
Window::swapInterval(0);
while (!Window::isShouldClose()){
frame++;
float currentTime = Window::getTime();
delta = currentTime - lastTime;
lastTime = currentTime;
if (Events::jpressed(GLFW_KEY_ESCAPE)){
Window::setShouldClose(true);
}
if (Events::jpressed(GLFW_KEY_TAB)){
Events::toggleCursor();
}
if (Events::jpressed(GLFW_KEY_F3)){
devdata = !devdata;
}
updateCameraPosition(camera, delta);
drawWorld(camera);
// worldRenderer.draw(world, camera, occlusion);
// hud.draw(level, assets);
// if (devdata) {
// hud.drawDebug(level, assets, fps, occlusion);
// }
Window::swapBuffers();
Events::pullEvents();
}
}
void loadResources() {
const float buffer[] = {
// треугольник
// X Y Z Light
-1, -1, 0.5, 0.5,
1, -1, 0.5, 0.1,
0, 1, 0.5, 0.9,
-1, -1, -0.5, 0.5,
1, -1, -0.5, 0.1,
0, 1, -0.5, 0.9,
};
const int mesh_attrs[] {
3, 1, 0
};
world = new Mesh(buffer, 6, mesh_attrs);
shader = Shader::loadShader("res/main.vsh", "res/main.fsh");
}
void unloadResources() {
delete world;
delete shader;
}
int main() {
Window::initialize(800, 600, "Lab2");
Events::initialize();
loadResources();
// glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
Camera cam(glm::vec3(0, 0, 5), glm::radians(90.0f));
mainloop(cam);
unloadResources();
Events::finalize();
Window::terminate();
return 0;
}

View File

@ -0,0 +1,57 @@
//
// Created by vlad on 23.03.23.
//
#include "Camera.h"
#include "Window.h"
#include <glm/ext.hpp>
using namespace glm;
Camera::Camera(vec3 position, float fov) : position(position), fov(fov), rotation(1.0f) {
updateVectors();
}
void Camera::updateVectors(){
front = vec3(rotation * vec4(0,0,-1,1));
right = vec3(rotation * vec4(1,0,0,1));
up = vec3(rotation * vec4(0,1,0,1));
dir = vec3(rotation * vec4(0,0,-1,1));
dir.y = 0;
float len = length(dir);
if (len > 0.0f){
dir.x /= len;
dir.z /= len;
}
}
void Camera::rotate(float x, float y, float z){
rotation = glm::rotate(rotation, z, vec3(0,0,1));
rotation = glm::rotate(rotation, y, vec3(0,1,0));
rotation = glm::rotate(rotation, x, vec3(1,0,0));
updateVectors();
}
mat4 Camera::getProjection(){
float as = this->aspect;
if (as == 0.0f){
as = (float)Window::width / (float)Window::height;
}
if (perspective)
return glm::perspective(fov, as, 0.05f, 1500.0f);
else
if (flipped)
return glm::ortho(0.0f, fov * as, fov, 0.0f);
else
return glm::ortho(0.0f, fov * as, 0.0f, fov);
}
mat4 Camera::getView(){
if (perspective)
return glm::lookAt(position, position+front, up);
else
return glm::translate(glm::mat4(1.0f), position);
}

33
lab2/src/window/Camera.h Normal file
View File

@ -0,0 +1,33 @@
//
// Created by vlad on 23.03.23.
//
#ifndef GRAPHICS_LABS_CAMERA_H
#define GRAPHICS_LABS_CAMERA_H
#include <glm/glm.hpp>
class Camera {
public:
void updateVectors();
glm::vec3 front;
glm::vec3 up;
glm::vec3 right;
glm::vec3 dir;
glm::vec3 position;
float fov;
glm::mat4 rotation;
bool perspective = true;
bool flipped = false;
float aspect = 0.0f;
Camera(glm::vec3 position, float fov);
void rotate(float x, float y, float z);
glm::mat4 getProjection();
glm::mat4 getView();
};
#endif //GRAPHICS_LABS_CAMERA_H

114
lab2/src/window/Events.cpp Normal file
View File

@ -0,0 +1,114 @@
//
// Created by vlad on 23.03.23.
//
#include "Events.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string.h>
bool* Events::_keys;
uint* Events::_frames;
uint Events::_current = 0;
float Events::deltaX = 0.0f;
float Events::deltaY = 0.0f;
float Events::x = 0.0f;
float Events::y = 0.0f;
bool Events::_cursor_locked = false;
bool Events::_cursor_started = false;
#define _MOUSE_BUTTONS 1024
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos){
if (Events::_cursor_started){
Events::deltaX += xpos-Events::x;
Events::deltaY += ypos-Events::y;
}
else {
Events::_cursor_started = true;
}
Events::x = xpos;
Events::y = ypos;
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode){
if (action == GLFW_PRESS){
Events::_keys[_MOUSE_BUTTONS+button] = true;
Events::_frames[_MOUSE_BUTTONS+button] = Events::_current;
}
else if (action == GLFW_RELEASE){
Events::_keys[_MOUSE_BUTTONS+button] = false;
Events::_frames[_MOUSE_BUTTONS+button] = Events::_current;
}
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
if (action == GLFW_PRESS){
Events::_keys[key] = true;
Events::_frames[key] = Events::_current;
}
else if (action == GLFW_RELEASE){
Events::_keys[key] = false;
Events::_frames[key] = Events::_current;
}
}
void window_size_callback(GLFWwindow* window, int width, int height){
glViewport(0,0, width, height);
Window::width = width;
Window::height = height;
}
int Events::initialize(){
GLFWwindow* window = Window::window;
_keys = new bool[1032];
_frames = new uint[1032];
memset(_keys, false, 1032*sizeof(bool));
memset(_frames, 0, 1032*sizeof(uint));
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetWindowSizeCallback(window, window_size_callback);
return 0;
}
void Events::finalize(){
delete[] _keys;
delete[] _frames;
}
bool Events::pressed(int keycode){
if (keycode < 0 || keycode >= _MOUSE_BUTTONS)
return false;
return _keys[keycode];
}
bool Events::jpressed(int keycode){
if (keycode < 0 || keycode >= _MOUSE_BUTTONS)
return false;
return _keys[keycode] && _frames[keycode] == _current;
}
bool Events::clicked(int button){
int index = _MOUSE_BUTTONS+button;
return _keys[index];
}
bool Events::jclicked(int button){
int index = _MOUSE_BUTTONS+button;
return _keys[index] && _frames[index] == _current;
}
void Events::toggleCursor(){
_cursor_locked = !_cursor_locked;
Window::setCursorMode(_cursor_locked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
}
void Events::pullEvents(){
_current++;
deltaX = 0.0f;
deltaY = 0.0f;
glfwPollEvents();
}

37
lab2/src/window/Events.h Normal file
View File

@ -0,0 +1,37 @@
//
// Created by vlad on 23.03.23.
//
#ifndef GRAPHICS_LABS_EVENTS_H
#define GRAPHICS_LABS_EVENTS_H
#include "Window.h"
typedef unsigned int uint;
class Events {
public:
static bool* _keys;
static uint* _frames;
static uint _current;
static float deltaX;
static float deltaY;
static float x;
static float y;
static bool _cursor_locked;
static bool _cursor_started;
static int initialize();
static void finalize();
static void pullEvents();
static bool pressed(int keycode);
static bool jpressed(int keycode);
static bool clicked(int button);
static bool jclicked(int button);
static void toggleCursor();
};
#endif //GRAPHICS_LABS_EVENTS_H

View File

@ -0,0 +1,83 @@
//
// Created by vlad on 23.03.23.
//
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Window.h"
GLFWwindow* Window::window;
int Window::width = 0;
int Window::height = 0;
int Window::initialize(int w, int h, const char* title){
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
//glfwWindowHint(GLFW_SAMPLES, 2);
window = glfwCreateWindow(w, h, title, nullptr, nullptr);
if (window == nullptr){
std::cerr << "Failed to create GLFW Window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK){
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
glViewport(0, 0, w, h);
glClearColor(0.0f,0.0f,0.0f,1);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Window::width = w;
Window::height = h;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return 0;
}
void Window::viewport(int x, int y, int w, int h){
glViewport(x, y, w, h);
}
void Window::setCursorMode(int mode){
glfwSetInputMode(window, GLFW_CURSOR, mode);
}
void Window::terminate(){
glfwTerminate();
}
bool Window::isShouldClose(){
return glfwWindowShouldClose(window);
}
void Window::setShouldClose(bool flag){
glfwSetWindowShouldClose(window, flag);
}
void Window::swapInterval(int interval){
glfwSwapInterval(interval);
}
void Window::swapBuffers(){
glfwSwapBuffers(window);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
float Window::getTime() {
return (float)glfwGetTime();
}

28
lab2/src/window/Window.h Normal file
View File

@ -0,0 +1,28 @@
//
// Created by vlad on 23.03.23.
//
#ifndef GRAPHICS_LABS_WINDOW_H
#define GRAPHICS_LABS_WINDOW_H
class GLFWwindow;
class Window {
public:
static int width;
static int height;
static GLFWwindow* window; // не лучшее решение делать window публичным
static int initialize(int w, int h, const char* title);
static void terminate();
static void viewport(int x, int y, int w, int h);
static void setCursorMode(int mode);
static bool isShouldClose();
static void setShouldClose(bool flag);
static void swapBuffers();
static void swapInterval(int interval);
static float getTime();
};
#endif //GRAPHICS_LABS_WINDOW_H