Skip to content

Commit 3077afc

Browse files
numberZerolhofhansl
authored andcommittedNov 26, 2020
Store stars in a single static mesh buffer
1 parent 89cc5bf commit 3077afc

File tree

2 files changed

+92
-115
lines changed

2 files changed

+92
-115
lines changed
 

‎src/client/sky.cpp

+86-113
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
Minetest
33
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4+
Copyright (C) 2020 numzero, Lobachevskiy Vitaliy <numzer0@yandex.ru>
45
56
This program is free software; you can redistribute it and/or modify
67
it under the terms of the GNU Lesser General Public License as published by
@@ -34,16 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3435
#include "config.h"
3536
using namespace irr::core;
3637

37-
Sky::Sky(s32 id, ITextureSource *tsrc) :
38-
scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
39-
RenderingEngine::get_scene_manager(), id)
40-
{
41-
setAutomaticCulling(scene::EAC_OFF);
42-
m_box.MaxEdge.set(0, 0, 0);
43-
m_box.MinEdge.set(0, 0, 0);
44-
45-
// Create material
46-
38+
static video::SMaterial baseMaterial() {
4739
video::SMaterial mat;
4840
mat.Lighting = false;
4941
#if ENABLE_GLES
@@ -56,14 +48,29 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
5648
mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
5749
mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
5850
mat.BackfaceCulling = false;
51+
return mat;
52+
};
53+
54+
Sky::Sky(s32 id, ITextureSource *tsrc) :
55+
scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
56+
RenderingEngine::get_scene_manager(), id)
57+
{
58+
setAutomaticCulling(scene::EAC_OFF);
59+
m_box.MaxEdge.set(0, 0, 0);
60+
m_box.MinEdge.set(0, 0, 0);
61+
62+
// Create materials
5963

60-
m_materials[0] = mat;
64+
m_materials[0] = baseMaterial();
65+
m_materials[0].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
66+
m_materials[0].Lighting = true;
67+
m_materials[0].ColorMaterial = video::ECM_NONE;
6168

62-
m_materials[1] = mat;
69+
m_materials[1] = baseMaterial();
6370
//m_materials[1].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
6471
m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
6572

66-
m_materials[2] = mat;
73+
m_materials[2] = baseMaterial();
6774
m_materials[2].setTexture(0, tsrc->getTextureForMesh("sunrisebg.png"));
6875
m_materials[2].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
6976
//m_materials[2].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
@@ -80,7 +87,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
8087
tsrc->getTexture(m_moon_params.tonemap) : NULL;
8188

8289
if (m_sun_texture) {
83-
m_materials[3] = mat;
90+
m_materials[3] = baseMaterial();
8491
m_materials[3].setTexture(0, m_sun_texture);
8592
m_materials[3].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
8693
// Disables texture filtering
@@ -92,7 +99,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
9299
m_materials[3].Lighting = true;
93100
}
94101
if (m_moon_texture) {
95-
m_materials[4] = mat;
102+
m_materials[4] = baseMaterial();
96103
m_materials[4].setTexture(0, m_moon_texture);
97104
m_materials[4].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
98105
// Disables texture filtering
@@ -105,7 +112,7 @@ Sky::Sky(s32 id, ITextureSource *tsrc) :
105112
}
106113

107114
for (int i = 5; i < 11; i++) {
108-
m_materials[i] = mat;
115+
m_materials[i] = baseMaterial();
109116
m_materials[i].Lighting = true;
110117
m_materials[i].MaterialType = video::EMT_SOLID;
111118
}
@@ -673,101 +680,32 @@ void Sky::draw_moon(video::IVideoDriver *driver, float moonsize, const video::SC
673680
c = video::SColor(255, 255, 255, 255);
674681
draw_sky_body(vertices, -d, d, c);
675682
place_sky_body(vertices, -90, wicked_time_of_day * 360 - 90);
676-
driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
683+
driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
677684
}
678685
}
679686

