grouped files in subdirs.

This commit is contained in:
Andreas Ortmann 2016-09-28 11:50:35 +02:00
parent 7d8585c5d9
commit aedda9d48e
14 changed files with 281 additions and 11 deletions

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"

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

@ -0,0 +1,88 @@
#include "renderer_ray_tracer.hpp"
#include <vector>
#include "glm/glm.hpp"
#include "glm/vec2.hpp"
#include "glm/vec3.hpp"
#include "glm/gtc/type_ptr.hpp"
static const char *vss =
#include "raycaster.vs"
;
static const char *fss =
#include "raycaster.fs"
;
namespace endofthejedi {
RendererRayTracer::RendererRayTracer() {
m_shader.load(vss, GL_VERTEX_SHADER);
m_shader.load(fss, GL_FRAGMENT_SHADER);
}
void RendererRayTracer::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();
}
}

View file

@ -0,0 +1,23 @@
#pragma once
#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 RendererRayTracer: Renderer {
private:
Shader m_shader;
protected:
public:
RendererRayTracer();
void render(const game::State *state) override;
};
}