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
|
||||
varying vec3 position;
|
||||
varying vec2 vertex;
|
||||
varying vec3 velocity;
|
||||
varying float decay;
|
||||
|
||||
varying float explCenterDist;
|
||||
|
||||
float pi = 3.14159;
|
||||
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
float hash(float n)
|
||||
{
|
||||
return fract(sin(n)*43758.5453);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float r = length(vertex);
|
||||
if (r > 1.0) {
|
||||
// normalize radius from 0..1
|
||||
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;
|
||||
}
|
||||
|
||||
//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 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 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(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 vec2 vertex;
|
||||
varying float explCenterDist;
|
||||
varying vec3 position;
|
||||
|
||||
uniform float aspectRatio;
|
||||
|
||||
|
@ -31,9 +32,9 @@ void main()
|
|||
// faster particles are smaller
|
||||
// TODO: scale by time too! scale down fast after 3 halfAges
|
||||
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;
|
||||
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;
|
||||
float md = length(move);
|
||||
if (md > in_maxDist) {
|
||||
|
@ -46,6 +47,7 @@ void main()
|
|||
|
||||
vertex = base.xy;
|
||||
velocity = in_velocity;
|
||||
position = in_position;
|
||||
|
||||
explCenterDist = length(explCenter - offset);
|
||||
}
|
|
@ -25,10 +25,10 @@ namespace endofthejedi {
|
|||
// TODO
|
||||
// it is transformed before uploading so it looks at the camera
|
||||
, m_data_geometry({
|
||||
1.0f, -1.0f,
|
||||
1.0f, 1.0f,
|
||||
-1.0f, 1.0f,
|
||||
-1.0f, -1.0f})
|
||||
0.5f, -0.5f,
|
||||
0.5f, 0.5f,
|
||||
-0.5f, 0.5f,
|
||||
-0.5f, -0.5f})
|
||||
{
|
||||
m_num_vertex_buffers = 4;
|
||||
|
||||
|
|
|
@ -49,9 +49,9 @@ namespace endofthejedi {
|
|||
// TODO: add dust particles
|
||||
// TODO: add little rocks flying around
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
//float s = 0.1;
|
||||
//glClearColor(s, s, s, 1.0);
|
||||
//glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
float s = 0.1;
|
||||
glClearColor(s, s, 1.2*s, 1.0);
|
||||
|
||||
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.003;
|
||||
float particleRadius = 0.005;
|
||||
float particleRadius = 0.02;
|
||||
|
||||
// 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
|
||||
|
@ -107,7 +107,7 @@ namespace endofthejedi {
|
|||
|
||||
ParticleBatch *batch = new ParticleBatch(id, n, particleRadius, duration);
|
||||
batch->setup(&m_shader_particles);
|
||||
batch->setCenter(glm::vec3(pos, 0.0));
|
||||
batch->setCenter(glm::vec3(explCenter, 0.0));
|
||||
batch->setMaxVelocity(maxVelocity);
|
||||
|
||||
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.
|
||||
//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);
|
||||
v *= util::randf_0_1() * util::randf_0_1() * util::randf_0_1();
|
||||
|
||||
float maxDist = 0.2;
|
||||
batch->setParticle(i, glm::vec3(pos, 0.0) + glm::ballRand(explCoreSize), v, maxDist);
|
||||
// find collisions with planetns and limit max distance so particles
|
||||
// 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();
|
||||
|
@ -189,6 +262,8 @@ namespace endofthejedi {
|
|||
|
||||
void RendererPolygon3d::renderMissiles()
|
||||
{
|
||||
// TODO: add fire trail for missiles near the sun
|
||||
|
||||
m_missileModel->bind();
|
||||
|
||||
for (const game::Player *player : m_state->players) {
|
||||
|
|
|
@ -33,4 +33,71 @@ namespace util {
|
|||
{
|
||||
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
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
namespace util {
|
||||
|
||||
|
@ -12,4 +13,32 @@ namespace util {
|
|||
|
||||
float deg2rad(float deg);
|
||||
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