680687
void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day)
681688
{
682-
driver->setMaterial(m_materials[1]);
683689
// Tune values so that stars first appear just after the sun
684690
// disappears over the horizon, and disappear just before the sun
685691
// appears over the horizon.
686692
// Also tune so that stars are at full brightness from time 20000
687693
// to time 4000.
688694

689695
float tod = wicked_time_of_day < 0.5f ? wicked_time_of_day : (1.0f - wicked_time_of_day);
690-
float starbrightness = clamp((0.25f - fabsf(tod)) * 20.0f, 0.0f, 1.0f);
691-
692-
float f = starbrightness;
693-
float d = (0.006 / 2) * m_star_params.scale;
694-
695-
video::SColor starcolor = m_star_params.starcolor;
696-
starcolor.setAlpha(f * m_star_params.starcolor.getAlpha());
697-
698-
// Stars are only drawn when not fully transparent
699-
if (m_star_params.starcolor.getAlpha() < 1)
696+
float starbrightness = (0.25f - fabsf(tod)) * 20.0f;
697+
int alpha = clamp<int>(starbrightness * m_star_params.starcolor.getAlpha(), 0, 255);
698+
if (!alpha) // Stars are only drawn when not fully transparent
700699
return;
701-
#if ENABLE_GLES
702-
u16 *indices = new u16[m_star_params.count * 3];
703-
video::S3DVertex *vertices =
704-
new video::S3DVertex[m_star_params.count * 3];
705-
for (u32 i = 0; i < m_star_params.count; i++) {
706-
indices[i * 3 + 0] = i * 3 + 0;
707-
indices[i * 3 + 1] = i * 3 + 1;
708-
indices[i * 3 + 2] = i * 3 + 2;
709-
v3f r = m_stars[i];
710-
core::CMatrix4<f32> a;
711-
a.buildRotateFromTo(v3f(0, 1, 0), r);
712-
v3f p = v3f(-d, 1, -d);
713-
v3f p1 = v3f(d, 1, 0);
714-
v3f p2 = v3f(-d, 1, d);
715-
a.rotateVect(p);
716-
a.rotateVect(p1);
717-
a.rotateVect(p2);
718-
p.rotateXYBy(wicked_time_of_day * 360 - 90);
719-
p1.rotateXYBy(wicked_time_of_day * 360 - 90);
720-
p2.rotateXYBy(wicked_time_of_day * 360 - 90);
721-
vertices[i * 3 + 0].Pos = p;
722-
vertices[i * 3 + 0].Color = starcolor;
723-
vertices[i * 3 + 1].Pos = p1;
724-
vertices[i * 3 + 1].Color = starcolor;
725-
vertices[i * 3 + 2].Pos = p2;
726-
vertices[i * 3 + 2].Color = starcolor;
727-
}
728-
driver->drawIndexedTriangleList(vertices, m_star_params.count * 3,
729-
indices, m_star_params.count);
730-
delete[] indices;
731-
delete[] vertices;
732-
#else
733-
u16 *indices = new u16[m_star_params.count * 4];
734-
video::S3DVertex *vertices =
735-
new video::S3DVertex[m_star_params.count * 4];
736-
for (u32 i = 0; i < m_star_params.count; i++) {
737-
indices[i * 4 + 0] = i * 4 + 0;
738-
indices[i * 4 + 1] = i * 4 + 1;
739-
indices[i * 4 + 2] = i * 4 + 2;
740-
indices[i * 4 + 3] = i * 4 + 3;
741-
v3f r = m_stars[i];
742-
core::CMatrix4<f32> a;
743-
a.buildRotateFromTo(v3f(0, 1, 0), r);
744-
v3f p = v3f(-d, 1, -d);
745-
v3f p1 = v3f(d, 1, -d);
746-
v3f p2 = v3f(d, 1, d);
747-
v3f p3 = v3f(-d, 1, d);
748-
a.rotateVect(p);
749-
a.rotateVect(p1);
750-
a.rotateVect(p2);
751-
a.rotateVect(p3);
752-
p.rotateXYBy(wicked_time_of_day * 360 - 90);
753-
p1.rotateXYBy(wicked_time_of_day * 360 - 90);
754-
p2.rotateXYBy(wicked_time_of_day * 360 - 90);
755-
p3.rotateXYBy(wicked_time_of_day * 360 - 90);
756-
vertices[i * 4 + 0].Pos = p;
757-
vertices[i * 4 + 0].Color = starcolor;
758-
vertices[i * 4 + 1].Pos = p1;
759-
vertices[i * 4 + 1].Color = starcolor;
760-
vertices[i * 4 + 2].Pos = p2;
761-
vertices[i * 4 + 2].Color = starcolor;
762-
vertices[i * 4 + 3].Pos = p3;
763-
vertices[i * 4 + 3].Color = starcolor;
764-
}
765-
driver->drawVertexPrimitiveList(vertices, m_star_params.count * 4,
766-
indices, m_star_params.count, video::EVT_STANDARD,
767-
scene::EPT_QUADS, video::EIT_16BIT);
768-
delete[] indices;
769-
delete[] vertices;
770-
#endif
700+
701+
m_materials[0].DiffuseColor = video::SColor(alpha, 0, 0, 0);
702+
m_materials[0].EmissiveColor = m_star_params.starcolor;
703+
auto sky_rotation = core::matrix4().setRotationAxisRadians(2.0f * M_PI * (wicked_time_of_day - 0.25f), v3f(0.0f, 0.0f, 1.0f));
704+
auto world_matrix = driver->getTransform(video::ETS_WORLD);
705+
driver->setTransform(video::ETS_WORLD, world_matrix * sky_rotation);
706+
driver->setMaterial(m_materials[0]);
707+
driver->drawMeshBuffer(m_stars.get());
708+
driver->setTransform(video::ETS_WORLD, world_matrix);
771709
}
772710

