aboutsummaryrefslogtreecommitdiff
path: root/src/client/sky.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/sky.cpp')
-rw-r--r--src/client/sky.cpp225
1 files changed, 102 insertions, 123 deletions
diff --git a/src/client/sky.cpp b/src/client/sky.cpp
index 2e0cbca86..3a40321dd 100644
--- a/src/client/sky.cpp
+++ b/src/client/sky.cpp
@@ -1,6 +1,7 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2020 numzero, Lobachevskiy Vitaliy <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -34,16 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "config.h"
using namespace irr::core;
-Sky::Sky(s32 id, ITextureSource *tsrc) :
- scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
- RenderingEngine::get_scene_manager(), id)
+static video::SMaterial baseMaterial()
{
- setAutomaticCulling(scene::EAC_OFF);
- m_box.MaxEdge.set(0, 0, 0);
- m_box.MinEdge.set(0, 0, 0);
-
- // Create material
-
video::SMaterial mat;
mat.Lighting = false;
#if ENABLE_GLES
@@ -56,14 +49,31 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
mat.BackfaceCulling = false;
+ return mat;
+};
+
+Sky::Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc) :
+ scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
+ RenderingEngine::get_scene_manager(), id)
+{
+ setAutomaticCulling(scene::EAC_OFF);
+ m_box.MaxEdge.set(0, 0, 0);
+ m_box.MinEdge.set(0, 0, 0);
+
+ m_enable_shaders = g_settings->getBool("enable_shaders");
- m_materials[0] = mat;
+ // Create materials
- m_materials[1] = mat;
+ m_materials[0] = baseMaterial();
+ m_materials[0].MaterialType = ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA)).material;
+ m_materials[0].Lighting = true;
+ m_materials[0].ColorMaterial = video::ECM_NONE;
+
+ m_materials[1] = baseMaterial();
//m_materials[1].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
- m_materials[2] = mat;
+ m_materials[2] = baseMaterial();
m_materials[2].setTexture(0, tsrc->getTextureForMesh("sunrisebg.png"));
m_materials[2].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
//m_materials[2].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
@@ -80,7 +90,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
tsrc->getTexture(m_moon_params.tonemap) : NULL;
if (m_sun_texture) {
- m_materials[3] = mat;
+ m_materials[3] = baseMaterial();
m_materials[3].setTexture(0, m_sun_texture);
m_materials[3].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
// Disables texture filtering
@@ -92,7 +102,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
m_materials[3].Lighting = true;
}
if (m_moon_texture) {
- m_materials[4] = mat;
+ m_materials[4] = baseMaterial();
m_materials[4].setTexture(0, m_moon_texture);
m_materials[4].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
// Disables texture filtering
@@ -105,7 +115,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
}
for (int i = 5; i < 11; i++) {
- m_materials[i] = mat;
+ m_materials[i] = baseMaterial();
m_materials[i].Lighting = true;
m_materials[i].MaterialType = video::EMT_SOLID;
}
@@ -202,7 +212,7 @@ void Sky::render()
const f32 t = 1.0f;
const f32 o = 0.0f;
- static const u16 indices[4] = {0, 1, 2, 3};
+ static const u16 indices[6] = {0, 1, 2, 0, 2, 3};
video::S3DVertex vertices[4];
driver->setMaterial(m_materials[1]);
@@ -244,7 +254,7 @@ void Sky::render()
vertex.Pos.rotateXZBy(180);
}
}
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
}
@@ -270,7 +280,7 @@ void Sky::render()
// Switch from -Z (south) to +Z (north)
vertex.Pos.rotateXZBy(-180);
}
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
}
@@ -301,7 +311,7 @@ void Sky::render()
// Switch from -Z (south) to -X (west)
vertex.Pos.rotateXZBy(-90);
}
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
// Draw sun
@@ -337,7 +347,7 @@ void Sky::render()
// Switch from -Z (south) to +Z (north)
vertex.Pos.rotateXZBy(-180);
}
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
// Draw bottom far cloudy fog thing in front of sun, moon and stars
@@ -346,7 +356,7 @@ void Sky::render()
vertices[1] = video::S3DVertex( 1, -1.0, -1, 0, 1, 0, c, o, t);
vertices[2] = video::S3DVertex( 1, -1.0, 1, 0, 1, 0, c, o, o);
vertices[3] = video::S3DVertex(-1, -1.0, 1, 0, 1, 0, c, t, o);
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
}
}
@@ -590,7 +600,7 @@ void Sky::draw_sun(video::IVideoDriver *driver, float sunsize, const video::SCol
* wicked_time_of_day: current time of day, to know where should be the sun in the sky
*/
{
- static const u16 indices[4] = {0, 1, 2, 3};
+ static const u16 indices[] = {0, 1, 2, 0, 2, 3};
std::array<video::S3DVertex, 4> vertices;
if (!m_sun_texture) {
driver->setMaterial(m_materials[1]);
@@ -608,7 +618,7 @@ void Sky::draw_sun(video::IVideoDriver *driver, float sunsize, const video::SCol
for (int i = 0; i < 4; i++) {
draw_sky_body(vertices, -sunsizes[i], sunsizes[i], colors[i]);
place_sky_body(vertices, 90, wicked_time_of_day * 360 - 90);
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
} else {
driver->setMaterial(m_materials[3]);
@@ -620,7 +630,7 @@ void Sky::draw_sun(video::IVideoDriver *driver, float sunsize, const video::SCol
c = video::SColor(255, 255, 255, 255);
draw_sky_body(vertices, -d, d, c);
place_sky_body(vertices, 90, wicked_time_of_day * 360 - 90);
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
}
@@ -637,7 +647,7 @@ void Sky::draw_moon(video::IVideoDriver *driver, float moonsize, const video::SC
* the sky
*/
{
- static const u16 indices[4] = {0, 1, 2, 3};
+ static const u16 indices[] = {0, 1, 2, 0, 2, 3};
std::array<video::S3DVertex, 4> vertices;
if (!m_moon_texture) {
driver->setMaterial(m_materials[1]);
@@ -661,7 +671,7 @@ void Sky::draw_moon(video::IVideoDriver *driver, float moonsize, const video::SC
for (int i = 0; i < 4; i++) {
draw_sky_body(vertices, moonsizes_1[i], moonsizes_2[i], colors[i]);
place_sky_body(vertices, -90, wicked_time_of_day * 360 - 90);
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
} else {
driver->setMaterial(m_materials[4]);
@@ -673,13 +683,12 @@ void Sky::draw_moon(video::IVideoDriver *driver, float moonsize, const video::SC
c = video::SColor(255, 255, 255, 255);
draw_sky_body(vertices, -d, d, c);
place_sky_body(vertices, -90, wicked_time_of_day * 360 - 90);
- driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+ driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
}
}
void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day)
{
- driver->setMaterial(m_materials[1]);
// Tune values so that stars first appear just after the sun
// disappears over the horizon, and disappear just before the sun
// appears over the horizon.
@@ -687,87 +696,18 @@ void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day)
// to time 4000.
float tod = wicked_time_of_day < 0.5f ? wicked_time_of_day : (1.0f - wicked_time_of_day);
- float starbrightness = clamp((0.25f - fabsf(tod)) * 20.0f, 0.0f, 1.0f);
-
- float f = starbrightness;
- float d = (0.006 / 2) * m_star_params.scale;
-
- video::SColor starcolor = m_star_params.starcolor;
- starcolor.setAlpha(f * m_star_params.starcolor.getAlpha());
-
- // Stars are only drawn when not fully transparent
- if (m_star_params.starcolor.getAlpha() < 1)
+ float starbrightness = (0.25f - fabsf(tod)) * 20.0f;
+ m_star_color = m_star_params.starcolor;
+ m_star_color.a *= clamp(starbrightness, 0.0f, 1.0f);
+ if (m_star_color.a <= 0.0f) // Stars are only drawn when not fully transparent
return;
-#if ENABLE_GLES
- u16 *indices = new u16[m_star_params.count * 3];
- video::S3DVertex *vertices =
- new video::S3DVertex[m_star_params.count * 3];
- for (u32 i = 0; i < m_star_params.count; i++) {
- indices[i * 3 + 0] = i * 3 + 0;
- indices[i * 3 + 1] = i * 3 + 1;
- indices[i * 3 + 2] = i * 3 + 2;
- v3f r = m_stars[i];
- core::CMatrix4<f32> a;
- a.buildRotateFromTo(v3f(0, 1, 0), r);
- v3f p = v3f(-d, 1, -d);
- v3f p1 = v3f(d, 1, 0);
- v3f p2 = v3f(-d, 1, d);
- a.rotateVect(p);
- a.rotateVect(p1);
- a.rotateVect(p2);
- p.rotateXYBy(wicked_time_of_day * 360 - 90);
- p1.rotateXYBy(wicked_time_of_day * 360 - 90);
- p2.rotateXYBy(wicked_time_of_day * 360 - 90);
- vertices[i * 3 + 0].Pos = p;
- vertices[i * 3 + 0].Color = starcolor;
- vertices[i * 3 + 1].Pos = p1;
- vertices[i * 3 + 1].Color = starcolor;
- vertices[i * 3 + 2].Pos = p2;
- vertices[i * 3 + 2].Color = starcolor;
- }
- driver->drawIndexedTriangleList(vertices, m_star_params.count * 3,
- indices, m_star_params.count);
- delete[] indices;
- delete[] vertices;
-#else
- u16 *indices = new u16[m_star_params.count * 4];
- video::S3DVertex *vertices =
- new video::S3DVertex[m_star_params.count * 4];
- for (u32 i = 0; i < m_star_params.count; i++) {
- indices[i * 4 + 0] = i * 4 + 0;
- indices[i * 4 + 1] = i * 4 + 1;
- indices[i * 4 + 2] = i * 4 + 2;
- indices[i * 4 + 3] = i * 4 + 3;
- v3f r = m_stars[i];
- core::CMatrix4<f32> a;
- a.buildRotateFromTo(v3f(0, 1, 0), r);
- v3f p = v3f(-d, 1, -d);
- v3f p1 = v3f(d, 1, -d);
- v3f p2 = v3f(d, 1, d);
- v3f p3 = v3f(-d, 1, d);
- a.rotateVect(p);
- a.rotateVect(p1);
- a.rotateVect(p2);
- a.rotateVect(p3);
- p.rotateXYBy(wicked_time_of_day * 360 - 90);
- p1.rotateXYBy(wicked_time_of_day * 360 - 90);
- p2.rotateXYBy(wicked_time_of_day * 360 - 90);
- p3.rotateXYBy(wicked_time_of_day * 360 - 90);
- vertices[i * 4 + 0].Pos = p;
- vertices[i * 4 + 0].Color = starcolor;
- vertices[i * 4 + 1].Pos = p1;
- vertices[i * 4 + 1].Color = starcolor;
- vertices[i * 4 + 2].Pos = p2;
- vertices[i * 4 + 2].Color = starcolor;
- vertices[i * 4 + 3].Pos = p3;
- vertices[i * 4 + 3].Color = starcolor;
- }
- driver->drawVertexPrimitiveList(vertices, m_star_params.count * 4,
- indices, m_star_params.count, video::EVT_STANDARD,
- scene::EPT_QUADS, video::EIT_16BIT);
- delete[] indices;
- delete[] vertices;
-#endif
+ m_materials[0].DiffuseColor = m_materials[0].EmissiveColor = m_star_color.toSColor();
+ auto sky_rotation = core::matrix4().setRotationAxisRadians(2.0f * M_PI * (wicked_time_of_day - 0.25f), v3f(0.0f, 0.0f, 1.0f));
+ auto world_matrix = driver->getTransform(video::ETS_WORLD);
+ driver->setTransform(video::ETS_WORLD, world_matrix * sky_rotation);
+ driver->setMaterial(m_materials[0]);
+ driver->drawMeshBuffer(m_stars.get());
+ driver->setTransform(video::ETS_WORLD, world_matrix);
}
void Sky::draw_sky_body(std::array<video::S3DVertex, 4> &vertices, float pos_1, float pos_2, const video::SColor &c)
@@ -822,7 +762,7 @@ void Sky::setSunTexture(std::string sun_texture,
m_sun_texture = tsrc->getTextureForMesh(m_sun_params.texture);
if (m_sun_texture) {
- m_materials[3] = m_materials[0];
+ m_materials[3] = baseMaterial();
m_materials[3].setTexture(0, m_sun_texture);
m_materials[3].MaterialType = video::
EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -870,7 +810,7 @@ void Sky::setMoonTexture(std::string moon_texture,
m_moon_texture = tsrc->getTextureForMesh(m_moon_params.texture);
if (m_moon_texture) {
- m_materials[4] = m_materials[0];
+ m_materials[4] = baseMaterial();
m_materials[4].setTexture(0, m_moon_texture);
m_materials[4].MaterialType = video::
EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -892,19 +832,58 @@ void Sky::setStarCount(u16 star_count, bool force_update)
// Allow force updating star count at game init.
if (m_star_params.count != star_count || force_update) {
m_star_params.count = star_count;
- m_stars.clear();
- // Rebuild the stars surrounding the camera
- for (u16 i = 0; i < star_count; i++) {
- v3f star = v3f(
- myrand_range(-10000, 10000),
- myrand_range(-10000, 10000),
- myrand_range(-10000, 10000)
- );
-
- star.normalize();
- m_stars.emplace_back(star);
- }
+ m_seed = (u64)myrand() << 32 | myrand();
+ updateStars();
+ }
+}
+
+void Sky::updateStars()
+{
+ m_stars.reset(new scene::SMeshBuffer());
+ // Stupid IrrLicht doesn’t allow non-indexed rendering, and indexed quad
+ // rendering is slow due to lack of hardware support. So as indices are
+ // 16-bit and there are 4 vertices per star... the limit is 2^16/4 = 0x4000.
+ // That should be well enough actually.
+ if (m_star_params.count > 0x4000) {
+ warningstream << "Requested " << m_star_params.count << " stars but " << 0x4000 << " is the max\n";
+ m_star_params.count = 0x4000;
+ }
+ m_stars->Vertices.reallocate(4 * m_star_params.count);
+ m_stars->Indices.reallocate(6 * m_star_params.count);
+
+ video::SColor fallback_color = m_star_params.starcolor; // used on GLES 2 “without shaders”
+ PcgRandom rgen(m_seed);
+ float d = (0.006 / 2) * m_star_params.scale;
+ for (u16 i = 0; i < m_star_params.count; i++) {
+ v3f r = v3f(
+ rgen.range(-10000, 10000),
+ rgen.range(-10000, 10000),
+ rgen.range(-10000, 10000)
+ );
+ core::CMatrix4<f32> a;
+ a.buildRotateFromTo(v3f(0, 1, 0), r);
+ v3f p = v3f(-d, 1, -d);
+ v3f p1 = v3f(d, 1, -d);
+ v3f p2 = v3f(d, 1, d);
+ v3f p3 = v3f(-d, 1, d);
+ a.rotateVect(p);
+ a.rotateVect(p1);
+ a.rotateVect(p2);
+ a.rotateVect(p3);
+ m_stars->Vertices.push_back(video::S3DVertex(p, {}, fallback_color, {}));
+ m_stars->Vertices.push_back(video::S3DVertex(p1, {}, fallback_color, {}));
+ m_stars->Vertices.push_back(video::S3DVertex(p2, {}, fallback_color, {}));
+ m_stars->Vertices.push_back(video::S3DVertex(p3, {}, fallback_color, {}));
+ }
+ for (u16 i = 0; i < m_star_params.count; i++) {
+ m_stars->Indices.push_back(i * 4 + 0);
+ m_stars->Indices.push_back(i * 4 + 1);
+ m_stars->Indices.push_back(i * 4 + 2);
+ m_stars->Indices.push_back(i * 4 + 2);
+ m_stars->Indices.push_back(i * 4 + 3);
+ m_stars->Indices.push_back(i * 4 + 0);
}
+ m_stars->setHardwareMappingHint(scene::EHM_STATIC);
}
void Sky::setSkyColors(const SkyColor &sky_color)
@@ -936,7 +915,7 @@ void Sky::addTextureToSkybox(std::string texture, int material_id,
// Keep a list of texture names handy.
m_sky_params.textures.emplace_back(texture);
video::ITexture *result = tsrc->getTextureForMesh(texture);
- m_materials[material_id+5] = m_materials[0];
+ m_materials[material_id+5] = baseMaterial();
m_materials[material_id+5].setTexture(0, result);
m_materials[material_id+5].MaterialType = video::EMT_SOLID;
}