finally frame buffer rendering is working

This commit is contained in:
Vladislav Khorev 2025-12-20 23:08:26 +03:00
parent e690d0f8e2
commit 29834d528a
20 changed files with 601 additions and 164 deletions

View File

@ -446,6 +446,8 @@ add_executable(space-game001
Perlin.h Perlin.h
StoneObject.cpp StoneObject.cpp
StoneObject.h StoneObject.h
FrameBuffer.cpp
FrameBuffer.h
) )
# Установка проекта по умолчанию для Visual Studio # Установка проекта по умолчанию для Visual Studio

49
FrameBuffer.cpp Normal file
View File

@ -0,0 +1,49 @@
#include "FrameBuffer.h"
#include <iostream>
#include "Environment.h"
namespace ZL {
FrameBuffer::FrameBuffer(int w, int h) : width(w), height(h) {
// 1. Ñîçäàåì FBO
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// 2. Ñîçäàåì òåêñòóðó, êóäà áóäåì "ôîòîãðàôèðîâàòü"
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
// Óñòàíàâëèâàåì ïàðàìåòðû òåêñòóðû
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 3. Ïðèâÿçûâàåì òåêñòóðó ê FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
// Ïðîâåðêà ãîòîâíîñòè
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "Error: Framebuffer is not complete!" << std::endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
FrameBuffer::~FrameBuffer() {
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &textureID);
}
void FrameBuffer::Bind() {
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, width, height); // Âàæíî: óñòàíàâëèâàåì âüþïîðò ïîä ðàçìåð òåêñòóðû
}
void FrameBuffer::Unbind() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Çäåñü æåëàòåëüíî âîçâðàùàòü âüþïîðò ê ðàçìåðàì ýêðàíà,
// íàïðèìåð, ÷åðåç Environment::width/height
glViewport(0, 0, Environment::width, Environment::height);
}
} // namespace ZL

29
FrameBuffer.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include "OpenGlExtensions.h"
#include <memory>
namespace ZL {
class FrameBuffer {
private:
GLuint fbo = 0;
GLuint textureID = 0;
int width, height;
public:
FrameBuffer(int w, int h);
~FrameBuffer();
// Çàïðåùàåì êîïèðîâàíèå, êàê â VBOHolder
FrameBuffer(const FrameBuffer&) = delete;
FrameBuffer& operator=(const FrameBuffer&) = delete;
void Bind(); // Íà÷àòü ðåíäåð â ýòîò áóôåð
void Unbind(); // Âåðíóòüñÿ ê îáû÷íîìó ðåíäåðó â ýêðàí
GLuint getTextureID() const { return textureID; }
int getWidth() const { return width; }
int getHeight() const { return height; }
};
} // namespace ZL

View File