773711
void Sky::draw_sky_body(std::array<video::S3DVertex, 4> &vertices, float pos_1, float pos_2, const video::SColor &c)
@@ -822,7 +760,7 @@ void Sky::setSunTexture(std::string sun_texture,
822760
m_sun_texture = tsrc->getTextureForMesh(m_sun_params.texture);
823761

824762
if (m_sun_texture) {
825-
m_materials[3] = m_materials[0];
763+
m_materials[3] = baseMaterial();
826764
m_materials[3].setTexture(0, m_sun_texture);
827765
m_materials[3].MaterialType = video::
828766
EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -870,7 +808,7 @@ void Sky::setMoonTexture(std::string moon_texture,
870808
m_moon_texture = tsrc->getTextureForMesh(m_moon_params.texture);
871809

872810
if (m_moon_texture) {
873-
m_materials[4] = m_materials[0];
811+
m_materials[4] = baseMaterial();
874812
m_materials[4].setTexture(0, m_moon_texture);
875813
m_materials[4].MaterialType = video::
876814
EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -892,19 +830,54 @@ void Sky::setStarCount(u16 star_count, bool force_update)
892830
// Allow force updating star count at game init.
893831
if (m_star_params.count != star_count || force_update) {
894832
m_star_params.count = star_count;
895-
m_stars.clear();
896-
// Rebuild the stars surrounding the camera
897-
for (u16 i = 0; i < star_count; i++) {
898-
v3f star = v3f(
899-
myrand_range(-10000, 10000),
900-
myrand_range(-10000, 10000),
901-
myrand_range(-10000, 10000)
902-
);
903-
904-
star.normalize();
905-
m_stars.emplace_back(star);
906-
}
833+
updateStars();
834+
}
835+
}
836+
837+
void Sky::updateStars() {
838+
m_stars.reset(new scene::SMeshBuffer());
839+
// Stupid IrrLicht doesn’t allow non-indexed rendering, and indexed quad
840+
// rendering is slow due to lack of hardware support. So as indices are
841+
// 16-bit and there are 4 vertices per star... the limit is 2^16/4 = 0x4000.
842+
// That should be well enough actually.
843+
if (m_star_params.count > 0x4000) {
844+
warningstream << "Requested " << m_star_params.count << " stars but " << 0x4000 << " is the max\n";
845+
m_star_params.count = 0x4000;
846+
}
847+
m_stars->Vertices.reallocate(4 * m_star_params.count);
848+
m_stars->Indices.reallocate(6 * m_star_params.count);
849+
850+
float d = (0.006 / 2) * m_star_params.scale;
851+
for (u16 i = 0; i < m_star_params.count; i++) {
852+
v3f r = v3f(
853+
myrand_range(-10000, 10000),
854+
myrand_range(-10000, 10000),
855+
myrand_range(-10000, 10000)
856+
);
857+
core::CMatrix4<f32> a;
858+
a.buildRotateFromTo(v3f(0, 1, 0), r);
859+
v3f p = v3f(-d, 1, -d);
860+
v3f p1 = v3f(d, 1, -d);
861+
v3f p2 = v3f(d, 1, d);
862+
v3f p3 = v3f(-d, 1, d);
863+
a.rotateVect(p);
864+
a.rotateVect(p1);
865+
a.rotateVect(p2);
866+
a.rotateVect(p3);
867+
m_stars->Vertices.push_back(video::S3DVertex(p, {}, {}, {}));
868+
m_stars->Vertices.push_back(video::S3DVertex(p1, {}, {}, {}));
869+
m_stars->Vertices.push_back(video::S3DVertex(p2, {}, {}, {}));
870+
m_stars->Vertices.push_back(video::S3DVertex(p3, {}, {}, {}));
871+
}
872+
for (u16 i = 0; i < m_star_params.count; i++) {
873+
m_stars->Indices.push_back(i * 4 + 0);
874+
m_stars->Indices.push_back(i * 4 + 1);
875+
m_stars->Indices.push_back(i * 4 + 2);
876+
m_stars->Indices.push_back(i * 4 + 2);
877+
m_stars->Indices.push_back(i * 4 + 3);
878+
m_stars->Indices.push_back(i * 4 + 0);
907879
}
880+
m_stars->setHardwareMappingHint(scene::EHM_STATIC);
908881
}
909882

910883
void Sky::setSkyColors(const SkyColor &sky_color)
@@ -936,7 +909,7 @@ void Sky::addTextureToSkybox(std::string texture, int material_id,
936909
// Keep a list of texture names handy.
937910
m_sky_params.textures.emplace_back(texture);
938911
video::ITexture *result = tsrc->getTextureForMesh(texture);
939-
m_materials[material_id+5] = m_materials[0];
912+
m_materials[material_id+5] = baseMaterial();
940913
m_materials[material_id+5].setTexture(0, result);
941914
m_materials[material_id+5].MaterialType = video::EMT_SOLID;
942915
}

‎src/client/sky.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2121
#include <array>
2222
#include "camera.h"
2323
#include "irrlichttypes_extrabloated.h"
24+
#include "irr_ptr.h"
2425
#include "skyparams.h"
2526

2627
#pragma once
@@ -77,7 +78,7 @@ class Sky : public scene::ISceneNode
7778
void setStarsVisible(bool stars_visible) { m_star_params.visible = stars_visible; }
7879
void setStarCount(u16 star_count, bool force_update);
7980
void setStarColor(video::SColor star_color) { m_star_params.starcolor = star_color; }
80-
void setStarScale(f32 star_scale) { m_star_params.scale = star_scale; }
81+
void setStarScale(f32 star_scale) { m_star_params.scale = star_scale; updateStars(); }
8182

8283
bool getCloudsVisible() const { return m_clouds_visible && m_clouds_enabled; }
8384
const video::SColorf &getCloudColor() const { return m_cloudcolor_f; }
@@ -178,13 +179,16 @@ class Sky : public scene::ISceneNode
178179

179180
bool m_default_tint = true;
180181

181-
std::vector<v3f> m_stars;
182+
irr_ptr<scene::SMeshBuffer> m_stars;
182183

183184
video::ITexture *m_sun_texture;
184185
video::ITexture *m_moon_texture;
185186
video::ITexture *m_sun_tonemap;
186187
video::ITexture *m_moon_tonemap;
187188

189+
void updateStars();
190+
void updateStarsColor(video::SColor color);
191+
188192
void draw_sun(video::IVideoDriver *driver, float sunsize, const video::SColor &suncolor,
189193
const video::SColor &suncolor2, float wicked_time_of_day);
190194
void draw_moon(video::IVideoDriver *driver, float moonsize, const video::SColor &mooncolor,

0 commit comments

Comments
 (0)
Please sign in to comment.