From cce4c4bb1a429444ca258473f9439dd410aaf3d0 Mon Sep 17 00:00:00 2001 From: Morten Delenk Date: Sun, 28 Aug 2016 11:31:10 +0200 Subject: [PATCH] Move a lot of code to classes. --- .kdev4/testgame.kdev4 | 3 + CMakeLists.txt | 2 +- main.cpp | 82 +++++++--------------- main.h | 7 +- renderer/shader.cpp | 130 +++++++++++++++++++++++++++++++++++ renderer/shader.h | 31 +++++++++ renderer/shapes/float2D.h | 7 ++ renderer/shapes/triangle.cpp | 32 +++++++++ renderer/shapes/triangle.h | 16 +++++ shaders/triangle.f.glsl | 5 ++ shaders/triangle.v.glsl | 4 ++ 11 files changed, 258 insertions(+), 61 deletions(-) create mode 100644 renderer/shader.cpp create mode 100644 renderer/shader.h create mode 100644 renderer/shapes/float2D.h create mode 100644 renderer/shapes/triangle.cpp create mode 100644 renderer/shapes/triangle.h create mode 100644 shaders/triangle.f.glsl create mode 100644 shaders/triangle.v.glsl diff --git a/.kdev4/testgame.kdev4 b/.kdev4/testgame.kdev4 index 28f237b..07c88a7 100644 --- a/.kdev4/testgame.kdev4 +++ b/.kdev4/testgame.kdev4 @@ -1,3 +1,6 @@ +[Buildset] +BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x10\x00t\x00e\x00s\x00t\x00g\x00a\x00m\x00e) + [CMake] Build Directory Count=1 Current Build Directory Index=0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c3bdc4..4b98ba4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.6) project(testgame) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -I..") set(CMAKE_LD_FLAGS "${CMAKE_LD_FLAGS} -L/usr/local/bin") -add_executable(testgame main.cpp renderer/main.cpp) +add_executable(testgame main.cpp renderer/main.cpp renderer/shader.cpp renderer/shapes/triangle.cpp) INCLUDE(FindPkgConfig) PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2) INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS}) diff --git a/main.cpp b/main.cpp index 572c924..a0fb3de 100644 --- a/main.cpp +++ b/main.cpp @@ -3,58 +3,32 @@ #include #include #include +#include using namespace std; bool TestGame::init() { - GLint compile_ok = GL_FALSE, link_ok = GL_FALSE; + GLint link_ok = GL_FALSE; //Compile Vertex shader - GLuint vs = glCreateShader(GL_VERTEX_SHADER); - const char *vs_source = - //"#version 100\n" // OpenGL ES 2.0 - "#version 120\n" // OpenGL 2.1 - "attribute vec2 coord2d; " - "void main(void) { " - " gl_Position = vec4(coord2d, 0.0, 1.0); " - "}"; - glShaderSource(vs, 1, &vs_source, NULL); - glCompileShader(vs); - glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok); - if (!compile_ok) { - cerr << "Error in vertex shader" << endl; - return false; + vs = new VertexShader("shaders/triangle.v.glsl"); + if(!vs->compile()) { + throw nullptr; } //Compile Fragment shader - GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - const char *fs_source = - //"#version 100\n" // OpenGL ES 2.0 - "#version 120\n" // OpenGL 2.1 - "void main(void) { " - " gl_FragColor[0] = 0.0; " - " gl_FragColor[1] = 0.0; " - " gl_FragColor[2] = 1.0; " - "}"; - glShaderSource(fs, 1, &fs_source, NULL); - glCompileShader(fs); - glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok); - if (!compile_ok) { - cerr << "Error in fragment shader" << endl; - return false; + fs = new FragmentShader("shaders/triangle.f.glsl"); + if(!fs->compile()) { + throw nullptr; } //Linking - program = glCreateProgram(); - glAttachShader(program, vs); - glAttachShader(program, fs); - glLinkProgram(program); - glGetProgramiv(program, GL_LINK_STATUS, &link_ok); - if (!link_ok) { - cerr << "Error in glLinkProgram" << endl; - return false; - } + vector shaders; + shaders.push_back(vs); + shaders.push_back(fs); + program=link(shaders); + //Set attributes const char* attribute_name = "coord2d"; attribute_coord2d = glGetAttribLocation(program, attribute_name); if (attribute_coord2d == -1) { cerr << "Could not bind attribute " << attribute_name << endl; - return false; + throw nullptr; } return true; @@ -81,23 +55,11 @@ void TestGame::render() glUseProgram(program); glEnableVertexAttribArray(attribute_coord2d); - GLfloat triangle_vertices[] = { - 0.0, 0.8, - -0.8, -0.8, - 0.8, -0.8, - }; - // Describe our vertices array to OpenGL (it can't guess its format automatically) - glVertexAttribPointer( - attribute_coord2d, // attribute - 2, // number of elements per vertex, here (x,y) - GL_FLOAT, // the type of each element - GL_FALSE, // take our values as-is - 0, // no extra data between each position - triangle_vertices // pointer to the C array - ); - // Push each element in buffer_vertices to the vertex shader - glDrawArrays(GL_TRIANGLES, 0, 3); + + t1.render(attribute_coord2d); + t2.render(attribute_coord2d); + t3.render(attribute_coord2d); glDisableVertexAttribArray(attribute_coord2d); @@ -107,10 +69,12 @@ void TestGame::render() TestGame::~TestGame() { glDeleteProgram(program); + delete fs; + delete vs; } int main(int argc, char **argv) { - TestGame game; - game.start(); - return 0; + TestGame game; + game.start(); + return 0; } diff --git a/main.h b/main.h index 428c320..475c8a0 100644 --- a/main.h +++ b/main.h @@ -1,15 +1,20 @@ #include +#include +#include #include class TestGame: public MainClass { private: + Triangle t1, t2, t3; GLuint program; GLint attribute_coord2d; auto render() -> void; + VertexShader *vs; + FragmentShader *fs; protected: virtual auto tick() -> bool; virtual auto init() -> bool; public: - TestGame(): MainClass(640,480) {}; + TestGame(): MainClass(640,480), t1(0.0, 0.0, 0.5, 1.0, 1.0, 0.0), t2(1.0,0.0,1.5,1.0,2.0,0.0), t3(0.5,1.0,1.0,2.0,1.5,1.0) {}; virtual ~TestGame(); virtual auto stop() -> void; }; \ No newline at end of file diff --git a/renderer/shader.cpp b/renderer/shader.cpp new file mode 100644 index 0000000..15fa8a0 --- /dev/null +++ b/renderer/shader.cpp @@ -0,0 +1,130 @@ +#include +#include +#include +using namespace std; +Shader::Shader(const char* filename): object(0) +{ + SDL_RWops *rw = SDL_RWFromFile(filename, "rb"); + if(rw==NULL) throw nullptr; //Load + + Sint64 res_size = SDL_RWsize(rw); + shader_contents=new char[res_size+1]; //Allocate + + Sint64 nb_read_total=0, nb_read=1; + char* buf = shader_contents; + while(nb_read_total < res_size && nb_read != 0 ) { //Read + nb_read = SDL_RWread(rw, buf, 1, (res_size - nb_read_total)); + nb_read_total += nb_read; + buf += nb_read; + } + + SDL_RWclose(rw); //Cleanup + if (nb_read_total != res_size) { + delete[] shader_contents; + throw nullptr; + } + shader_contents[nb_read_total] = '\0'; +} + +Shader::~Shader() +{ + delete[] shader_contents; + if(object) + glDeleteShader(object); +} + +Shader::operator GLuint() +{ + return object; +} + +void Shader::printLog() +{ + printLog(object); +} + +void Shader::printLog(GLuint object) +{ + GLint log_length = 0; + if(glIsShader(object)) { + glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length); + } else if(glIsProgram(object)) { + glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length); + } else { + cerr << "printlog: Not a shader or a program" << endl; + return; + } + + char* log = new char[log_length]; + + if(glIsShader(object)) + glGetShaderInfoLog(object, log_length, NULL, log); + else + glGetProgramInfoLog(object, log_length, NULL, log); + + cerr << log; + delete[] log; +} +auto FragmentShader::compile() -> bool { + const GLchar *source = shader_contents; + GLuint res = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar* sources[] = { +#ifdef GL_ES_VERSION_2_0 + "#version 100\n" //OpenGL ES 2.0 +#else + "#version 120\n" //OpenGL .1 +#endif + ,source }; + glShaderSource(res, 2, sources, NULL); + + glCompileShader(res); + GLint compile_ok = GL_FALSE; + glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok); + if(compile_ok == GL_FALSE) { + printLog(res); + glDeleteShader(res); + return false; + } + object=res; + return true; +} +auto VertexShader::compile() -> bool { + const GLchar *source = shader_contents; + GLuint res = glCreateShader(GL_VERTEX_SHADER); + + const GLchar* sources[] = { +#ifdef GL_ES_VERSION_2_0 + "#version 100\n" //OpenGL ES 2.0 +#else + "#version 120\n" //OpenGL .1 +#endif + ,source }; + glShaderSource(res, 2, sources, NULL); + + glCompileShader(res); + GLint compile_ok = GL_FALSE; + glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok); + if(compile_ok == GL_FALSE) { + printLog(res); + glDeleteShader(res); + return false; + } + object=res; + return true; +} +GLuint link(vector< Shader*> &shaders) +{ + GLint link_ok = GL_FALSE; + GLuint program=glCreateProgram(); + for(int i=0;iprintLog(program); + throw nullptr; + } + return program; +} \ No newline at end of file diff --git a/renderer/shader.h b/renderer/shader.h new file mode 100644 index 0000000..a975a36 --- /dev/null +++ b/renderer/shader.h @@ -0,0 +1,31 @@ +#ifndef __RENDERER_SHADER_H +#define __RENDERER_SHADER_H +#include +#include +class Shader { +private: + Shader() {} +protected: + char * shader_contents; + GLuint object; + auto printLog() -> void; +public: + auto printLog(GLuint object) -> void; + Shader(const char* filename); + virtual ~Shader(); + virtual auto compile() -> bool = 0; //Linking is done by the program. + virtual operator GLuint(); + +}; +class FragmentShader: public Shader { +public: + FragmentShader(const char* filename): Shader(filename) {}; + virtual auto compile() -> bool; +}; +class VertexShader: public Shader { +public: + VertexShader(const char* filename): Shader(filename) {}; + virtual auto compile() -> bool; +}; +auto link(std::vector &shaders) -> GLuint; +#endif \ No newline at end of file diff --git a/renderer/shapes/float2D.h b/renderer/shapes/float2D.h new file mode 100644 index 0000000..a2fc99d --- /dev/null +++ b/renderer/shapes/float2D.h @@ -0,0 +1,7 @@ +#ifndef __SHAPES_FLOAT2D_H +#define __SHAPES_FLOAT2D_H +struct float2D { + float x; + float y; +}; +#endif \ No newline at end of file diff --git a/renderer/shapes/triangle.cpp b/renderer/shapes/triangle.cpp new file mode 100644 index 0000000..b6d2ba7 --- /dev/null +++ b/renderer/shapes/triangle.cpp @@ -0,0 +1,32 @@ +#include +Triangle::Triangle(float x, float y, float alen, float blen, float clen) +{ + A.x=x; + A.y=y; + +} +Triangle::Triangle(float ax, float ay, float bx, float by, float cx, float cy) +{ + A.x=ax-1.0; + A.y=ay-1.0; + B.x=bx-1.0; + B.y=by-1.0; + C.x=cx-1.0; + C.y=cy-1.0; +} + +Triangle::~Triangle() +{ + +} +bool Triangle::render(GLint attrib) +{ + GLfloat triangle_vertices[] = { + A.x, A.y, + B.x, B.y, + C.x, C.y + }; + glVertexAttribPointer(attrib, 2, GL_FLOAT, GL_FALSE, 0, triangle_vertices); + glDrawArrays(GL_TRIANGLES, 0, 3); + return true; +} diff --git a/renderer/shapes/triangle.h b/renderer/shapes/triangle.h new file mode 100644 index 0000000..02dbb8d --- /dev/null +++ b/renderer/shapes/triangle.h @@ -0,0 +1,16 @@ +#ifndef __SHAPE_TRIANGLE_HPP +#define __SHAPE_TRIANGLE_HPP +#include +#include +class Triangle { +private: + float2D A; + float2D B; + float2D C; //The three points +public: + Triangle(float x, float y, float alen, float blen, float clen); + Triangle(float ax, float ay, float bx, float by, float cx, float cy); + ~Triangle(); + auto render(GLint attrib) -> bool; +}; +#endif \ No newline at end of file diff --git a/shaders/triangle.f.glsl b/shaders/triangle.f.glsl new file mode 100644 index 0000000..498d374 --- /dev/null +++ b/shaders/triangle.f.glsl @@ -0,0 +1,5 @@ +void main(void) { + gl_FragColor[0] = 1.0; + gl_FragColor[1] = 1.0; + gl_FragColor[2] = 0.0; +} \ No newline at end of file diff --git a/shaders/triangle.v.glsl b/shaders/triangle.v.glsl new file mode 100644 index 0000000..f7d6eba --- /dev/null +++ b/shaders/triangle.v.glsl @@ -0,0 +1,4 @@ +attribute vec2 coord2d; +void main(void) { + gl_Position = vec4(coord2d, 0.0, 1.0); +}