Merge branch 'end'

This commit is contained in:
end 2016-09-28 07:58:48 +02:00
commit 74b4573c3a
19 changed files with 663 additions and 265 deletions

View file

@ -10,8 +10,10 @@ set(GAME_SRC
glclasses.cpp
renderer.cpp
game_window.cpp
triangle_window.cpp
renderer_simple.cpp
renderer_shader.cpp
session.cpp
util.cpp
game.cpp
state/object.cpp
@ -29,6 +31,8 @@ set(GAME_HEADERS
opengl.hpp
glclasses.hpp
renderer.hpp
renderer_simple.hpp
renderer_shader.hpp
)
include_directories(${CMAKE_CURRENT_BINARY_DIR})

View file

@ -69,7 +69,8 @@ bool Game::cycle(float dt)
steps++;
}
//std::cout << m_time_for_next_step << " s remaining time, " << steps << " steps taken." << std::endl;
// std::cout << m_time_for_next_step << " s remaining time, " << steps << "
// steps taken." << std::endl;
return true;
}

View file

@ -2,6 +2,8 @@
#include "opengl.hpp"
#include "renderer.hpp"
#include "renderer_simple.hpp"
#include "renderer_shader.hpp"
#include "game.hpp"
@ -15,6 +17,9 @@
class GameWindow : public endofthejedi::GLWindow {
private:
Game* m_game;
endofthejedi::RendererSimple m_renderer;
protected:
void init() override {
glClearColor(0.5f, 0.6f, 0.7f, 1.0f);
@ -39,80 +44,14 @@ protected:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (const game::Planet *planet : m_game->state()->planets) {
drawPlanet(planet->position, planet->radius);
}
for (const game::Trace *trace : m_game->state()->traces) {
drawTrace(trace);
}
for (const game::Explosion *explosion : m_game->state()->explosions) {
drawExplosion(explosion);
}
for (const game::Ship *ship : m_game->state()->ships) {
drawShip(ship->position);
}
for (const game::Player *player : m_game->state()->players) {
for (const game::Missile *missile : player->missiles) {
drawMissile(missile->position);
}
}
m_renderer.render(m_game->state());
}
void resize() override { glViewport(0, 0, getwidth(), getheight()); }
void drawShip(const glm::vec2 &pos)
{
//std::cout<<"draw ship @ " << pos.x << ", " << pos.y << std::endl;
glm::vec3 color = glm::vec3(0.2, 1.0, 0.3);
float radius = m_game->state()->shipRadius();
m_renderer.drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 12);
}
void drawPlanet(const glm::vec2 &pos, float radius)
{
glm::vec3 color = glm::vec3(0.7, 0.1, 0.2);
//std::cout<<"draw planet @ " << pos.x << ", " << pos.y << std::endl;
m_renderer.drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 32);
}
void drawMissile(const glm::vec2 &pos)
{
glm::vec3 color = glm::vec3(1.0, 1.0, 0.3);
m_renderer.drawCircle(pos.x, pos.y, 0.01, color.x, color.y, color.z, 6);
}
void drawTrace(const game::Trace *trace)
{
for (const game::Trace::TracePoint &p : trace->points) {
glm::vec3 color = glm::vec3(0.1, 0.3, 1.0) / (1.0f + 500.0f*p.speed);
m_renderer.drawCircle(p.position.x, p.position.y, 0.005, color.x, color.y, color.z, 3);
}
}
void drawExplosion(const game::Explosion *explosion)
{
// TODO: transparent
// TODO: with glow in the middle
float r = explosion->maxRadius * (explosion->age / explosion->maxAge);
// TODO: transparency?
glm::vec3 color = glm::vec3(1.0, 0.9, 0.1);
m_renderer.drawCircle(explosion->position.x, explosion->position.y, r, color.x, color.y, color.z, 64);
}
public:
GameWindow(unsigned int width, unsigned int height, Game* game)
: endofthejedi::GLWindow(width, height) { m_game = game; }
private:
Game *m_game;
endofthejedi::Renderer m_renderer;
GameWindow(unsigned int width, unsigned int height, Game *ptr)
: endofthejedi::GLWindow(width, height) {
m_game = ptr;
}
};

View file

