X Tutup
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions data/shaders/opengl/thruster.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright © 2008-2026 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

#include "attributes.glsl"
#include "lib.glsl"

uniform sampler2D texture0; //diffuse

in vec2 texCoord0;
in vec4 flame_color;
in float ramp;

out vec4 frag_color;

void main(void)
{
vec4 color = texture(texture0, texCoord0);
vec3 old_color = color.rgb;
color *= flame_color;
// generate a light blue flickering glow around the flame
float ramp2 = ramp * ramp;
color.g += ramp2 * ramp2 * old_color.g;
color.r += ramp2 * ramp * old_color.r;
color.b += ramp2 * old_color.b;

frag_color = color;
}
12 changes: 12 additions & 0 deletions data/shaders/opengl/thruster.shaderdef
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Copyright © 2008-2026 Pioneer Developers. See AUTHORS.txt for details
## Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

# Basic shader for drawing unlit, possibly textured models that are animated

Shader thruster

Texture sampler2D texture0 name=texture0
Buffer DrawData binding=1

Vertex "thruster.vert"
Fragment "thruster.frag"
46 changes: 46 additions & 0 deletions data/shaders/opengl/thruster.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright © 2008-2026 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

// #extension GL_ARB_gpu_shader5 : enable

#include "attributes.glsl"
#include "lib.glsl"

out vec2 texCoord0;
out vec4 flame_color;
out float ramp;

float map_percentage( float val, float base_percent)
{
return base_percent + val * (1.0 - base_percent);
}

void main(void)
{
// emission.r is the thruster power setting
float thruster_power = material.emission.r;
// emission.a is the random flicker value
float random = material.emission.a;

// power setting effects the brightness and opacity of the flame
float brightness = map_percentage(thruster_power, 0.25);
// flicker should only change the brightness a small amount each frame
float flicker = map_percentage(random, 0.95);

flame_color = material.diffuse * flicker * brightness;
// a very light blue flickering glow around flame
flame_color.rg *= vec2(flicker);

// the power setting also controls the length of the flame
// flame length can range from 50% to 100%
float flame_length = map_percentage(thruster_power, 0.5);
// modulate the flame shape using flicker
// flame_length only effects the z axis which is the thrust direction
vec4 scale = vec4(flicker, flicker, flicker * flame_length, 1.0);

gl_Position = uViewProjectionMatrix * (a_vertex * scale);

texCoord0 = a_uv0.xy;
// set the blend ramp
ramp = a_uv0.y * 0.5;
}
1 change: 1 addition & 0 deletions src/Intro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,6 @@ void Intro::Draw(float deltaTime)
matrix4x4f::Translation(0, 0, m_dist) *
matrix4x4f::RotateXMatrix(DEG2RAD(-15.0f)) *
matrix4x4f::RotateYMatrix(duration);
m_model->SetRenderTime(duration);
m_model->Render(trans);
}
1 change: 1 addition & 0 deletions src/ShipCockpit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ void ShipCockpit::Update(const Player *player, float timeStep)
vector3f linthrust{ prop->GetLinThrusterState() };
vector3f angthrust{ prop->GetAngThrusterState() };
GetModel()->SetThrust(linthrust, -angthrust);
GetModel()->SetRenderTime(Pi::game->GetTime());
}
}

Expand Down
1 change: 1 addition & 0 deletions src/editor/ModelViewerWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ void ModelViewerWidget::DrawModel(matrix4x4f trans)
(m_options.showGeomBBox ? SceneGraph::Model::DEBUG_GEOMBBOX : 0x0) |
(m_options.wireframe ? SceneGraph::Model::DEBUG_WIREFRAME : 0x0));