@ -137,6 +137,7 @@ namespace ZL
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env.vertex", "./shaders/env_web.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env.vertex", "./shaders/env_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/defaultAtmosphere.vertex", "./shaders/defaultAtmosphere.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/defaultAtmosphere.vertex", "./shaders/defaultAtmosphere.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColorPlanet", "./shaders/defaultColorPlanet.vertex", "./shaders/defaultColorPlanet_web.fragment", CONST_ZIP_FILE);
#else #else
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_desktop.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_desktop.fragment", CONST_ZIP_FILE);
@ -144,7 +145,8 @@ namespace ZL
renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env_sky.vertex", "./shaders/env_sky_desktop.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env_sky.vertex", "./shaders/env_sky_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/defaultAtmosphere.vertex", "./shaders/defaultAtmosphere.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/defaultAtmosphere.vertex", "./shaders/defaultAtmosphere.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColor2", "./shaders/defaultColor_fog2.vertex", "./shaders/defaultColor_fog2_desktop.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("defaultColor2", "./shaders/defaultColor_fog2.vertex", "./shaders/defaultColor_fog2_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColorStones", "./shaders/defaultColor_fog_stones.vertex", "./shaders/defaultColor_fog_stones_desktop.fragment", CONST_ZIP_FILE);
//renderer.shaderManager.AddShaderFromFiles("defaultColorBake", "./shaders/defaultColor_fog_bake.vertex", "./shaders/defaultColor_fog_stones_bake.fragment", CONST_ZIP_FILE);
#endif #endif
cubemapTexture = std::make_shared<Texture>( cubemapTexture = std::make_shared<Texture>(
@ -181,8 +183,8 @@ namespace ZL
for (int i = 0; i < boxCoordsArr.size(); i++) for (int i = 0; i < boxCoordsArr.size(); i++)
{ {
//boxRenderArr[i].AssignFrom(boxBase); boxRenderArr[i].AssignFrom(boxBase);
boxRenderArr[i].data = CreateBaseConvexPolyhedron(1999); //boxRenderArr[i].data = CreateBaseConvexPolyhedron(1999);
boxRenderArr[i].RefreshVBO(); boxRenderArr[i].RefreshVBO();
} }
@ -357,8 +359,8 @@ namespace ZL
renderer.TranslateMatrix(boxCoordsArr[i].pos); renderer.TranslateMatrix(boxCoordsArr[i].pos);
renderer.RotateMatrix(boxCoordsArr[i].m); renderer.RotateMatrix(boxCoordsArr[i].m);
//glBindTexture(GL_TEXTURE_2D, boxTexture->getTexID()); glBindTexture(GL_TEXTURE_2D, boxTexture->getTexID());
glBindTexture(GL_TEXTURE_2D, rockTexture->getTexID()); //glBindTexture(GL_TEXTURE_2D, rockTexture->getTexID());
renderer.DrawVertexRenderStruct(boxRenderArr[i]); renderer.DrawVertexRenderStruct(boxRenderArr[i]);
renderer.PopMatrix(); renderer.PopMatrix();
@ -624,6 +626,22 @@ namespace ZL
} }
else if (event.type == SDL_KEYUP) else if (event.type == SDL_KEYUP)
{ {
if (event.key.keysym.sym == SDLK_a)
{
planetObject.x += 1;
}
if (event.key.keysym.sym == SDLK_s)
{
planetObject.x -= 1;
}
if (event.key.keysym.sym == SDLK_q)
{
planetObject.y += 1;
}
if (event.key.keysym.sym == SDLK_w)
{
planetObject.y -= 1;
}
if (event.key.keysym.sym == SDLK_i) if (event.key.keysym.sym == SDLK_i)
{ {
Environment::shipVelocity += 500.f; Environment::shipVelocity += 500.f;

View File

@ -327,10 +327,16 @@ namespace ZL {
// Ñòàíäàðòíûå UV-êîîðäèíàòû äëÿ ïîêðûòèÿ îäíîãî òðåóãîëüíèêà // Ñòàíäàðòíûå UV-êîîðäèíàòû äëÿ ïîêðûòèÿ îäíîãî òðåóãîëüíèêà
// Ïîêðûâàåò òåêñòóðîé âñþ ãðàíü. // Ïîêðûâàåò òåêñòóðîé âñþ ãðàíü.
const std::array<Vector2f, 3> triangleUVs = { const std::array<Vector2f, 3> triangleUVs = {
Vector2f(0.5f, 1.0f),
Vector2f(0.0f, 1.0f - sqrt(3)*0.5),
Vector2f(1.0f, 1.0f - sqrt(3) * 0.5),
};
/*const std::array<Vector2f, 3> triangleUVs2 = {
Vector2f(0.0f, 0.0f), Vector2f(0.0f, 0.0f),
Vector2f(1.0f, 0.0f), Vector2f(1.0f, 0.0f),
Vector2f(0.0f, 1.0f) Vector2f(0.0f, 1.0f)
}; };*/
result.VertexIDs.reserve(geometry.size() * 3); // Çàïîëíÿåì ID çäåñü result.VertexIDs.reserve(geometry.size() * 3); // Çàïîëíÿåì ID çäåñü
for (const auto& t : geometry) { for (const auto& t : geometry) {
@ -341,6 +347,7 @@ namespace ZL {
// Çàïîëíÿåì NormalData (íîðìàëü = íîðìàëèçîâàííàÿ ïîçèöèÿ íà ñôåðå) // Çàïîëíÿåì NormalData (íîðìàëü = íîðìàëèçîâàííàÿ ïîçèöèÿ íà ñôåðå)
result.vertexData.NormalData.push_back(t.data[i].normalized()); result.vertexData.NormalData.push_back(t.data[i].normalized());
result.vertexData.TexCoordData.push_back(triangleUVs[i]); result.vertexData.TexCoordData.push_back(triangleUVs[i]);
//result.vertexData.TexCoord2Data.push_back(triangleUVs2[i]);
// Çàïîëíÿåì VertexIDs // Çàïîëíÿåì VertexIDs
result.VertexIDs.push_back(t.ids[i]); result.VertexIDs.push_back(t.ids[i]);

View File

@ -16,7 +16,8 @@ namespace ZL {
VertexID generateEdgeID(const VertexID& id1, const VertexID& id2); VertexID generateEdgeID(const VertexID& id1, const VertexID& id2);
constexpr static int MAX_LOD_LEVELS = 6; //constexpr static int MAX_LOD_LEVELS = 6;
constexpr static int MAX_LOD_LEVELS = 1;
struct Triangle struct Triangle
{ {

View File

@ -23,12 +23,25 @@ namespace ZL {
planetRenderStruct.data = planetData.getLodLevel(lodIndex).vertexData; planetRenderStruct.data = planetData.getLodLevel(lodIndex).vertexData;
planetRenderStruct.RefreshVBO(); planetRenderStruct.RefreshVBO();
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", "")); planetRenderStructCut.data = planetData.getLodLevel(lodIndex).vertexData;
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", "")); planetRenderStructCut.data.PositionData.resize(3);
planetRenderStructCut.RefreshVBO();
//sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", ""));
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sandx.png", ""));
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rockx.png", ""));
// Атмосфера // Атмосфера
planetAtmosphereRenderStruct.data = planetData.getAtmosphereLod().vertexData; planetAtmosphereRenderStruct.data = planetData.getAtmosphereLod().vertexData;
planetAtmosphereRenderStruct.RefreshVBO(); planetAtmosphereRenderStruct.RefreshVBO();
planetStones = CreateStoneGroupData(777, planetData.getLodLevel(lodIndex));
planetStones.inflate({ 0/*,1,2,3,4,5,6,7*/ });
planetStonesRenderStruct.AssignFrom(planetStones.mesh);
planetStonesRenderStruct.RefreshVBO();
} }
void PlanetObject::prepareDrawData() { void PlanetObject::prepareDrawData() {
@ -37,81 +50,124 @@ namespace ZL {
} }
void PlanetObject::update(float deltaTimeMs) { void PlanetObject::update(float deltaTimeMs) {
// Получаем видимые треугольники, передавая позицию корабля // 1. Получаем базовые треугольники под камерой
auto lr = planetData.getTrianglesUnderCamera(Environment::shipPosition); auto lr = planetData.getTrianglesUnderCamera(Environment::shipPosition);
int currentLod = planetData.getCurrentLodIndex(); int currentLod = planetData.getCurrentLodIndex();
const auto& fullMesh = planetData.getLodLevel(currentLod).vertexData;
planetRenderYellowStruct.data.PositionData.clear(); // Временный вектор для сбора новых индексов
planetRenderYellowStruct.data.TexCoordData.clear(); std::vector<int> newIndices;
std::set<int> used;
triangleIndicesToDraw.clear();
std::set<int> usedYellow;
// Рекурсивно (или итеративно, как у тебя) собираем индексы видимых зон
for (int i : lr) { for (int i : lr) {
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[i * 3]); if (used.insert(i).second) newIndices.push_back(i);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[i * 3 + 1]);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[i * 3 + 2]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[i * 3]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[i * 3 + 1]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[i * 3 + 2]);
usedYellow.insert(i);
triangleIndicesToDraw.push_back(i);
}
for (int i : lr) {
auto neighbors = planetData.findNeighbors(i, currentLod); auto neighbors = planetData.findNeighbors(i, currentLod);
for (int n : neighbors) { for (int n : neighbors) {
if (usedYellow.count(n) == 0) { if (used.insert(n).second) newIndices.push_back(n);
usedYellow.insert(n);
triangleIndicesToDraw.push_back(n);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[n * 3]);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[n * 3 + 1]);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[n * 3 + 2]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[n * 3]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[n * 3 + 1]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[n * 3 + 2]);
}
auto neighbors2 = planetData.findNeighbors(n, currentLod);
auto neighbors2 = planetData.findNeighbors(n, currentLod);
for (int n2 : neighbors2) { for (int n2 : neighbors2) {
if (usedYellow.count(n2) == 0) { if (used.insert(n2).second) newIndices.push_back(n2);
usedYellow.insert(n2);
triangleIndicesToDraw.push_back(n2);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[n2 * 3]);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[n2 * 3 + 1]);
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[n2 * 3 + 2]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[n2 * 3]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[n2 * 3 + 1]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[n2 * 3 + 2]);
}
} }
} }
} }
planetRenderYellowStruct.RefreshVBO();
planetStonesRenderStruct.data = CreateConvexPolyhedron(777, planetData.getLodLevel(5), triangleIndicesToDraw); // 2. Сортируем новый список, чтобы порядок не влиял на сравнение
planetStonesRenderStruct.RefreshVBO(); std::sort(newIndices.begin(), newIndices.end());
// 3. Сравниваем с тем, что было нарисовано в прошлый раз
if (newIndices != triangleIndicesToDraw) {
// Обновляем список индексов (используем move для эффективности)
triangleIndicesToDraw = std::move(newIndices);
// --- ОБНОВЛЯЕМ ЖЕЛТУЮ ЗОНУ (только когда изменился состав треугольников) ---
const auto& fullMesh = planetData.getLodLevel(currentLod).vertexData;
planetRenderYellowStruct.data.PositionData.clear();
planetRenderYellowStruct.data.TexCoordData.clear();
for (int i : triangleIndicesToDraw) {
// Копируем геометрию для подсветки
for (int j = 0; j < 3; ++j) {
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[i * 3 + j]);
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[i * 3 + j]);
}
}
planetRenderYellowStruct.RefreshVBO();
// --- ОБНОВЛЯЕМ КАМНИ (через новую структуру StoneGroup) ---
//planetStones.inflate(triangleIndicesToDraw);
// Используем AssignFrom, он внутри сам вызывает RefreshVBO
//planetStonesRenderStruct.AssignFrom(planetStones.mesh);
}
} }
void PlanetObject::bakeStoneTexture(Renderer& renderer) {
void PlanetObject::draw(Renderer& renderer) { // 1. Создаем FB (размер 512x512 для четкости)
prepareDrawData();
//-------------------------- glViewport(0, 0, 1024, 1024);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawPlanet(renderer); /*
//drawYellowZone(renderer); static const std::string stoneShader = "defaultColor2";
drawStones(renderer); renderer.shaderManager.PushShader(stoneShader);
drawAtmosphere(renderer); static const std::string vPositionName = "vPosition";
} static const std::string vColorName = "vColor";
static const std::string vNormalName = "vNormal";
static const std::string vTexCoordName = "vTexCoord";
//static const std::string vTexCoord3Name = "vTexCoord3";
static const std::string textureUniformName = "Texture";
void PlanetObject::drawPlanet(Renderer& renderer) renderer.EnableVertexAttribArray(vPositionName);
{ renderer.EnableVertexAttribArray(vColorName);
static const std::string defaultShaderName = "defaultColor"; renderer.EnableVertexAttribArray(vNormalName);
renderer.EnableVertexAttribArray(vTexCoordName);
// 2. Очищаем (черный фон - это "нет камня")
glClearColor(0.0f, 0.5f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 3. Настраиваем камеру (Ортографическая проекция над треугольником)
// Смотрим на плоскость, где лежит эталонный треугольник
renderer.PushProjectionMatrix(0.666667f, 1.777779f, 2000, 200000);
renderer.PushMatrix();
renderer.LoadIdentity();
renderer.TranslateMatrix({ 0, 0, -45000.0f }); // Отодвигаемся, чтобы видеть камни
// 4. Рендерим камни
// Берем семена и параметры из первого треугольника (индекс 0)
// Используем упрощенный вызов отрисовки геометрии камней
// Рисуем меш камней для ОДНОГО эталонного треугольника
// Здесь используем уже созданную нами функцию inflate для индекса 0
planetStones.inflate({ 0 });
VertexRenderStruct tempStoneRender;
tempStoneRender.AssignFrom(planetStones.mesh);
renderer.DrawVertexRenderStruct(tempStoneRender);
renderer.PopMatrix();
renderer.PopProjectionMatrix();
//stoneMapFB->Unbind();
renderer.DisableVertexAttribArray(vPositionName);
renderer.DisableVertexAttribArray(vColorName);
renderer.DisableVertexAttribArray(vNormalName);
renderer.DisableVertexAttribArray(vTexCoordName);
renderer.shaderManager.PopShader();
// Восстанавливаем вьюпорт под экран
glViewport(0, 0, Environment::width, Environment::height);*/
//static const std::string defaultShaderName = "defaultColor";
static const std::string defaultShaderName2 = "defaultColor2"; static const std::string defaultShaderName2 = "defaultColor2";
static const std::string vPositionName = "vPosition"; static const std::string vPositionName = "vPosition";
static const std::string vColorName = "vColor"; static const std::string vColorName = "vColor";
@ -120,7 +176,10 @@ namespace ZL {
//static const std::string vTexCoord3Name = "vTexCoord3"; //static const std::string vTexCoord3Name = "vTexCoord3";
static const std::string textureUniformName = "Texture"; static const std::string textureUniformName = "Texture";
renderer.shaderManager.PushShader(defaultShaderName); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderer.shaderManager.PushShader(defaultShaderName2);
renderer.RenderUniform1i(textureUniformName, 0); renderer.RenderUniform1i(textureUniformName, 0);
renderer.EnableVertexAttribArray(vPositionName); renderer.EnableVertexAttribArray(vPositionName);
renderer.EnableVertexAttribArray(vColorName); renderer.EnableVertexAttribArray(vColorName);
@ -133,6 +192,166 @@ namespace ZL {
const float currentZNear = zRange.first; const float currentZNear = zRange.first;
const float currentZFar = zRange.second; const float currentZFar = zRange.second;
// 2. Применяем динамическую матрицу проекции
/*renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
1.0,
currentZNear, currentZFar);*/
renderer.PushProjectionMatrix(
-PlanetData::PLANET_RADIUS*sqrt(2)*(1-0/100.f)*0.5,
PlanetData::PLANET_RADIUS * sqrt(2) * (1 - 0 / 100.f) * 0.5,
-PlanetData::PLANET_RADIUS * sqrt(2) * (1 - 0 / 100.f) * 0.5,
PlanetData::PLANET_RADIUS * sqrt(2) * (1 - 0 / 100.f) * 0.5,
currentZNear, currentZFar);
renderer.PushMatrix();
renderer.LoadIdentity();
//renderer.RotateMatrix(Environment::inverseShipMatrix);
renderer.TranslateMatrix(Vector3f{ 0,0,-45000 });
Vector4f q1 = QuatFromRotateAroundX(-M_PI * 45.0 / 180.0);
Vector4f q2 = QuatFromRotateAroundY(M_PI * 45.0 / 180.0);
//Vector4f q3 = {-cos(0.5*M_PI * x / 180.0), -cos(0.5 * M_PI * x / 180.0), -cos(0.5 * M_PI * x / 180.0),sin(0.5 * M_PI * x / 180.0) };
Matrix3f r1 = QuatToMatrix(q1);
Matrix3f r2 = QuatToMatrix(q2);
//Matrix3f r3 = QuatToMatrix(q3);
Matrix3f invr = InverseMatrix( MultMatrixMatrix(r2, r1));
renderer.RotateMatrix(invr);
const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix();
Vector3f lightDir_World = Vector3f(1.0f, 0.0f, -1.0f).normalized();
// В OpenGL/шейдерах удобнее работать с вектором, указывающим ОТ источника к поверхности.
Vector3f lightDirection_World = -lightDir_World; // Вектор, направленный от источника
Vector3f lightDirection_View;
lightDirection_View.v[0] = viewMatrix.m[0] * lightDirection_World.v[0] + viewMatrix.m[4] * lightDirection_World.v[1] + viewMatrix.m[8] * lightDirection_World.v[2];
lightDirection_View.v[1] = viewMatrix.m[1] * lightDirection_World.v[0] + viewMatrix.m[5] * lightDirection_World.v[1] + viewMatrix.m[9] * lightDirection_World.v[2];
lightDirection_View.v[2] = viewMatrix.m[2] * lightDirection_World.v[0] + viewMatrix.m[6] * lightDirection_World.v[1] + viewMatrix.m[10] * lightDirection_World.v[2];
lightDirection_View = lightDirection_View.normalized(); // Нормализуем на всякий случай
// Установка uniform-переменной
// Предполагается, что RenderUniform3fv определена в Renderer.h
/*
renderer.RenderUniform3fv("uLightDirection", &lightDirection_View.v[0]);
renderer.RenderUniformMatrix4fv("ModelViewMatrix", false, &viewMatrix.m[0]);
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
renderer.RenderUniform1f("uCurrentZFar", currentZFar);
Vector3f color2 = { 1.0, 1.0, 1.0 };
renderer.RenderUniform3fv("uColor", &color2.v[0]);*/
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID());
//planetRenderStructCut.AssignFrom(planetRenderStruct.data);
//planetRenderStructCut.data.PositionData.resize(3);
//planetRenderStructCut.RefreshVBO();
renderer.DrawVertexRenderStruct(planetRenderStructCut);
//planetStones.inflate({0/*,1,2,3,4,5,6,7*/});
//planetStonesRenderStruct.AssignFrom(planetStones.mesh);
//planetStonesRenderStruct.RefreshVBO();
glClear(GL_DEPTH_BUFFER_BIT);
if (planetStonesRenderStruct.data.PositionData.size() > 0)
{
//glBindTexture(GL_TEXTURE_2D, fb->getTextureID());
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
renderer.DrawVertexRenderStruct(planetStonesRenderStruct);
//glDisable(GL_BLEND);
CheckGlError();
}
renderer.PopMatrix();
renderer.PopProjectionMatrix();
//renderer.DisableVertexAttribArray(vTexCoord3Name);
renderer.DisableVertexAttribArray(vTexCoordName);
renderer.DisableVertexAttribArray(vNormalName);
renderer.DisableVertexAttribArray(vColorName);
renderer.DisableVertexAttribArray(vPositionName);
renderer.shaderManager.PopShader();
CheckGlError();
//glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
void PlanetObject::draw(Renderer& renderer) {
prepareDrawData();
{
if (stoneMapFB == nullptr)
{
stoneMapFB = std::make_unique<FrameBuffer>(1024, 1024);
}
stoneMapFB->Bind();
bakeStoneTexture(renderer);
stoneMapFB->Unbind();
}
//bakeStoneTexture(renderer);
glViewport(0, 0, Environment::width, Environment::height);
//--------------------------
drawPlanet(renderer);
//drawYellowZone(renderer);
//drawStones(renderer);
//drawAtmosphere(renderer);
}
void PlanetObject::drawPlanet(Renderer& renderer)
{
static const std::string defaultShaderName = "defaultColorStones";
static const std::string vPositionName = "vPosition";
static const std::string vColorName = "vColor";
static const std::string vNormalName = "vNormal";
static const std::string vTexCoordName = "vTexCoord";
static const std::string vTexCoord2Name = "vTexCoord2";
//static const std::string vTexCoord3Name = "vTexCoord3";
static const std::string textureUniformName = "Texture";
renderer.shaderManager.PushShader(defaultShaderName);
renderer.EnableVertexAttribArray(vPositionName);
renderer.EnableVertexAttribArray(vColorName);
renderer.EnableVertexAttribArray(vNormalName);
renderer.EnableVertexAttribArray(vTexCoordName);
//renderer.EnableVertexAttribArray(vTexCoord3Name);
float dist = planetData.distanceToPlanetSurface(Environment::shipPosition);
auto zRange = planetData.calculateZRange(dist);
const float currentZNear = zRange.first;
const float currentZFar = zRange.second;
// 2. Применяем динамическую матрицу проекции // 2. Применяем динамическую матрицу проекции
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
static_cast<float>(Environment::width) / static_cast<float>(Environment::height), static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
@ -146,7 +365,6 @@ namespace ZL {
const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix(); const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix();
Vector3f lightDir_World = Vector3f(1.0f, 0.0f, -1.0f).normalized(); Vector3f lightDir_World = Vector3f(1.0f, 0.0f, -1.0f).normalized();
// В OpenGL/шейдерах удобнее работать с вектором, указывающим ОТ источника к поверхности. // В OpenGL/шейдерах удобнее работать с вектором, указывающим ОТ источника к поверхности.
Vector3f lightDirection_World = -lightDir_World; // Вектор, направленный от источника Vector3f lightDirection_World = -lightDir_World; // Вектор, направленный от источника
@ -164,10 +382,20 @@ namespace ZL {
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist); renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
renderer.RenderUniform1f("uCurrentZFar", currentZFar); renderer.RenderUniform1f("uCurrentZFar", currentZFar);
//glEnable(GL_BLEND); renderer.RenderUniform1f("testShift1", x/500.f);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения renderer.RenderUniform1f("testShift2", y / 5000.f);
renderer.RenderUniform1i("Texture", 0);
renderer.RenderUniform1i("StoneMap", 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, stoneMapFB->getTextureID());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID());
renderer.DrawVertexRenderStruct(planetRenderStruct); renderer.DrawVertexRenderStruct(planetRenderStruct);
//glDisable(GL_BLEND); //glDisable(GL_BLEND);
CheckGlError(); CheckGlError();
@ -176,6 +404,7 @@ namespace ZL {
renderer.PopMatrix(); renderer.PopMatrix();
renderer.PopProjectionMatrix(); renderer.PopProjectionMatrix();
//renderer.DisableVertexAttribArray(vTexCoord3Name); //renderer.DisableVertexAttribArray(vTexCoord3Name);
renderer.DisableVertexAttribArray(vTexCoord2Name);
renderer.DisableVertexAttribArray(vTexCoordName); renderer.DisableVertexAttribArray(vTexCoordName);
renderer.DisableVertexAttribArray(vNormalName); renderer.DisableVertexAttribArray(vNormalName);
renderer.DisableVertexAttribArray(vColorName); renderer.DisableVertexAttribArray(vColorName);
@ -188,7 +417,7 @@ namespace ZL {
void PlanetObject::drawStones(Renderer& renderer) void PlanetObject::drawStones(Renderer& renderer)
{ {
static const std::string defaultShaderName = "defaultColor"; //static const std::string defaultShaderName = "defaultColor";
static const std::string defaultShaderName2 = "defaultColor2"; static const std::string defaultShaderName2 = "defaultColor2";
static const std::string vPositionName = "vPosition"; static const std::string vPositionName = "vPosition";
static const std::string vColorName = "vColor"; static const std::string vColorName = "vColor";
@ -223,7 +452,6 @@ namespace ZL {
const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix(); const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix();
Vector3f lightDir_World = Vector3f(1.0f, 0.0f, -1.0f).normalized(); Vector3f lightDir_World = Vector3f(1.0f, 0.0f, -1.0f).normalized();
// В OpenGL/шейдерах удобнее работать с вектором, указывающим ОТ источника к поверхности. // В OpenGL/шейдерах удобнее работать с вектором, указывающим ОТ источника к поверхности.
Vector3f lightDirection_World = -lightDir_World; // Вектор, направленный от источника Vector3f lightDirection_World = -lightDir_World; // Вектор, направленный от источника
@ -250,6 +478,7 @@ namespace ZL {
if (planetStonesRenderStruct.data.PositionData.size() > 0) if (planetStonesRenderStruct.data.PositionData.size() > 0)
{ {
//glBindTexture(GL_TEXTURE_2D, fb->getTextureID());
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID()); glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
renderer.DrawVertexRenderStruct(planetStonesRenderStruct); renderer.DrawVertexRenderStruct(planetStonesRenderStruct);
//glDisable(GL_BLEND); //glDisable(GL_BLEND);

View File

@ -15,6 +15,8 @@
#include <set> #include <set>
#include "Perlin.h" #include "Perlin.h"
#include "PlanetData.h" #include "PlanetData.h"
#include "StoneObject.h"
#include "FrameBuffer.h"
namespace ZL { namespace ZL {
@ -25,9 +27,11 @@ namespace ZL {
// Данные только для рендеринга (OpenGL specific) // Данные только для рендеринга (OpenGL specific)
VertexRenderStruct planetRenderStruct; VertexRenderStruct planetRenderStruct;
VertexRenderStruct planetRenderStructCut;
VertexRenderStruct planetRenderYellowStruct; VertexRenderStruct planetRenderYellowStruct;
VertexRenderStruct planetAtmosphereRenderStruct; VertexRenderStruct planetAtmosphereRenderStruct;
VertexRenderStruct planetStonesRenderStruct; VertexRenderStruct planetStonesRenderStruct;
StoneGroup planetStones;
std::vector<int> triangleIndicesToDraw; std::vector<int> triangleIndicesToDraw;
@ -37,11 +41,17 @@ namespace ZL {
bool drawDataDirty = true; bool drawDataDirty = true;
void prepareDrawData(); void prepareDrawData();
std::unique_ptr<FrameBuffer> stoneMapFB;
public: public:
PlanetObject(); PlanetObject();
int x = 0;
int y = 0;
void init(); void init();
void update(float deltaTimeMs); void update(float deltaTimeMs);
void bakeStoneTexture(Renderer& renderer);
void draw(Renderer& renderer); void draw(Renderer& renderer);
void drawStones(Renderer& renderer); void drawStones(Renderer& renderer);
void drawPlanet(Renderer& renderer); void drawPlanet(Renderer& renderer);

View File

@ -294,6 +294,18 @@ namespace ZL {
glBufferData(GL_ARRAY_BUFFER, data.TexCoordData.size() * 8, &data.TexCoordData[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, data.TexCoordData.size() * 8, &data.TexCoordData[0], GL_STATIC_DRAW);
} }
/*if (data.TexCoord2Data.size() > 0)
{
if (!texCoord2VBO)
{
texCoord2VBO = std::make_shared<VBOHolder>();
}
glBindBuffer(GL_ARRAY_BUFFER, texCoord2VBO->getBuffer());
glBufferData(GL_ARRAY_BUFFER, data.TexCoord2Data.size() * 8, &data.TexCoord2Data[0], GL_STATIC_DRAW);
}*/
if (data.TexCoord3Data.size() > 0) if (data.TexCoord3Data.size() > 0)
{ {
if (!texCoord3VBO) if (!texCoord3VBO)
@ -442,6 +454,18 @@ namespace ZL {
throw std::runtime_error("Projection matrix stack overflow!!!!"); throw std::runtime_error("Projection matrix stack overflow!!!!");
} }
} }
void Renderer::PushProjectionMatrix(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar)
{
Matrix4f m = MakeOrthoMatrix(xmin, xmax, ymin, ymax, zNear, zFar);
ProjectionMatrixStack.push(m);
SetMatrix();
if (ProjectionMatrixStack.size() > CONST_MATRIX_STACK_SIZE)
{
throw std::runtime_error("Projection matrix stack overflow!!!!");
}
}
void Renderer::PushPerspectiveProjectionMatrix(float fovY, float aspectRatio, float zNear, float zFar) void Renderer::PushPerspectiveProjectionMatrix(float fovY, float aspectRatio, float zNear, float zFar)
{ {
@ -764,6 +788,7 @@ namespace ZL {
static const std::string vBinormal("vBinormal"); static const std::string vBinormal("vBinormal");
static const std::string vColor("vColor"); static const std::string vColor("vColor");
static const std::string vTexCoord("vTexCoord"); static const std::string vTexCoord("vTexCoord");
//static const std::string vTexCoord2("vTexCoord2");
static const std::string vTexCoord3("vTexCoord3"); static const std::string vTexCoord3("vTexCoord3");
static const std::string vPosition("vPosition"); static const std::string vPosition("vPosition");
@ -798,7 +823,7 @@ namespace ZL {
if (VertexRenderStruct.data.TexCoord3Data.size() > 0) if (VertexRenderStruct.data.TexCoord3Data.size() > 0)
{ {
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.texCoord3VBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.texCoord3VBO->getBuffer());
VertexAttribPointer2fv(vTexCoord3, 0, NULL); VertexAttribPointer3fv(vTexCoord3, 0, NULL);
} }
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.positionVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.positionVBO->getBuffer());

View File

@ -44,6 +44,7 @@ namespace ZL {
{ {
std::vector<Vector3f> PositionData; std::vector<Vector3f> PositionData;
std::vector<Vector2f> TexCoordData; std::vector<Vector2f> TexCoordData;
//std::vector<Vector2f> TexCoord2Data;
std::vector<Vector3f> TexCoord3Data; std::vector<Vector3f> TexCoord3Data;
std::vector<Vector3f> NormalData; std::vector<Vector3f> NormalData;
std::vector<Vector3f> TangentData; std::vector<Vector3f> TangentData;
@ -64,6 +65,7 @@ namespace ZL {
std::shared_ptr<VAOHolder> vao; std::shared_ptr<VAOHolder> vao;
std::shared_ptr<VBOHolder> positionVBO; std::shared_ptr<VBOHolder> positionVBO;
std::shared_ptr<VBOHolder> texCoordVBO; std::shared_ptr<VBOHolder> texCoordVBO;
//std::shared_ptr<VBOHolder> texCoord2VBO;
std::shared_ptr<VBOHolder> texCoord3VBO; std::shared_ptr<VBOHolder> texCoord3VBO;
std::shared_ptr<VBOHolder> normalVBO; std::shared_ptr<VBOHolder> normalVBO;
std::shared_ptr<VBOHolder> tangentVBO; std::shared_ptr<VBOHolder> tangentVBO;
@ -95,6 +97,7 @@ namespace ZL {
void InitOpenGL(); void InitOpenGL();
void PushProjectionMatrix(float width, float height, float zNear = 0.f, float zFar = 1.f); void PushProjectionMatrix(float width, float height, float zNear = 0.f, float zFar = 1.f);
void PushProjectionMatrix(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar);
void PushPerspectiveProjectionMatrix(float fovY, float aspectRatio, float zNear, float zFar); void PushPerspectiveProjectionMatrix(float fovY, float aspectRatio, float zNear, float zFar);
void PopProjectionMatrix(); void PopProjectionMatrix();

View File

@ -39,6 +39,7 @@ namespace ZL {
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled);
glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog); glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
if (!vertexShaderCompiled) if (!vertexShaderCompiled)
{ {
throw std::runtime_error("Failed to compile vertex shader code!"); throw std::runtime_error("Failed to compile vertex shader code!");

View File

@ -47,7 +47,7 @@ namespace ZL {
// --- ÊÎÍÑÒÀÍÒÛ ÏÀÐÀÌÅÒÐÎÂ (êàê âû ïðîñèëè) --- // --- ÊÎÍÑÒÀÍÒÛ ÏÀÐÀÌÅÒÐÎÂ (êàê âû ïðîñèëè) ---
//const float BASE_SCALE = 3.0f; // Îáùèé ðàçìåð êàìíÿ //const float BASE_SCALE = 3.0f; // Îáùèé ðàçìåð êàìíÿ
const float BASE_SCALE = 20.0f; // Îáùèé ðàçìåð êàìíÿ const float BASE_SCALE = 800.0f; // Îáùèé ðàçìåð êàìíÿ
const float MIN_AXIS_SCALE = 0.5f; // Ìèíèìàëüíîå ðàñòÿæåíèå/ñæàòèå ïî îñè const float MIN_AXIS_SCALE = 0.5f; // Ìèíèìàëüíîå ðàñòÿæåíèå/ñæàòèå ïî îñè
const float MAX_AXIS_SCALE = 1.5f; // Ìàêñèìàëüíîå ðàñòÿæåíèå/ñæàòèå ïî îñè const float MAX_AXIS_SCALE = 1.5f; // Ìàêñèìàëüíîå ðàñòÿæåíèå/ñæàòèå ïî îñè
const float MIN_PERTURBATION = 0.05f; // Ìèíèìàëüíîå ðàäèàëüíîå âîçìóùåíèå âåðøèíû const float MIN_PERTURBATION = 0.05f; // Ìèíèìàëüíîå ðàäèàëüíîå âîçìóùåíèå âåðøèíû
@ -201,107 +201,70 @@ namespace ZL {
return result; return result;
} }
VertexDataStruct CreateConvexPolyhedron(uint64_t seed, const LodLevel& planetLodLevel, const std::vector<int>& triangleIndices) { StoneGroup CreateStoneGroupData(uint64_t globalSeed, const LodLevel& planetLodLevel) {
StoneGroup group;
VertexDataStruct finalMesh;
const int STONES_PER_TRIANGLE = 100; const int STONES_PER_TRIANGLE = 100;
// Ðåçåðâèðóåì ìåñòî ïîä âñå òðåóãîëüíèêè òåêóùåãî LOD
group.allInstances.resize(planetLodLevel.triangles.size());
// Êîíñòàíòû òðàíñôîðìàöèè (íóæíû çäåñü, ÷òîáû êàæäûé êàìåíü áûë óíèêàëüíûì) for (size_t tIdx = 0; tIdx < planetLodLevel.triangles.size(); ++tIdx) {
const float MIN_AXIS_SCALE = 0.5f; const Triangle& tri = planetLodLevel.triangles[tIdx];
const float MAX_AXIS_SCALE = 1.5f; std::mt19937 engine(static_cast<unsigned int>(globalSeed));
// 1. Ñîçäàåì ÁÀÇÎÂÛÉ ÌÅØ ÎÄÈÍ ÐÀÇ, ÷òîáû íå ïîâòîðÿòü ñëîæíóþ ãåíåðàöèþ for (int i = 0; i < STONES_PER_TRIANGLE; ++i) {
// Èñïîëüçóåì îòäåëüíûé seed äëÿ áàçîâîé ôîðìû, ÷òîáû îíà áûëà óíèêàëüíîé, StoneInstance instance;
// íî îñòàâàëàñü îäèíàêîâîé ïðè ðàçíûõ seed äëÿ ðàçìåùåíèÿ. instance.seed = globalSeed;// + tIdx * 1000 + i; // Óíèêàëüíûé ñèä äëÿ êàæäîãî êàìíÿ
uint64_t baseSeed = 1337; // Êîíñòàíòíûé seed äëÿ ôîðìû êàìíÿ
VertexDataStruct baseStone = CreateBaseConvexPolyhedron(baseSeed); instance.position = GetRandomPointOnTriangle(tri, engine);
// 2. Èòåðèðóåìñÿ ïî çàäàííûì òðåóãîëüíèêàì // Ãåíåðèðóåì ñëó÷àéíûå ïàðàìåòðû îäèí ðàç
for (int triangleIndex : triangleIndices) { instance.scale = {
getRandomFloat(engine, 0.5f, 1.5f),
std::mt19937 engine(static_cast<unsigned int>(seed)); getRandomFloat(engine, 0.5f, 1.5f),
getRandomFloat(engine, 0.5f, 1.5f)
if (triangleIndex >= planetLodLevel.triangles.size()) {
// Îáðàáîòêà îøèáêè
continue;
}
const Triangle& currentTriangle = planetLodLevel.triangles[triangleIndex];
// 3. Ãåíåðèðóåì 100 êàìíåé íà êàæäîì òðåóãîëüíèêå
for (int i = 0; i < STONES_PER_TRIANGLE; i++) {
// --- 3.1. Ãåíåðèðóåì ñëó÷àéíîå ìåñòîïîëîæåíèå íà òðåóãîëüíèêå ---
Vector3f stoneCenter = GetRandomPointOnTriangle(currentTriangle, engine);
// --- 3.2. Ïðèìåíÿåì ñëó÷àéíóþ òðàíñôîðìàöèþ (Ìàñøòàá + Ïîâîðîò) ---
// Ñëó÷àéíûå ìàñøòàáû
Vector3f scaleFactors = {
getRandomFloat(engine, MIN_AXIS_SCALE, MAX_AXIS_SCALE),
getRandomFloat(engine, MIN_AXIS_SCALE, MAX_AXIS_SCALE),
getRandomFloat(engine, MIN_AXIS_SCALE, MAX_AXIS_SCALE)
}; };
// Ñëó÷àéíûé ïîâîðîò (íàïðèìåð, âîêðóã îñè íîðìàëè ê ïîâåðõíîñòè)
// Äëÿ ðåàëèñòè÷íîñòè, êàìåíü äîëæåí ëåæàòü íà ïîâåðõíîñòè.
// Âåêòîð 'ââåðõ' äëÿ êàìíÿ äîëæåí áûòü âûðîâíåí ïî íîðìàëè òðåóãîëüíèêà.
// 1. Ñîçäàåì âðàùåíèå âîêðóã íîðìàëè òðåóãîëüíèêà (currentTriangle.normal)
float angle = getRandomFloat(engine, 0.0f, 360.0f);
// (Äëÿ ïðîñòîòû çäåñü èñïîëüçóåòñÿ Matrix4f::Identity, íî âàì íóæíî ðåàëèçîâàòü
// QuaternionFromAxisAngle äëÿ êîððåêòíîãî âðàùåíèÿ âîêðóã çàäàííîé îñè Normal)
// --- ÏÐÎÑÒÎÅ ÐÅØÅÍÈÅ: Ñëó÷àéíûé ïîâîðîò âîêðóã òðåõ îñåé ---
Vector4f qx = QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f)); Vector4f qx = QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f));
Vector4f qy = QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f)); Vector4f qy = QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f));
Vector4f qz = QuatFromRotateAroundZ(getRandomFloat(engine, 0.0f, 360.0f)); Vector4f qz = QuatFromRotateAroundZ(getRandomFloat(engine, 0.0f, 360.0f));
Vector4f qFinal = slerp(qx, qy, 0.5f); instance.rotation = slerp(slerp(qx, qy, 0.5f), qz, 0.5f).normalized();
qFinal = slerp(qFinal, qz, 0.5f).normalized();
Matrix3f rotationMatrix = QuatToMatrix(qFinal);
group.allInstances[tIdx].push_back(instance);
// --- 3.3. Òðàíñôîðìèðóåì è Ñìåùàåì âåðøèíû áàçîâîãî ìåøà ---
// Êîïèðóåì äàííûå äëÿ òåêóùåãî êàìíÿ
VertexDataStruct currentStone = baseStone;
// Ïðèìåíÿåì ìàñøòàáèðîâàíèå, ïîâîðîò, è ñìåùåíèå ê êàæäîé âåðøèíå
for (size_t j = 0; j < currentStone.PositionData.size(); j++) {
Vector3f& pos = currentStone.PositionData[j];
Vector3f& norm = currentStone.NormalData[j];
// 1. Ìàñøòàáèðîâàíèå
pos.v[0] *= scaleFactors.v[0];
pos.v[1] *= scaleFactors.v[1];
pos.v[2] *= scaleFactors.v[2];
// 2. Ïîâîðîò
pos = MultMatrixVector(rotationMatrix, pos);
norm = MultMatrixVector(rotationMatrix, norm);
// 3. Ñìåùåíèå (Translation)
pos = pos + stoneCenter;
}
// --- 3.4. Îáúåäèíÿåì ìåøè ---
finalMesh.PositionData.insert(finalMesh.PositionData.end(),
currentStone.PositionData.begin(),
currentStone.PositionData.end());
finalMesh.NormalData.insert(finalMesh.NormalData.end(),
currentStone.NormalData.begin(),
currentStone.NormalData.end());
finalMesh.TexCoordData.insert(finalMesh.TexCoordData.end(),
currentStone.TexCoordData.begin(),
currentStone.TexCoordData.end());
// ... àíàëîãè÷íî äëÿ äðóãèõ äàííûõ (Tangent, Binormal, Color)
} }
} }
return group;
}
return finalMesh; void StoneGroup::inflate(const std::vector<int>& triangleIndices) {
// 1. Î÷èùàåì òåêóùèé ìåø ïåðåä çàïîëíåíèåì
mesh.PositionData.clear();
mesh.NormalData.clear();
mesh.TexCoordData.clear();
static VertexDataStruct baseStone = CreateBaseConvexPolyhedron(1337);
// 2. Íàïîëíÿåì ìåø òîëüêî äëÿ âèäèìûõ òðåóãîëüíèêîâ
for (int tIdx : triangleIndices) {
if (tIdx >= allInstances.size()) continue;
for (const auto& inst : allInstances[tIdx]) {
Matrix3f rotMat = QuatToMatrix(inst.rotation);
for (size_t j = 0; j < baseStone.PositionData.size(); ++j) {
Vector3f p = baseStone.PositionData[j];
Vector3f n = baseStone.NormalData[j];
// Ìàñøòàá -> Ïîâîðîò -> Ñìåùåíèå
p.v[0] *= inst.scale.v[0];
p.v[1] *= inst.scale.v[1];
p.v[2] *= inst.scale.v[2];
mesh.PositionData.push_back(MultMatrixVector(rotMat, p) + inst.position);
mesh.NormalData.push_back(MultMatrixVector(rotMat, n));
mesh.TexCoordData.push_back(baseStone.TexCoordData[j]);
}
}
}
} }
} // namespace ZL } // namespace ZL

View File

@ -5,7 +5,26 @@
namespace ZL { namespace ZL {
VertexDataStruct CreateBaseConvexPolyhedron(uint64_t seed); struct StoneInstance {
VertexDataStruct CreateConvexPolyhedron(uint64_t seed, const LodLevel& planetLodLevel, const std::vector<int>& triangleIndices); uint64_t seed;
Vector3f position;
Vector3f scale;
Vector4f rotation;
};
struct StoneGroup {
// mesh.PositionData è ïðî÷èå áóäóò çàïîëíÿòüñÿ â inflate()
VertexDataStruct mesh;
// Âíåøíèé âåêòîð — èíäåêñ òðåóãîëüíèêà ïëàíåòû,
// âíóòðåííèé — ñïèñîê êàìíåé íà ýòîì òðåóãîëüíèêå
std::vector<std::vector<StoneInstance>> allInstances;
// Î÷èùàåò ñòàðóþ ãåîìåòðèþ è ãåíåðèðóåò íîâóþ äëÿ óêàçàííûõ èíäåêñîâ
void inflate(const std::vector<int>& triangleIndices);
};
// Òåïåðü âîçâðàùàåò çàãîòîâêó ñî âñåìè ïàðàìåòðàìè, íî áåç òÿæåëîãî ìåøà
StoneGroup CreateStoneGroupData(uint64_t globalSeed, const LodLevel& planetLodLevel);
} // namespace ZL } // namespace ZL

View File

@ -189,6 +189,38 @@ namespace ZL {
return r; return r;
} }
Matrix4f MakeOrthoMatrix(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar)
{
float width = xmax - xmin;
float height = ymax - ymin;
float depthRange = zFar - zNear;
if (width <= 0 || height <= 0 || depthRange <= 0)
{
throw std::runtime_error("Invalid dimensions for orthogonal matrix");
}
Matrix4f r;
// Масштабирование
r.m[0] = 2.f / width;
r.m[5] = 2.f / height;
r.m[10] = -1.f / depthRange;
// Обнуление неиспользуемых компонентов
r.m[1] = r.m[2] = r.m[3] = 0;
r.m[4] = r.m[6] = r.m[7] = 0;
r.m[8] = r.m[9] = r.m[11] = 0;
// Трансляция (смещение)
r.m[12] = -(xmax + xmin) / width;
r.m[13] = -(ymax + ymin) / height;
r.m[14] = zNear / depthRange;
r.m[15] = 1.f;
return r;
}
Matrix4f MakePerspectiveMatrix(float fovY, float aspectRatio, float zNear, float zFar) Matrix4f MakePerspectiveMatrix(float fovY, float aspectRatio, float zNear, float zFar)
{ {
float tanHalfFovy = tan(fovY / 2.f); float tanHalfFovy = tan(fovY / 2.f);

View File

@ -153,6 +153,7 @@ namespace ZL {
Matrix4f operator*(const Matrix4f& m1, const Matrix4f& m2); Matrix4f operator*(const Matrix4f& m1, const Matrix4f& m2);
Matrix4f MakeOrthoMatrix(float width, float height, float zNear, float zFar); Matrix4f MakeOrthoMatrix(float width, float height, float zNear, float zFar);
Matrix4f MakeOrthoMatrix(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar);
Matrix4f MakePerspectiveMatrix(float fovY, float aspectRatio, float zNear, float zFar); Matrix4f MakePerspectiveMatrix(float fovY, float aspectRatio, float zNear, float zFar);

BIN
resources/rockx.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sandx.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -90,8 +90,8 @@ void main()
// 4. Смешивание цвета с туманом // 4. Смешивание цвета с туманом
//vec3 mountainColor = vec3((length(pos+vec3(0.0,0.0,45000.0))-20000.0)/100.0, 0.5,0.0); //vec3 mountainColor = vec3((length(pos+vec3(0.0,0.0,45000.0))-20000.0)/100.0, 0.5,0.0);
gl_FragColor = mix(vec4(uColor* finalColor.rgb, 1.0), FOG_COLOR, fogFactor); //gl_FragColor = mix(vec4(uColor* finalColor.rgb, 1.0), FOG_COLOR, fogFactor);
//gl_FragColor = vec4((length(pos+vec3(0.0,0.0,45000.0))-20000.0)/100.0, 0.0,0.0, 1.0); //gl_FragColor = vec4((length(pos+vec3(0.0,0.0,45000.0))-20000.0)/100.0, 0.0,0.0, 1.0);
//gl_FragColor = vec4(fogFactor, 0.5,0.5, 1.0); //gl_FragColor = vec4(fogFactor, 0.5,0.5, 1.0);
//gl_FragColor = vec4(uColor*textureColor.rgb, 1.0); gl_FragColor = vec4(textureColor.rgb, 1.0);
} }

View File

@ -0,0 +1,18 @@
// Вершинный шейдер (Vertex Shader)
attribute vec3 vPosition;
attribute vec2 vTexCoord;
varying vec2 TexCoord;
uniform mat4 ProjectionModelViewMatrix;
void main()
{
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
TexCoord = vTexCoord;
}

View File

@ -0,0 +1,24 @@
// Fragment Shader
varying vec2 TexCoord;
uniform sampler2D Texture; // sandTexture
uniform sampler2D StoneMap; // Наша запеченная текстура
uniform float testShift1;
uniform float testShift2;
void main()
{
vec2 newTexCoord;
newTexCoord.x = TexCoord.x;
//newTexCoord.y = 1.0 - TexCoord.y - 0.0122;
//newTexCoord.y = TexCoord.y * (1.0+testShift) + 0.0122;
//newTexCoord.y = (TexCoord.y + 0.0122)*(1.0 +x/500.0);
newTexCoord.y = TexCoord.y * (1.0-6.0/500.0) + 0.0122+ (11.0/500.0) *0.1 -6/5000.0;
//newTexCoord.y = TexCoord.y;
vec4 sandColor = texture2D(Texture, TexCoord);
vec4 stoneData = texture2D(StoneMap, newTexCoord);
//vec3 finalColor = sandColor.rgb*0.5 + stoneData.rgb*0.5;
vec3 finalColor = stoneData.rgb;
//vec3 finalColor = sandColor.rgb;
gl_FragColor = vec4(finalColor, 1.0);
}