@ -1,5 +1,8 @@
#include "glclasses.hpp"
#include <iostream>
#include <vector>
endofthejedi::VAO::VAO() { glGenVertexArrays(1, &m_name); }
endofthejedi::VAO::~VAO() { glDeleteVertexArrays(1, &m_name); }
@ -13,27 +16,62 @@ void endofthejedi::VAO::fill(GLuint index, GLint size, GLenum type,
glVertexAttribPointer(index, size, GL_FLOAT, normalized, stride, pointer);
}
endofthejedi::Shader::Shader() {
m_program = glCreateProgram();
}
endofthejedi::Shader::Shader() { m_program = glCreateProgram(); }
endofthejedi::Shader::~Shader() {}
void endofthejedi::Shader::bind() {
glUseProgram(m_program);
bool endofthejedi::Shader::check() {
GLint len = 0;
GLint result = 0;
glGetProgramiv(m_program, GL_LINK_STATUS, &result);
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &len);
if (len > 1) {
char *error = (char *)malloc(len);
glGetProgramInfoLog(m_program, len, NULL, error);
std::string str(error);
std::cout << str << "\n";
}
std::cout << "checked program"
<< "\n";
return (bool)result;
}
void endofthejedi::Shader::unbind() {
glUseProgram(0);
bool endofthejedi::Shader::checkShader(GLuint shader) {
GLint len = 0;
GLint result = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 1) {
char *error = (char *)malloc(len+1);
glGetShaderInfoLog(shader, 0, &len, error);
std::string str(error, error + len);
std::cout << str << "\n";
}
std::cout << "checked shader"
<< "\n";
return (bool)result;
}
void endofthejedi::Shader::bind() { glUseProgram(m_program); }
void endofthejedi::Shader::unbind() { glUseProgram(0); }
void endofthejedi::Shader::load(std::string path, GLenum shadertype) {
GLuint cheddar = glCreateShader(shadertype);
const char *cheddardata = path.c_str();
glShaderSource(cheddar, 1, &cheddardata, NULL);
glCompileShader(cheddar);
checkShader(cheddar);
glAttachShader(m_program, cheddar);
glLinkProgram(m_program);
check();
glDeleteShader(cheddar);
}
GLuint endofthejedi::Shader::location(std::string name) {
return glGetUniformLocation(m_program, name.c_str());
}

View file

