From 0bf4ad9e4a9e1c97e92aa23a365405dfef89bd7c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 17 Jan 2021 19:36:30 +0000 Subject: Big reshuffle Fixes code quality warnings now picked up. --- gfx/gl/camera.cpp | 46 +++++++++++++++++++ gfx/gl/camera.h | 24 ++++++++++ gfx/gl/shader.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++ gfx/gl/shader.h | 35 +++++++++++++++ gfx/gl/shaders/basicShader.fs | 13 ++++++ gfx/gl/shaders/basicShader.vs | 18 ++++++++ gfx/gl/transform.cpp | 27 ++++++++++++ gfx/gl/transform.h | 58 ++++++++++++++++++++++++ 8 files changed, 321 insertions(+) create mode 100644 gfx/gl/camera.cpp create mode 100644 gfx/gl/camera.h create mode 100644 gfx/gl/shader.cpp create mode 100644 gfx/gl/shader.h create mode 100644 gfx/gl/shaders/basicShader.fs create mode 100644 gfx/gl/shaders/basicShader.vs create mode 100644 gfx/gl/transform.cpp create mode 100644 gfx/gl/transform.h (limited to 'gfx/gl') diff --git a/gfx/gl/camera.cpp b/gfx/gl/camera.cpp new file mode 100644 index 0000000..b4a76d0 --- /dev/null +++ b/gfx/gl/camera.cpp @@ -0,0 +1,46 @@ +#include "camera.h" +#include + +Camera::Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar) : + projection {glm::perspective(fov, aspect, zNear, zFar)}, pos {pos}, forward {0.0F, 0.0F, 1.0F}, up {0.0F, 1.0F, + 0.0F} +{ +} + +glm::mat4 +Camera::GetViewProjection() const +{ + return projection * glm::lookAt(pos, pos + forward, up); +} + +void +Camera::MoveForward(float amt) +{ + pos += forward * amt; +} + +void +Camera::MoveRight(float amt) +{ + pos += glm::cross(up, forward) * amt; +} + +void +Camera::Pitch(float angle) +{ + const auto right = glm::normalize(glm::cross(up, forward)); + + forward = glm::vec3(glm::normalize(glm::rotate(angle, right) * glm::vec4(forward, 0.0))); + up = glm::normalize(glm::cross(forward, right)); +} + +void +Camera::RotateY(float angle) +{ + static constexpr glm::vec3 UP {0.0F, 1.0F, 0.0F}; + + const auto rotation = glm::rotate(angle, UP); + + forward = glm::vec3(glm::normalize(rotation * glm::vec4(forward, 0.0))); + up = glm::vec3(glm::normalize(rotation * glm::vec4(up, 0.0))); +} diff --git a/gfx/gl/camera.h b/gfx/gl/camera.h new file mode 100644 index 0000000..fa4296d --- /dev/null +++ b/gfx/gl/camera.h @@ -0,0 +1,24 @@ +#ifndef CAMERA_INCLUDED_H +#define CAMERA_INCLUDED_H + +#include + +class Camera { +public: + Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar); + + [[nodiscard]] glm::mat4 GetViewProjection() const; + + void MoveForward(float amt); + void MoveRight(float amt); + void Pitch(float angle); + void RotateY(float angle); + +private: + glm::mat4 projection; + glm::vec3 pos; + glm::vec3 forward; + glm::vec3 up; +}; + +#endif diff --git a/gfx/gl/shader.cpp b/gfx/gl/shader.cpp new file mode 100644 index 0000000..33fdf61 --- /dev/null +++ b/gfx/gl/shader.cpp @@ -0,0 +1,100 @@ +#include "shader.h" +#include "transform.h" +#include +#include +#include +#include + +Shader::Shader(const std::string &) : + m_program {glCreateProgram()}, m_shaders {CreateShader( + (GLchar *)(basicShader_vs), basicShader_vs_len, GL_VERTEX_SHADER), + CreateShader( + (GLchar *)basicShader_fs, basicShader_fs_len, GL_FRAGMENT_SHADER)}, + m_uniforms {} +{ + for (auto m_shader : m_shaders) { + glAttachShader(m_program, m_shader); + } + + glBindAttribLocation(m_program, 0, "position"); + glBindAttribLocation(m_program, 1, "texCoord"); + glBindAttribLocation(m_program, 2, "normal"); + + glLinkProgram(m_program); + CheckShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program"); + + glValidateProgram(m_program); + CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program"); + + m_uniforms = {glGetUniformLocation(m_program, "MVP"), glGetUniformLocation(m_program, "Normal"), + glGetUniformLocation(m_program, "lightDirection")}; +} + +Shader::~Shader() +{ + for (auto m_shader : m_shaders) { + glDetachShader(m_program, m_shader); + glDeleteShader(m_shader); + } + + glDeleteProgram(m_program); +} + +void +Shader::Bind() const +{ + glUseProgram(m_program); +} + +void +Shader::Update(const Transform & transform, const Camera & camera) const +{ + glm::mat4 MVP = transform.GetMVP(camera); + glm::mat4 Normal = transform.GetModel(); + + glUniformMatrix4fv(m_uniforms[0], 1, GL_FALSE, &MVP[0][0]); + glUniformMatrix4fv(m_uniforms[1], 1, GL_FALSE, &Normal[0][0]); + glUniform3f(m_uniforms[2], 0.0F, 0.0F, 1.0F); +} + +void +Shader::CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string & errorMessage) +{ + GLint success = 0; + std::array error {}; + + if (isProgram) { + glGetProgramiv(shader, flag, &success); + } + else { + glGetShaderiv(shader, flag, &success); + } + + if (success == GL_FALSE) { + if (isProgram) { + glGetProgramInfoLog(shader, error.size(), nullptr, error.data()); + } + else { + glGetShaderInfoLog(shader, error.size(), nullptr, error.data()); + } + + throw std::runtime_error {errorMessage + ": '" + std::string {error.data(), error.size()} + "'"}; + } +} + +GLuint +Shader::CreateShader(const GLchar * text, GLint len, unsigned int type) +{ + GLuint shader = glCreateShader(type); + + if (shader == 0) { + throw std::runtime_error {"Error compiling shader type " + std::to_string(type)}; + } + + glShaderSource(shader, 1, &text, &len); + glCompileShader(shader); + + CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error compiling shader!"); + + return shader; +} diff --git a/gfx/gl/shader.h b/gfx/gl/shader.h new file mode 100644 index 0000000..2072199 --- /dev/null +++ b/gfx/gl/shader.h @@ -0,0 +1,35 @@ +#ifndef SHADER_INCLUDED_H +#define SHADER_INCLUDED_H + +#include +#include +#include +#include + +class Camera; +class Transform; + +class Shader { +public: + explicit Shader(const std::string & fileName); + virtual ~Shader(); + + NO_COPY(Shader); + NO_MOVE(Shader); + + void Bind() const; + void Update(const Transform & transform, const Camera & camera) const; + +private: + static constexpr unsigned int NUM_SHADERS = 2; + static constexpr unsigned int NUM_UNIFORMS = 3; + + static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string & errorMessage); + static GLuint CreateShader(const GLchar * text, GLint len, unsigned int type); + + GLuint m_program; + std::array m_shaders; + std::array m_uniforms; +}; + +#endif diff --git a/gfx/gl/shaders/basicShader.fs b/gfx/gl/shaders/basicShader.fs new file mode 100644 index 0000000..3aa974f --- /dev/null +++ b/gfx/gl/shaders/basicShader.fs @@ -0,0 +1,13 @@ +#version 120 + +varying vec2 texCoord0; +varying vec3 normal0; + +uniform sampler2D sampler; +uniform vec3 lightDirection; + +void main() +{ + gl_FragColor = texture2D(sampler, texCoord0) * + clamp(dot(-lightDirection, normal0), 0.0, 1.0); +} diff --git a/gfx/gl/shaders/basicShader.vs b/gfx/gl/shaders/basicShader.vs new file mode 100644 index 0000000..e673548 --- /dev/null +++ b/gfx/gl/shaders/basicShader.vs @@ -0,0 +1,18 @@ +#version 120 + +attribute vec3 position; +attribute vec2 texCoord; +attribute vec3 normal; + +varying vec2 texCoord0; +varying vec3 normal0; + +uniform mat4 MVP; +uniform mat4 Normal; + +void main() +{ + gl_Position = MVP * vec4(position, 1.0); + texCoord0 = texCoord; + normal0 = (Normal * vec4(normal, 0.0)).xyz; +} diff --git a/gfx/gl/transform.cpp b/gfx/gl/transform.cpp new file mode 100644 index 0000000..7b256af --- /dev/null +++ b/gfx/gl/transform.cpp @@ -0,0 +1,27 @@ +#include "transform.h" +#include "camera.h" +#include + +Transform::Transform(glm::vec3 pos, glm::vec3 rot, glm::vec3 scale) : pos {pos}, rot {rot}, scale {scale} { } + +glm::mat4 +Transform::GetModel() const +{ + const auto posMat = glm::translate(pos); + const auto scaleMat = glm::scale(scale); + const auto rotX = glm::rotate(rot.x, glm::vec3(1.0, 0.0, 0.0)); + const auto rotY = glm::rotate(rot.y, glm::vec3(0.0, 1.0, 0.0)); + const auto rotZ = glm::rotate(rot.z, glm::vec3(0.0, 0.0, 1.0)); + const auto rotMat = rotX * rotY * rotZ; + + return posMat * rotMat * scaleMat; +} + +glm::mat4 +Transform::GetMVP(const Camera & camera) const +{ + const auto VP = camera.GetViewProjection(); + const auto M = GetModel(); + + return VP * M; +} diff --git a/gfx/gl/transform.h b/gfx/gl/transform.h new file mode 100644 index 0000000..07040ae --- /dev/null +++ b/gfx/gl/transform.h @@ -0,0 +1,58 @@ +#ifndef TRANSFORM_INCLUDED_H +#define TRANSFORM_INCLUDED_H + +#include + +class Camera; + +class Transform { +public: + explicit Transform(glm::vec3 pos = {}, glm::vec3 rot = {}, glm::vec3 scale = {1.0F, 1.0F, 1.0F}); + + [[nodiscard]] glm::mat4 GetModel() const; + + [[nodiscard]] glm::mat4 GetMVP(const Camera & camera) const; + + [[nodiscard]] inline glm::vec3 & + GetPos() + { + return pos; + } + + [[nodiscard]] inline glm::vec3 & + GetRot() + { + return rot; + } + + [[nodiscard]] inline glm::vec3 & + GetScale() + { + return scale; + } + + inline void + SetPos(glm::vec3 && pos) + { + this->pos = pos; + } + + inline void + SetRot(glm::vec3 && rot) + { + this->rot = rot; + } + + inline void + SetScale(glm::vec3 && scale) + { + this->scale = scale; + } + +private: + glm::vec3 pos; + glm::vec3 rot; + glm::vec3 scale; +}; + +#endif -- cgit v1.2.3