From 34b7903d254ce50d76ca8f1b8233237daa1c6ada Mon Sep 17 00:00:00 2001 From: Jyrki Vesterinen Date: Sat, 7 Apr 2018 10:33:39 +0300 Subject: [PATCH] Add a shader class --- projectfiles/VC14/wesnoth.vcxproj | 16 +++- projectfiles/VC14/wesnoth.vcxproj.filters | 6 ++ source_lists/libwesnoth_sdl | 1 + src/ogl/shader.cpp | 110 ++++++++++++++++++++++ src/ogl/shader.hpp | 49 ++++++++++ 5 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 src/ogl/shader.cpp create mode 100644 src/ogl/shader.hpp diff --git a/projectfiles/VC14/wesnoth.vcxproj b/projectfiles/VC14/wesnoth.vcxproj index 1acf4f010b42..c3f44584daa5 100644 --- a/projectfiles/VC14/wesnoth.vcxproj +++ b/projectfiles/VC14/wesnoth.vcxproj @@ -2530,7 +2530,20 @@ $(IntDir)OGL\ $(IntDir)OGL\ - + + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + + + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ $(IntDir)OGL\ @@ -3887,6 +3900,7 @@ + diff --git a/projectfiles/VC14/wesnoth.vcxproj.filters b/projectfiles/VC14/wesnoth.vcxproj.filters index e73700445891..2524cb1d7bb0 100644 --- a/projectfiles/VC14/wesnoth.vcxproj.filters +++ b/projectfiles/VC14/wesnoth.vcxproj.filters @@ -1552,6 +1552,9 @@ OGL + + OGL + @@ -3023,6 +3026,9 @@ OGL + + OGL + diff --git a/source_lists/libwesnoth_sdl b/source_lists/libwesnoth_sdl index dfc246b03b03..41e1c5afd3bb 100644 --- a/source_lists/libwesnoth_sdl +++ b/source_lists/libwesnoth_sdl @@ -1,4 +1,5 @@ ogl/context.cpp +ogl/shader.cpp ogl/sprite.cpp ogl/texture.cpp ogl/utils.cpp diff --git a/src/ogl/shader.cpp b/src/ogl/shader.cpp new file mode 100644 index 000000000000..0abc444948dd --- /dev/null +++ b/src/ogl/shader.cpp @@ -0,0 +1,110 @@ +/* + Copyright (C) 2018 by Jyrki Vesterinen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#include "ogl/shader.hpp" + +#include "log.hpp" +#include "ogl/vertex.hpp" + +#include +#include +#include +#include +#include +#include + +static lg::log_domain log_opengl("opengl"); +#define LOG_GL LOG_STREAM(info, log_opengl) +#define ERR_GL LOG_STREAM(err, log_opengl) + +namespace +{ + +std::pair compile_subshader(GLuint shader, const std::string& source_code) +{ + GLint compile_status; + std::array compile_log; + + int src_length = source_code.length(); + const char* src_char_array = source_code.data(); + glShaderSource(shader, 1, &src_char_array, &src_length); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); + glGetShaderInfoLog(shader, compile_log.size(), nullptr, compile_log.data()); + + return {compile_status == GL_TRUE, {compile_log.data()}}; +} + +} + +namespace gl +{ + +shader::~shader() +{ + std::array subshaders; + glGetAttachedShaders(shader_program_, subshaders.size(), nullptr, subshaders.data()); + + glDeleteProgram(shader_program_); + for(const GLuint s : subshaders) { + glDeleteShader(s); + } +} + +void shader::activate() const +{ + glUseProgram(shader_program_); + + GLint position_index = glGetAttribLocation(shader_program_, "position"); + GLint texcoord_index = glGetAttribLocation(shader_program_, "tex_coord"); + + glVertexAttribPointer(position_index, 2, GL_FLOAT, false, sizeof(vertex), + reinterpret_cast(offsetof(vertex, x))); + glVertexAttribPointer(texcoord_index, 2, GL_FLOAT, false, sizeof(vertex), + reinterpret_cast(offsetof(vertex, u))); + + glEnableVertexAttribArray(position_index); + glEnableVertexAttribArray(texcoord_index); +} + +void shader::compile(const std::string& vertex_shader_src, const std::string& pixel_shader_src) +{ + bool success; + std::string compile_log; + + GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); + std::tie(success, compile_log) = compile_subshader(vertex_shader, vertex_shader_src); + if(!success) { + ERR_GL << "Error compiling vertex shader\n" << compile_log << std::endl; + throw std::invalid_argument("error compiling vertex shader"); + } else if(compile_log != "") { + LOG_GL << compile_log << std::endl; + } + + GLuint pixel_shader = glCreateShader(GL_FRAGMENT_SHADER); + std::tie(success, compile_log) = compile_subshader(pixel_shader, pixel_shader_src); + if(!success) { + ERR_GL << "Error compiling pixel shader\n" << compile_log << std::endl; + throw std::invalid_argument("error compiling pixel shader"); + } else if(compile_log != "") { + LOG_GL << compile_log << std::endl; + } + + shader_program_ = glCreateProgram(); + glAttachShader(shader_program_, vertex_shader); + glAttachShader(shader_program_, pixel_shader); + + glLinkProgram(shader_program_); +} + +} \ No newline at end of file diff --git a/src/ogl/shader.hpp b/src/ogl/shader.hpp new file mode 100644 index 000000000000..4317c041771e --- /dev/null +++ b/src/ogl/shader.hpp @@ -0,0 +1,49 @@ +/* + Copyright (C) 2018 by Jyrki Vesterinen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#pragma once + +#include + +#include + +namespace gl +{ + +class shader +{ +public: + /** Constructor. + @param vertex_shader_src Vertex shader source code. + @param pixel_shader_src Pixel shader source code. + @throw std::invalid_argument if compiling the shader fails. + */ + shader(const std::string& vertex_shader_src, const std::string& pixel_shader_src) + { + compile(pixel_shader_src, vertex_shader_src); + } + + /// Destructor. + ~shader(); + + /// Makes the shader the active shader. + /// The right VBO and VAO must be already bound. + void activate() const; + +private: + void compile(const std::string& vertex_shader_src, const std::string& pixel_shader_src); + + GLuint shader_program_ = 0u; +}; + +}