@ -11,6 +11,7 @@ template <GLenum T> class BufferObject {
private:
GLuint m_name;
GLvoid *m_mappointer;
protected:
public:
BufferObject();
@ -29,17 +30,22 @@ typedef BufferObject<GL_ELEMENT_ARRAY_BUFFER> IBO;
class VAO {
private:
GLuint m_name;
protected:
public:
VAO();
~VAO();
void bind();
void fill(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride = 0, const GLvoid* pointer = NULL);
void fill(GLuint index, GLint size, GLenum type, GLboolean normalized,
GLsizei stride = 0, const GLvoid *pointer = NULL);
};
class Shader {
private:
GLuint m_program;
bool check();
bool checkShader(GLuint shader);
protected:
public:
Shader();
@ -47,8 +53,8 @@ class VAO {
void bind();
void unbind();
void load(std::string data, GLenum shadertype);
GLuint location(std::string name);
};
}
#define TBufferObject_(pre, post) \

View file

@ -3,6 +3,7 @@
#include <iostream>
#include <sys/time.h>
#include <unistd.h>
#include "options.hpp"
#define UNUSED(foo) (void) foo;

View file

@ -1,5 +1,4 @@
#pragma once
#include <stdexcept>
#include <X11/X.h>
#include <X11/Xlib.h>

234
game/raycaster.fs Normal file
View file

@ -0,0 +1,234 @@
R"raw_string(
#version 120
struct intersection
{
bool intersected;
vec3 point;
vec3 normal;
vec3 color;
float reflection;
int idx;
//todo different types
};
varying vec2 outvertex;
//settings
uniform float aspectratio;
uniform float time;
uniform int supersamples;
uniform int reflections;
uniform bool shadows;
uniform vec3 backgroundcolor;
//light
uniform vec3 l_position;
uniform float l_radius;
//spheres
//todo ubo?
uniform int s_length;
uniform vec3 s_positions[100];
uniform float s_radii[100];
uniform vec4 s_colors[100];
uniform float s_reflections[100];
const float PI = 3.14159265359;
//din = german industrial normal
float light_diffuse(vec3 pos, vec3 din)
{
vec3 l_dir = normalize(l_position - pos);
return max(dot(l_dir, din), 0.0f);
}
//adapted from https://wiki.delphigl.com/index.php/shader_ConeVolumeShadow
float light_shadow(vec3 pos)
{
float s = 1.0f;
for(int l = 0; l < s_length; l++)
{
vec3 s_pos = s_positions[l];
float s_rad = s_radii[l];
// project fragment (pos) on the cone axis => F_
vec3 nvLO = s_pos - l_position;
float dLO = length(nvLO);
nvLO /= dLO;
vec3 vLF = pos - l_position;
float dLF_ = dot(vLF, nvLO);
if (dLF_ < dLO) {
// fragment before occluder => no shadow
continue;
}
vec3 F_ = l_position + dLF_ * nvLO;
float rF = distance(F_, pos);
// compute outer and inner radius at F_
float rF_outer = (s_rad + l_radius) * (dLF_ / dLO) - l_radius;
if (rF >= rF_outer) {
// outside the outer cone => no shadow
continue;
}
float rF_inner = (s_rad - l_radius) * (dLF_ / dLO) + l_radius;
if (rF_inner >= rF) {
// inside the inner cone => full shadow
return 0.0;
}
else if (rF_inner >= 0.0 || rF >= -rF_inner) {
// soft shadow, linear interpolation
s *= (rF - rF_inner) / (rF_outer - rF_inner);
}
else {
// light from both sides of the occluder
s *= (-2.0*rF_inner) / (rF_outer - rF_inner);
}
}
return s;
}
intersection intersect_sphere(vec3 r_pos, vec3 r_dir, vec3 s_pos, float s_rad, inout float minimum)
{
intersection result = intersection(false,vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
vec3 v = r_pos - s_pos;
float a = dot(r_pos, r_pos);
float b = dot(v, r_dir);
float c = dot(v, v) - (s_rad * s_rad);
float d = b * b - c;
if(d >= 0)
{
float w1 = -b - sqrt(d);
float w2 = -b + sqrt(d);
if(w1 > 0.0f || w2 > 0.0f)
{
float w = min(w1, w2);
float o = max(w1, w2);
if(w1 <= 0.0f)
w = w2;
else
if(w2 <= 0.0f)
w = w1;
if(w < minimum)
{
minimum = w;
}
else
{
return intersection(false,vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
}
vec3 p = r_pos + (w * r_dir);
result.intersected = true;
result.point = p;
result.normal = normalize((p - s_pos) / s_rad);
return result;
}
}
return result;
}
intersection intersect(vec3 r_pos, vec3 r_dir, int idx)
{
intersection result = intersection(false,vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
float minimum = 1000.0f;
for(int l = 0; l < s_length; l++)
{
if(idx == l)
continue;
float maximum;
intersection r = intersect_sphere(r_pos, r_dir, s_positions[l], s_radii[l], minimum);
if(r.intersected)
{
r.color = s_colors[l].rgb;
r.idx = l;
r.reflection = s_reflections[l];
result = r;
}
//todo other geometric objects
//todo handle min with other geometric objects
}
return result;
}
vec3 cast_ray(vec3 r_pos, vec3 r_pixel)
{
vec3 r_dir = normalize(r_pixel - r_pos);
vec3 color = backgroundcolor;
intersection i = intersection(false,vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
vec3 p = r_pos;
vec3 d = r_dir;
int idx = -1;
for(int bounce = 0; bounce < reflections; bounce++)
{
intersection i = intersect(p,d, idx);
if(i.intersected)
{
float l_factor = light_diffuse(i.point, i.normal);
if(shadows && l_factor > 0.004f)
{
l_factor *= light_shadow(i.point);
}
if(bounce == 0)
{
color = i.color * l_factor;
}
else
{
color = mix(color, color * i.color * l_factor, i.reflection);
}
//d = 2*(dot(p, i.normal))*i.normal - p;
d = reflect(-p, i.normal);
p = i.point;
idx = i.idx;
}
else
break;
}
return color;
}
void main()
{
vec2 rp = outvertex;
rp.x = rp.x * aspectratio;
vec4 outcolor = vec4(cast_ray(vec3(0.0f, 0.0f, 1.0f), vec3(rp, 0.0f)), 0.0f);
for(int supersample = 1; supersample < supersamples; supersample++)
{
outcolor = mix(outcolor, vec4(cast_ray(vec3(sin(supersample * PI/supersamples)/200, cos(supersample * PI/supersamples)/200, 1.0f), vec3(rp, 0.0f)), 0.0f), 0.5f);
}
gl_FragColor = outcolor;
}
)raw_string"

13
game/raycaster.vs Normal file
View file

@ -0,0 +1,13 @@
R"raw_string(
#version 120
attribute vec2 invertex;
varying vec2 outvertex;
void main() {
gl_Position.xy = invertex;
gl_Position.zw = vec2(0.0f, 1.0);
outvertex = invertex;
}
)raw_string"

View file

@ -1,18 +1,4 @@
#include "renderer.hpp"
endofthejedi::Renderer::Renderer() {
}
endofthejedi::Renderer::~Renderer() {}
void endofthejedi::Renderer::drawCircle(float x, float y, float radius, float r, float g, float b, int numSides)
{
glBegin(GL_TRIANGLE_FAN);
glColor3f(r,g,b);
glVertex2f(x, y); // center of circle
for (int i = 0; i <= numSides; i++) {
glVertex2f(x + (radius * cos(i * 2 * M_PI / numSides)), y + (radius * sin(i * 2 * M_PI / numSides)));
}
glEnd();
void endofthejedi::Renderer::render(const game::State *state) {
}

View file

@ -5,21 +5,15 @@
#include <epoxy/gl.h>
#include <epoxy/glx.h>
#include "glclasses.hpp"
#include "game.hpp"
namespace endofthejedi {
class Renderer {
private:
VBO m_vbo;
VAO m_vao;
Shader m_shader;
protected:
public:
Renderer();
~Renderer();
void drawCircle(float x, float y, float radius, float r,
float g, float b, int numSides=12);
virtual void render(const game::State *state);
};
}

75
game/renderer_shader.cpp Normal file
View file

@ -0,0 +1,75 @@
#include "renderer_shader.hpp"
#include <vector>
#include "glm/glm.hpp"
#include "glm/vec2.hpp"
#include "glm/vec3.hpp"
#include "glm/gtc/type_ptr.hpp"
endofthejedi::RendererShader::RendererShader() {
m_shader.load(vss, GL_VERTEX_SHADER);
m_shader.load(fss, GL_FRAGMENT_SHADER);
}
void endofthejedi::RendererShader::render(const game::State *state) {
m_shader.bind();
std::vector<glm::vec3> positions;
std::vector<glm::vec4> colors;
std::vector<GLfloat> radii;
std::vector<GLfloat> reflections;
for (const game::Planet *planet : state->planets) {
positions.push_back(glm::vec3(planet->position, -5.0f));
radii.push_back(planet->radius);
colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
}
for (const game::Ship *ship : state->ships) {
positions.push_back(glm::vec3(ship->position, -3.0f));
radii.push_back(ship->radius);
colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
}
for (const game::Player *player : state->players) {
for (const game::Missile *missile : player->missiles) {
positions.push_back(glm::vec3(missile->position, -3.0f));
radii.push_back(0.01f);
colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
}
}
for (auto &pos : positions) {
pos.x *= 5;
pos.y *= 5;
}
for (auto &rad : radii) {
rad *= 5;
}
/*
for (const game::Trace *trace : state->traces) {
positions.push_back(glm::vec3(trace->position, -3.0f));
radii.push_back(trace->radius);
colors.push_back(glm::vec4(0.0f, 1.0f, 0.0f, 0.5f));
}*/
glUniform1f(m_shader.location("aspectratio"), 1.0f);
glUniform1i(m_shader.location("reflections"), 1);
glUniform3f(m_shader.location("l_position"), 0.6f, 0.1f, 0.0f);
glUniform1f(m_shader.location("l_radius"), 1.0f);
glUniform3fv(m_shader.location("s_positions"), positions.size(),
glm::value_ptr(positions[0]));
glUniform4fv(m_shader.location("s_colors"), colors.size(),
glm::value_ptr(colors[0]));
glUniform1fv(m_shader.location("s_radii"), radii.size(), &radii[0]);
glUniform1i(m_shader.location("s_length"), positions.size());
// render fullscreen quad with legacy opengl (too lazy, sorry)
glBegin(GL_QUADS);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, -1.0f);
glVertex2f(1.0f, 1.0f);
glVertex2f(-1.0f, 1.0f);
glEnd();
}

30
game/renderer_shader.hpp Normal file
View file

@ -0,0 +1,30 @@
#pragma once
static const char *vss =
#include "raycaster.vs"
;
static const char *fss =
#include "raycaster.fs"
;
#include "renderer.hpp"
#include "glclasses.hpp"
#include "game.hpp"
#include "state/planet.hpp"
#include "state/trace.hpp"
#include "state/player.hpp"
#include "state/ship.hpp"
namespace endofthejedi {
class RendererShader : Renderer {
private:
Shader m_shader;
protected:
public:
RendererShader();
void render(const game::State *state) override;
};
}

79
game/renderer_simple.cpp Normal file
View file

@ -0,0 +1,79 @@
#include "renderer_simple.hpp"
void endofthejedi::RendererSimple::drawCircle(float x, float y, float radius,
float r, float g, float b,
int numSides) {
glBegin(GL_TRIANGLE_FAN);
glColor3f(r, g, b);
glVertex2f(x, y); // center of circle
for (int i = 0; i <= numSides; i++) {
glVertex2f(x + (radius * cos(i * 2 * M_PI / numSides)),
y + (radius * sin(i * 2 * M_PI / numSides)));
}
glEnd();
}
void endofthejedi::RendererSimple::drawShip(const glm::vec2 &pos,
float radius) {
// std::cout<<"draw ship @ " << pos.x << ", " << pos.y << std::endl;
glm::vec3 color = glm::vec3(0.2, 1.0, 0.3);
drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 12);
}
void endofthejedi::RendererSimple::drawPlanet(const glm::vec2 &pos,
float radius) {
glm::vec3 color = glm::vec3(0.7, 0.1, 0.2);
// std::cout<<"draw planet @ " << pos.x << ", " << pos.y << std::endl;
drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 32);
}
void endofthejedi::RendererSimple::drawMissile(const glm::vec2 &pos) {
glm::vec3 color = glm::vec3(1.0, 1.0, 0.3);
drawCircle(pos.x, pos.y, 0.01, color.x, color.y, color.z, 6);
}
void endofthejedi::RendererSimple::drawTrace(const game::Trace *trace) {
for (const game::Trace::TracePoint &p : trace->points) {
glm::vec3 color = glm::vec3(0.1, 0.3, 1.0) / (1.0f + 500.0f * p.speed);
drawCircle(p.position.x, p.position.y, 0.005, color.x, color.y, color.z,
3);
}
}
void endofthejedi::RendererSimple::drawExplosion(
const game::Explosion *explosion) {
// TODO: transparent
// TODO: with glow in the middle
float r = explosion->maxRadius * (explosion->age / explosion->maxAge);
// TODO: transparency?
glm::vec3 color = glm::vec3(1.0, 0.9, 0.1);
drawCircle(explosion->position.x, explosion->position.y, r, color.x,
color.y, color.z, 64);
}
void endofthejedi::RendererSimple::render(const game::State *state) {
for (const game::Planet *planet : state->planets) {
drawPlanet(planet->position, planet->radius);
}
for (const game::Trace *trace : state->traces) {
drawTrace(trace);
}
for (const game::Explosion *explosion : state->explosions) {
drawExplosion(explosion);
}
for (const game::Ship *ship : state->ships) {
drawShip(ship->position, ship->radius);
}
for (const game::Player *player : state->players) {
for (const game::Missile *missile : player->missiles) {
drawMissile(missile->position);
}
}
}

33
game/renderer_simple.hpp Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include "renderer.hpp"
#include "glclasses.hpp"
#include "game.hpp"
#include "state/trace.hpp"
#include "state/object.hpp"
#include "state/missile.hpp"
#include "state/player.hpp"
#include "state/planet.hpp"
#include "state/ship.hpp"
#include "state/explosion.hpp"
namespace endofthejedi {
class RendererSimple : Renderer {
private:
void drawCircle(float x, float y, float radius, float r, float g, float b,
int numSides = 12);
void drawShip(const glm::vec2 &pos, float radius);
void drawPlanet(const glm::vec2 &pos, float radius);
void drawMissile(const glm::vec2 &pos);
void drawTrace(const game::Trace *trace);
void drawExplosion(const game::Explosion *explosion);
protected:
public:
void render(const game::State *state) override;
};
}

View file

@ -1,5 +1,7 @@
#pragma once
#define ASIO_STANDALONE
#include <iostream>
#include <memory>
#include <utility>

View file

@ -1,36 +0,0 @@
#pragma once
#include "opengl.hpp"
class TriangleWindow : public endofthejedi::GLWindow {
private:
protected:
void init() override {
glClearColor(0.5f, 0.6f, 0.7f, 1.0f);
resize();
glEnable(GL_DEPTH_TEST);
}
void render(double time) override {
(void) time;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, -1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glEnd();
}
void resize() override { glViewport(0, 0, getwidth(), getheight()); }
public:
TriangleWindow(unsigned int width, unsigned int height)
: endofthejedi::GLWindow(width, height)
{
}
};