nicer particles, adding code so that particles don't penetrate through planets. added not-yet compeleted intersection code.
This commit is contained in:
parent
57e6e56217
commit
4712926be2
6 changed files with 207 additions and 17 deletions
|
@ -1,10 +1,13 @@
|
||||||
#version 120
|
#version 120
|
||||||
|
varying vec3 position;
|
||||||
varying vec2 vertex;
|
varying vec2 vertex;
|
||||||
varying vec3 velocity;
|
varying vec3 velocity;
|
||||||
varying float decay;
|
varying float decay;
|
||||||
|
|
||||||
varying float explCenterDist;
|
varying float explCenterDist;
|
||||||
|
|
||||||
|
float pi = 3.14159;
|
||||||
|
|
||||||
vec3 hsv2rgb(vec3 c)
|
vec3 hsv2rgb(vec3 c)
|
||||||
{
|
{
|
||||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||||
|
@ -12,15 +15,28 @@ vec3 hsv2rgb(vec3 c)
|
||||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float hash(float n)
|
||||||
|
{
|
||||||
|
return fract(sin(n)*43758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float r = length(vertex);
|
// normalize radius from 0..1
|
||||||
if (r > 1.0) {
|
vec2 vn = 2.0*vertex;
|
||||||
|
float rn = length(vn);
|
||||||
|
float angle = atan(vn.y, vn.x);
|
||||||
|
float hs = 20.0;
|
||||||
|
float removeCorners = 0.5 * (hash(fract(hs*vertex.x)) + hash(fract(hs*vertex.y)));
|
||||||
|
if (rn+removeCorners > 1.0) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//float rf = 0.5-0.5*rn;
|
||||||
|
float rf = 1.0;
|
||||||
|
|
||||||
float d = decay/(1.0+max(0.0, 1.0-2.0*explCenterDist));
|
float d = decay/(1.0+max(0.0, 1.0-2.0*explCenterDist));
|
||||||
float h = (1.0-d)/6.0;
|
float h = max(0.0, (1.0-d)/6.0) * rf;
|
||||||
float v = max(0.0, (1.0-log(d)));
|
float v = max(0.0, (1.0-log(d)));
|
||||||
float s = max(0.0, min(30.0 * sqrt(decay) * explCenterDist, 1.0));
|
float s = max(0.0, min(30.0 * sqrt(decay) * explCenterDist, 1.0));
|
||||||
|
|
||||||
|
@ -30,4 +46,5 @@ void main()
|
||||||
gl_FragColor = vec4(hsv2rgb(vec3(h, s, v)), 1.0);
|
gl_FragColor = vec4(hsv2rgb(vec3(h, s, v)), 1.0);
|
||||||
|
|
||||||
//gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
|
//gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
|
||||||
|
//gl_FragColor.rgb = vec3(0.5+0.5*(a/pi));
|
||||||
}
|
}
|
|
@ -14,6 +14,7 @@ varying float decay;
|
||||||
varying vec3 velocity;
|
varying vec3 velocity;
|
||||||
varying vec2 vertex;
|
varying vec2 vertex;
|
||||||
varying float explCenterDist;
|
varying float explCenterDist;
|
||||||
|
varying vec3 position;
|
||||||
|
|
||||||
uniform float aspectRatio;
|
uniform float aspectRatio;
|
||||||
|
|
||||||
|
@ -31,9 +32,9 @@ void main()
|
||||||
// faster particles are smaller
|
// faster particles are smaller
|
||||||
// TODO: scale by time too! scale down fast after 3 halfAges
|
// TODO: scale by time too! scale down fast after 3 halfAges
|
||||||
float scaleBySpeed = (1.0 - 0.95*length(in_velocity)/maxVelocity);
|
float scaleBySpeed = (1.0 - 0.95*length(in_velocity)/maxVelocity);
|
||||||
float finalSize = size * scaleBySpeed;
|
float finalSize = size * scaleBySpeed * (1.0-max(0.0, decay-3.0*halfAge)/2.0);
|
||||||
vec2 base = in_geometry;
|
vec2 base = in_geometry;
|
||||||
vec3 p = finalSize*vec3(base, 0.0);
|
vec3 p = vec3(finalSize*base, 0.0);
|
||||||
vec3 move = (0.2*age + log(1.0+age*5.0)) * in_velocity;
|
vec3 move = (0.2*age + log(1.0+age*5.0)) * in_velocity;
|
||||||
float md = length(move);
|
float md = length(move);
|
||||||
if (md > in_maxDist) {
|
if (md > in_maxDist) {
|
||||||
|
@ -46,6 +47,7 @@ void main()
|
||||||
|
|
||||||
vertex = base.xy;
|
vertex = base.xy;
|
||||||
velocity = in_velocity;
|
velocity = in_velocity;
|
||||||
|
position = in_position;
|
||||||
|
|
||||||
explCenterDist = length(explCenter - offset);
|
explCenterDist = length(explCenter - offset);
|
||||||
}
|
}
|
|
@ -25,10 +25,10 @@ namespace endofthejedi {
|
||||||
// TODO
|
// TODO
|
||||||
// it is transformed before uploading so it looks at the camera
|
// it is transformed before uploading so it looks at the camera
|
||||||
, m_data_geometry({
|
, m_data_geometry({
|
||||||
1.0f, -1.0f,
|
0.5f, -0.5f,
|
||||||
1.0f, 1.0f,
|
0.5f, 0.5f,
|
||||||
-1.0f, 1.0f,
|
-0.5f, 0.5f,
|
||||||
-1.0f, -1.0f})
|
-0.5f, -0.5f})
|
||||||
{
|
{
|
||||||
m_num_vertex_buffers = 4;
|
m_num_vertex_buffers = 4;
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,9 @@ namespace endofthejedi {
|
||||||
// TODO: add dust particles
|
// TODO: add dust particles
|
||||||
// TODO: add little rocks flying around
|
// TODO: add little rocks flying around
|
||||||
|
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
//glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
//float s = 0.1;
|
float s = 0.1;
|
||||||
//glClearColor(s, s, s, 1.0);
|
glClearColor(s, s, 1.2*s, 1.0);
|
||||||
|
|
||||||
m_shader_game_objects.bind();
|
m_shader_game_objects.bind();
|
||||||
|
|
||||||
|
@ -94,11 +94,11 @@ namespace endofthejedi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererPolygon3d::addExplosionEffect(size_t id, const glm::vec2 &pos, size_t n, float duration)
|
void RendererPolygon3d::addExplosionEffect(size_t id, const glm::vec2 &explCenter, size_t n, float duration)
|
||||||
{
|
{
|
||||||
//float particleRadius = 0.005;
|
//float particleRadius = 0.005;
|
||||||
//float particleRadius = 0.003;
|
//float particleRadius = 0.003;
|
||||||
float particleRadius = 0.005;
|
float particleRadius = 0.02;
|
||||||
|
|
||||||
// TODO: use this as shader input too and make the area 2x around this
|
// TODO: use this as shader input too and make the area 2x around this
|
||||||
// so that it stays hot/yellow for 2/3 of the time
|
// so that it stays hot/yellow for 2/3 of the time
|
||||||
|
@ -107,7 +107,7 @@ namespace endofthejedi {
|
||||||
|
|
||||||
ParticleBatch *batch = new ParticleBatch(id, n, particleRadius, duration);
|
ParticleBatch *batch = new ParticleBatch(id, n, particleRadius, duration);
|
||||||
batch->setup(&m_shader_particles);
|
batch->setup(&m_shader_particles);
|
||||||
batch->setCenter(glm::vec3(pos, 0.0));
|
batch->setCenter(glm::vec3(explCenter, 0.0));
|
||||||
batch->setMaxVelocity(maxVelocity);
|
batch->setMaxVelocity(maxVelocity);
|
||||||
|
|
||||||
for (size_t i=0; i<n; i++) {
|
for (size_t i=0; i<n; i++) {
|
||||||
|
@ -121,11 +121,84 @@ namespace endofthejedi {
|
||||||
// especially in 3d this would look bad without 3d velocity vector.
|
// especially in 3d this would look bad without 3d velocity vector.
|
||||||
//glm::vec3 v = 0.5f*glm::vec3(sin(t), cos(t), util::randf_m1_1());
|
//glm::vec3 v = 0.5f*glm::vec3(sin(t), cos(t), util::randf_m1_1());
|
||||||
|
|
||||||
|
glm::vec3 pos = glm::vec3(explCenter, 0.0) + glm::ballRand(explCoreSize);
|
||||||
|
|
||||||
glm::vec3 v = glm::ballRand(maxVelocity);
|
glm::vec3 v = glm::ballRand(maxVelocity);
|
||||||
v *= util::randf_0_1() * util::randf_0_1() * util::randf_0_1();
|
v *= util::randf_0_1() * util::randf_0_1() * util::randf_0_1();
|
||||||
|
|
||||||
float maxDist = 0.2;
|
// find collisions with planetns and limit max distance so particles
|
||||||
batch->setParticle(i, glm::vec3(pos, 0.0) + glm::ballRand(explCoreSize), v, maxDist);
|
// won't fly through planets
|
||||||
|
//float maxDist = 0.1;
|
||||||
|
//float maxDist = 0.1*util::randf_0_1();
|
||||||
|
bool isInsidePlanet = false;
|
||||||
|
float maxParticleDist = INFINITY;
|
||||||
|
|
||||||
|
const game::Planet *nearestPlanet = nullptr;
|
||||||
|
for (const game::Planet *planet : m_state->planets) {
|
||||||
|
const glm::vec3 ppos3 = glm::vec3(planet->position, 0.0f);
|
||||||
|
// TODO: check if inside planet!
|
||||||
|
float dist = glm::distance(ppos3, pos);
|
||||||
|
if (dist <= planet->radius) {
|
||||||
|
isInsidePlanet = true;
|
||||||
|
nearestPlanet = planet;
|
||||||
|
}
|
||||||
|
if (isInsidePlanet) {
|
||||||
|
// skip searching for nearer planets once we are inside some
|
||||||
|
// planet as the position/velocity will be changed to start
|
||||||
|
// at the surface of the planet we were in with
|
||||||
|
// reflected or planet-normal velocity.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// TODO: if inside, move position so that it looks like
|
||||||
|
// reflecting the particle from the planet
|
||||||
|
bool fliesInPlanetDirection = glm::dot(v, ppos3-pos) > 0.0f;
|
||||||
|
if (dist < maxParticleDist && fliesInPlanetDirection) {
|
||||||
|
nearestPlanet = planet;
|
||||||
|
maxParticleDist = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInsidePlanet) {
|
||||||
|
util::IntersectionTest intersect;
|
||||||
|
if (!intersect.raySphere(
|
||||||
|
pos, v,
|
||||||
|
glm::vec3(nearestPlanet->position, 0.0f), nearestPlanet->radius))
|
||||||
|
{
|
||||||
|
//std::cout<<"warning: intersection should be valid!" << std::endl;
|
||||||
|
// TODO: must be as they lie on a plane and the dist is < as
|
||||||
|
// the radius.
|
||||||
|
// handle if this is wrong.
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// set position to the intersection point between explosion
|
||||||
|
// center and planet surface
|
||||||
|
//const glm::vec3 planetNormal = glm::vec3(glm::normalize(explCenter - nearestPlanet->position), 0.0f);
|
||||||
|
|
||||||
|
//pos = glm::vec3(nearestPlanet->position, 0.0f) + nearestPlanet->radius*planetNormal;
|
||||||
|
|
||||||
|
// build new velocity by reflecting the old velocity on the
|
||||||
|
// planet normal
|
||||||
|
// TODO: add a bit random
|
||||||
|
// TODO: add reflection
|
||||||
|
// TODO: distribute particles around main reflection angle and
|
||||||
|
// TODO: add material exhaust that is specific for the planet.
|
||||||
|
// TODO: spawn waves on water planet
|
||||||
|
// TODO: start fire on gas planet
|
||||||
|
//v = glm::length(v) * planetNormal;
|
||||||
|
//v = v - 2.0f*glm::dot(v, planetNormal) * planetNormal;
|
||||||
|
//v = glm::length(v) * planetNormal;
|
||||||
|
|
||||||
|
//glm::vec3 r = v - 2.0f*glm::dot(v, planetNormal) * planetNormal;
|
||||||
|
//glm::vec3 vn = glm::length(v) * planetNormal;
|
||||||
|
//v = (r+vn) / 2.0f;
|
||||||
|
|
||||||
|
//glm::vec3 vc = glm::vec3(nearestPlanet->position-explCenter, 0.0f);
|
||||||
|
//glm::vec3 r = vc - 2.0f*glm::dot(vc, planetNormal) * planetNormal;
|
||||||
|
//v = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
batch->setParticle(i, pos, v, maxParticleDist);
|
||||||
}
|
}
|
||||||
|
|
||||||
batch->upload();
|
batch->upload();
|
||||||
|
@ -189,6 +262,8 @@ namespace endofthejedi {
|
||||||
|
|
||||||
void RendererPolygon3d::renderMissiles()
|
void RendererPolygon3d::renderMissiles()
|
||||||
{
|
{
|
||||||
|
// TODO: add fire trail for missiles near the sun
|
||||||
|
|
||||||
m_missileModel->bind();
|
m_missileModel->bind();
|
||||||
|
|
||||||
for (const game::Player *player : m_state->players) {
|
for (const game::Player *player : m_state->players) {
|
||||||
|
|
|
@ -33,4 +33,71 @@ namespace util {
|
||||||
{
|
{
|
||||||
return 180.0 * rad / M_PI;
|
return 180.0 * rad / M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IntersectionTest::IntersectionTest() : m_valid(false), m_distance(INFINITY)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::IntersectionTest(float d) : m_valid(true), m_distance(d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float IntersectionTest::distance() const { assert(m_valid); return m_distance; }
|
||||||
|
bool IntersectionTest::valid() const { return m_valid; }
|
||||||
|
|
||||||
|
bool IntersectionTest::raySphere(
|
||||||
|
const glm::vec3 &rayPos, const glm::vec3 &rayDir,
|
||||||
|
const glm::vec3 &spherePos, float sphereRadius)
|
||||||
|
{
|
||||||
|
m_valid = false;
|
||||||
|
|
||||||
|
// TODO: get code
|
||||||
|
return m_valid;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
const glm::vec3 &o = ray.pos();
|
||||||
|
const glm::vec3 &l = ray.dir();
|
||||||
|
const glm::vec3 &c = m_pos;
|
||||||
|
const float &r = m_radius;
|
||||||
|
|
||||||
|
const glm::vec3 omc = o-c;
|
||||||
|
const float dot = glm::dot(l, omc);
|
||||||
|
const float s = dot*dot - util::dotSelf(omc) + r*r;
|
||||||
|
|
||||||
|
if (s < 0.001) {
|
||||||
|
return RayIntersection();
|
||||||
|
}
|
||||||
|
|
||||||
|
const float t = -dot;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// TODO: is that meant as t?
|
||||||
|
if (s == 0) {
|
||||||
|
// not interested in touch point
|
||||||
|
return RayIntersection();
|
||||||
|
|
||||||
|
//d1 = t;
|
||||||
|
//return RayTouchesOnePoint;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const float sr = sqrt(s);
|
||||||
|
|
||||||
|
d1 = t - sr;
|
||||||
|
d2 = t + sr;
|
||||||
|
|
||||||
|
// if end intersection lies behind it, this is completely uninteresting for us
|
||||||
|
// 0.01 because to get rid of rounding/precision errors
|
||||||
|
if (d2 <= 0.01) {
|
||||||
|
return RayIntersection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the start of the interval lies behind us, make it 0 because we just
|
||||||
|
// want to know whats before us.
|
||||||
|
// 0.01 because to get rid of rounding/precision errors
|
||||||
|
if (d1 < 0.0) {
|
||||||
|
d1 = 0.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <glm/vec2.hpp>
|
#include <glm/vec2.hpp>
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
|
@ -12,4 +13,32 @@ namespace util {
|
||||||
|
|
||||||
float deg2rad(float deg);
|
float deg2rad(float deg);
|
||||||
float rad2deg(float rad);
|
float rad2deg(float rad);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for intersection in positive direction of a ray.
|
||||||
|
* TODO: support inside?
|
||||||
|
*/
|
||||||
|
class IntersectionTest {
|
||||||
|
public:
|
||||||
|
IntersectionTest();
|
||||||
|
|
||||||
|
// creates a valid intersection point at distance d
|
||||||
|
IntersectionTest(float d);
|
||||||
|
|
||||||
|
// intersection distance
|
||||||
|
float distance() const;
|
||||||
|
|
||||||
|
// returns true if there's an interseciton.
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
// return true if there's an intersection. then intersectionPoint is filled
|
||||||
|
// with details.
|
||||||
|
bool raySphere(
|
||||||
|
const glm::vec3 &rayPos, const glm::vec3 &rayDir,
|
||||||
|
const glm::vec3 &spherePos, float sphereRadius);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_valid;
|
||||||
|
float m_distance;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue