Move a lot of code to classes.

This commit is contained in:
Morten Delenk 2016-08-28 11:31:10 +02:00
parent 4d5b548ffe
commit cce4c4bb1a
No known key found for this signature in database
GPG key ID: 3F818D0F65DCB490
11 changed files with 258 additions and 61 deletions

View file

@ -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

View file

@ -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})

View file

@ -3,58 +3,32 @@
#include <main.h>
#include <SDL.h>
#include <GL/glew.h>
#include <renderer/shader.h>
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<Shader *> 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,6 +69,8 @@ void TestGame::render()
TestGame::~TestGame()
{
glDeleteProgram(program);
delete fs;
delete vs;
}
int main(int argc, char **argv) {

7
main.h
View file

@ -1,15 +1,20 @@
#include <renderer/main.h>
#include <renderer/shader.h>
#include <renderer/shapes/triangle.h>
#include <GL/glew.h>
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;
};

130
renderer/shader.cpp Normal file
View file

@ -0,0 +1,130 @@
#include <renderer/shader.h>
#include <SDL.h>
#include <iostream>
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;i<shaders.size();i++) {
glAttachShader(program, *shaders[i]);
}
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
if (link_ok==GL_FALSE) {
shaders[0]->printLog(program);
throw nullptr;
}
return program;
}

31
renderer/shader.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef __RENDERER_SHADER_H
#define __RENDERER_SHADER_H
#include <GL/glew.h>
#include <vector>
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<Shader*> &shaders) -> GLuint;
#endif

View file

@ -0,0 +1,7 @@
#ifndef __SHAPES_FLOAT2D_H
#define __SHAPES_FLOAT2D_H
struct float2D {
float x;
float y;
};
#endif

View file

@ -0,0 +1,32 @@
#include <renderer/shapes/triangle.h>
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;
}

View file

@ -0,0 +1,16 @@
#ifndef __SHAPE_TRIANGLE_HPP
#define __SHAPE_TRIANGLE_HPP
#include <GL/glew.h>
#include <renderer/shapes/float2D.h>
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

5
shaders/triangle.f.glsl Normal file
View file

@ -0,0 +1,5 @@
void main(void) {
gl_FragColor[0] = 1.0;
gl_FragColor[1] = 1.0;
gl_FragColor[2] = 0.0;
}

4
shaders/triangle.v.glsl Normal file
View file

@ -0,0 +1,4 @@
attribute vec2 coord2d;
void main(void) {
gl_Position = vec4(coord2d, 0.0, 1.0);
}