m_model->SetRenderTime(GetApp()->GetTime());
m_model->Render(m_modelViewMat);
m_navLights->Render(m_renderer);
}
Expand Down
1 change: 1 addition & 0 deletions src/scenegraph/Model.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ namespace SceneGraph {
Graphics::Renderer *GetRenderer() const { return m_renderer; }

//special for ship model use
void SetRenderTime(const double newRenderTime) { m_renderData.renderTime = newRenderTime; }
void SetThrust(const vector3f &linear, const vector3f &angular);

void SetThrusterColor(const vector3f &dir, const Color &color);
Expand Down
6 changes: 4 additions & 2 deletions src/scenegraph/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ namespace SceneGraph {
Color customColor;

float boundingRadius; //updated by model and passed to submodels
unsigned int nodemask;
uint32_t nodemask;
double renderTime;

RenderData() :
linthrust(),
angthrust(),
boundingRadius(0.f),
nodemask(NODE_SOLID) //draw solids
nodemask(NODE_SOLID), //draw solids
renderTime(0.0)
{
}
};
Expand Down
57 changes: 46 additions & 11 deletions src/scenegraph/Thruster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,23 @@ namespace SceneGraph {
static const std::string thrusterGlowTextureFilename("textures/halo.dds");
static Color baseColor(178, 153, 255, 255);

uint32_t hash32(uint32_t x)
{
x ^= x >> 16;
x *= 0x21f0aaad;
x ^= x >> 15;
x *= 0xd35a2d97;
x ^= x >> 15;
return x;
}

Thruster::Thruster(Graphics::Renderer *r, bool _linear, const vector3f &_pos, const vector3f &_dir) :
Node(r, NODE_TRANSPARENT),
linearOnly(_linear),
dir(_dir),
pos(_pos),
currentColor(baseColor)
currentColor(baseColor),
displayedPower(0.f)
{
//set up materials
Graphics::MaterialDescriptor desc;
Expand All @@ -43,12 +54,12 @@ namespace SceneGraph {

auto vtxFormat = Graphics::VertexFormatDesc::FromAttribSet(Graphics::ATTRIB_POSITION | Graphics::ATTRIB_UV0);

m_tMat.Reset(r->CreateMaterial("unlit", desc, rsd, vtxFormat));
m_tMat.Reset(r->CreateMaterial("thruster", desc, rsd, vtxFormat));
m_tMat->SetTexture("texture0"_hash,
Graphics::TextureBuilder::Billboard(thrusterTextureFilename).GetOrCreateTexture(r, "billboard"));
m_tMat->diffuse = baseColor;

m_glowMat.Reset(r->CreateMaterial("unlit", desc, rsd, vtxFormat));
m_glowMat.Reset(r->CreateMaterial("thruster", desc, rsd, vtxFormat));
m_glowMat->SetTexture("texture0"_hash,
Graphics::TextureBuilder::Billboard(thrusterGlowTextureFilename).GetOrCreateTexture(r, "billboard"));
m_glowMat->diffuse = baseColor;
Expand All @@ -61,7 +72,8 @@ namespace SceneGraph {
linearOnly(thruster.linearOnly),
dir(thruster.dir),
pos(thruster.pos),
currentColor(thruster.currentColor)
currentColor(thruster.currentColor),
displayedPower(thruster.displayedPower)
{
}

Expand Down Expand Up @@ -101,9 +113,32 @@ namespace SceneGraph {
power = fabs(at.z);
}
}
if (power < 0.001f) return;

m_tMat->diffuse = m_glowMat->diffuse = currentColor * power;
// fade in/out the amount of thruster power shown
displayedPower = MathUtil::Lerp(displayedPower, power, 0.2f);
if (displayedPower < 0.01f) {
return;
}

// animate the thrust flame using the thruster shader
// update animation time on each render
// a unique time stamp is needed for each thruster flame to have a unique flicker
// use thruster position to make each thruster time different
// generate a psuedo random flicker
// this could be done in the vertex shader but the value only needs to be
// generated once per frame, not for every vertex
float hash = pos.x + pos.y + pos.z;
hash = (uint16_t(hash32(*reinterpret_cast<uint32_t *>(&hash)) & 0xFFFF)) / 65535.f;
const float flicker = abs(sin(static_cast<float>(rd->renderTime) * 55.f * (0.75f + hash * 0.5f)));

// pass the power setting and flicker value using the material emissive
// emissive.a is the flicker value for the flame
m_tMat->emissive.a = m_glowMat->emissive.a = flicker * 255.f;

// emissive.r is the thruster power setting which effects flame length and brightness
m_tMat->emissive.r = m_glowMat->emissive.r = 255.0f * displayedPower;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a huge fan of retaining the displayedPower state variable, but if the smooth fade makes a perceptual difference then I will not protest it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it does, but feel free to hack at it and see if there's anything better!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do any further hacking-about in master, thanks!


m_tMat->diffuse = m_glowMat->diffuse = currentColor;

//directional fade
vector3f cdir = vector3f(trans * -dir).Normalized();
Expand Down Expand Up @@ -184,18 +219,18 @@ namespace SceneGraph {
verts.Clear();
{
//create glow billboard when looking down the thruster
const float w = 0.2;
constexpr float w = 0.2f;

vector3f one(-w, -w, 0.f); //top left
vector3f two(-w, w, 0.f); //top right
vector3f three(w, w, 0.f); //bottom right
vector3f four(w, -w, 0.f); //bottom left

//uv coords
const vector2f topLeft(0.f, 1.f);
const vector2f topRight(1.f, 1.f);
const vector2f botLeft(0.f, 0.f);
const vector2f botRight(1.f, 0.f);
static constexpr vector2f const topLeft(0.f, 1.f);
static constexpr vector2f const topRight(1.f, 1.f);
static constexpr vector2f const botLeft(0.f, 0.f);
static constexpr vector2f const botRight(1.f, 0.f);

for (int i = 0; i < 5; i++) {
verts.Add(one, topLeft);
Expand Down
1 change: 1 addition & 0 deletions src/scenegraph/Thruster.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace SceneGraph {
vector3f dir;
vector3f pos;
Color currentColor;
float displayedPower; // used to fade in/out to power (size) of thruster shown
};

} // namespace SceneGraph
Expand Down
5 changes: 4 additions & 1 deletion src/ship/Propulsion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,10 @@ void Propulsion::Render(Graphics::Renderer *r, const Camera *camera, const vecto
* thruster and so on)... this code is :-/
*/
//angthrust negated, for some reason
if (m_smodel != nullptr) m_smodel->SetThrust(vector3f(GetLinThrusterState()), -vector3f(GetAngThrusterState()));
if (m_smodel != nullptr) {
m_smodel->SetThrust(vector3f(GetLinThrusterState()), -vector3f(GetAngThrusterState()));
m_smodel->SetRenderTime(Pi::game->GetTime());
}
}

void Propulsion::AIModelCoordsMatchSpeedRelTo(const vector3d &v, const DynamicBody *other)
Expand Down
2 changes: 1 addition & 1 deletion src/vector2.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class vector2 {
vector2() :
x(0.0f),
y(0.0f) {}
vector2(T _x, T _y) :
constexpr vector2(T _x, T _y) :
x(_x),
y(_y) {}
explicit vector2(int v) :
Expand Down
X Tutup