grouped files in subdirs.
This commit is contained in:
parent
7d8585c5d9
commit
aedda9d48e
14 changed files with 281 additions and 11 deletions
234
game/renderer_ray_tracer/raycaster.fs
Normal file
234
game/renderer_ray_tracer/raycaster.fs
Normal 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/renderer_ray_tracer/raycaster.vs
Normal file
13
game/renderer_ray_tracer/raycaster.vs
Normal 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"
|
||||
88
game/renderer_ray_tracer/renderer_ray_tracer.cpp
Normal file
88
game/renderer_ray_tracer/renderer_ray_tracer.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
23
game/renderer_ray_tracer/renderer_ray_tracer.hpp
Normal file
23
game/renderer_ray_tracer/renderer_ray_tracer.hpp
Normal 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;
|
||||
};
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue