618 lines
23 KiB
C++
618 lines
23 KiB
C++
#include "PlanetObject.h"
|
||
#include <random>
|
||
#include <cmath>
|
||
#include "OpenGlExtensions.h"
|
||
#include "Environment.h"
|
||
#include "StoneObject.h"
|
||
|
||
namespace ZL {
|
||
|
||
|
||
Matrix3f GetRotationForTriangle(const Triangle& tri) {
|
||
// Для треугольника №0:
|
||
// tri.data[0] = {0, 20000, 0} (A)
|
||
// tri.data[1] = {0, 0, 20000} (B)
|
||
// tri.data[2] = {20000, 0, 0} (C)
|
||
|
||
Vector3f vA = tri.data[0];
|
||
Vector3f vB = tri.data[1];
|
||
Vector3f vC = tri.data[2];
|
||
|
||
// 1. Вычисляем ось X (горизонталь).
|
||
// Нам нужна грань BC: от (0, 0, 20000) до (20000, 0, 0)
|
||
Vector3f x_axis = (vC - vB).normalized();
|
||
|
||
|
||
// 2. Вычисляем нормаль (ось Z).
|
||
// Порядок cross product (AB x AC) определит "лицевую" сторону.
|
||
Vector3f edge1 = vB - vA;
|
||
Vector3f edge2 = vC - vA;
|
||
Vector3f z_axis = edge1.cross(edge2).normalized();
|
||
|
||
// 3. Вычисляем ось Y (вертикаль).
|
||
// В ортонормированном базисе Y всегда перпендикулярна Z и X.
|
||
Vector3f y_axis = z_axis.cross(x_axis).normalized();
|
||
|
||
// 4. Формируем прямую матрицу поворота (Rotation/World Matrix).
|
||
// Векторы базиса записываются в СТОЛБЦЫ.
|
||
// В памяти Matrix3f m (std::array<float, 9>):
|
||
// m[0]=X.x, m[1]=Y.x, m[2]=Z.x
|
||
// m[3]=X.y, m[4]=Y.y, m[5]=Z.y
|
||
// m[6]=X.z, m[7]=Y.z, m[8]=Z.z
|
||
|
||
Matrix3f rot;
|
||
|
||
// Столбец 0: Ось X
|
||
rot.m[0] = x_axis.v[0];
|
||
rot.m[3] = x_axis.v[1];
|
||
rot.m[6] = x_axis.v[2];
|
||
|
||
// Столбец 1: Ось Y
|
||
rot.m[1] = y_axis.v[0];
|
||
rot.m[4] = y_axis.v[1];
|
||
rot.m[7] = y_axis.v[2];
|
||
|
||
// Столбец 2: Ось Z
|
||
rot.m[2] = z_axis.v[0];
|
||
rot.m[5] = z_axis.v[1];
|
||
rot.m[8] = z_axis.v[2];
|
||
|
||
return rot;
|
||
}
|
||
|
||
PlanetObject::PlanetObject()
|
||
{
|
||
|
||
}
|
||
|
||
void PlanetObject::init() {
|
||
// 1. Инициализируем данные (генерация мешей)
|
||
planetData.init();
|
||
|
||
// 2. Забираем данные для VBO
|
||
// Берем максимальный LOD для начальной отрисовки
|
||
int lodIndex = planetData.getMaxLodIndex();
|
||
planetRenderStruct.data = planetData.getLodLevel(lodIndex).vertexData;
|
||
/*planetRenderStruct.data.PositionData[0] = planetRenderStruct.data.PositionData[6 * 3];
|
||
planetRenderStruct.data.PositionData[0+1] = planetRenderStruct.data.PositionData[6 * 3+1];
|
||
planetRenderStruct.data.PositionData[0+2] = planetRenderStruct.data.PositionData[6 * 3+2];
|
||
*/
|
||
//planetRenderStruct.data.PositionData.resize(3);
|
||
/*planetRenderStruct.data.NormalData[0] = Vector3f{1.0,1.0,1.0}.normalized();
|
||
planetRenderStruct.data.NormalData[1] = Vector3f{ 1.0,1.0,1.0 }.normalized();
|
||
planetRenderStruct.data.NormalData[2] = Vector3f{ 1.0,1.0,1.0 }.normalized();*/
|
||
planetRenderStruct.RefreshVBO();
|
||
|
||
planetRenderStructCut.data = planetData.getLodLevel(lodIndex).vertexData;
|
||
|
||
planetRenderStructCut.data.PositionData.resize(3);
|
||
|
||
planetRenderStructCut.RefreshVBO();
|
||
//sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", ""));
|
||
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", ""));
|
||
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", ""));
|
||
|
||
// Атмосфера
|
||
planetAtmosphereRenderStruct.data = planetData.getAtmosphereLod().vertexData;
|
||
planetAtmosphereRenderStruct.RefreshVBO();
|
||
|
||
|
||
planetStones = CreateStoneGroupData(777, planetData.getLodLevel(lodIndex));
|
||
planetStones.inflate({ 0/*,1,2,3,4,5,6,7*/ });
|
||
planetStonesToBakeRenderStruct.AssignFrom(planetStones.mesh);
|
||
planetStonesToBakeRenderStruct.RefreshVBO();
|
||
|
||
|
||
}
|
||
|
||
void PlanetObject::prepareDrawData() {
|
||
if (!drawDataDirty) return;
|
||
drawDataDirty = false;
|
||
}
|
||
|
||
|
||
void PlanetObject::update(float deltaTimeMs) {
|
||
// 1. Получаем базовые треугольники под камерой
|
||
auto lr = planetData.getTrianglesUnderCamera(Environment::shipPosition);
|
||
int currentLod = planetData.getCurrentLodIndex();
|
||
|
||
// Временный вектор для сбора новых индексов
|
||
std::vector<int> newIndices;
|
||
std::set<int> used;
|
||
|
||
// Рекурсивно (или итеративно, как у тебя) собираем индексы видимых зон
|
||
for (int i : lr) {
|
||
if (used.insert(i).second) newIndices.push_back(i);
|
||
|
||
auto neighbors = planetData.findNeighbors(i, currentLod);
|
||
for (int n : neighbors) {
|
||
if (used.insert(n).second) newIndices.push_back(n);
|
||
|
||
auto neighbors2 = planetData.findNeighbors(n, currentLod);
|
||
for (int n2 : neighbors2) {
|
||
if (used.insert(n2).second) newIndices.push_back(n2);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 2. Сортируем новый список, чтобы порядок не влиял на сравнение
|
||
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]);
|
||
}
|
||
}
|
||
if (planetRenderYellowStruct.data.PositionData.size() > 0)
|
||
{
|
||
planetRenderYellowStruct.RefreshVBO();
|
||
}
|
||
|
||
// --- ОБНОВЛЯЕМ КАМНИ (через новую структуру StoneGroup) ---
|
||
if (triangleIndicesToDraw.size() > 0)
|
||
{
|
||
planetStones.inflate(triangleIndicesToDraw);
|
||
// Используем AssignFrom, он внутри сам вызывает RefreshVBO
|
||
planetStonesRenderStruct.AssignFrom(planetStones.mesh);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
void PlanetObject::bakeStoneTexture(Renderer& renderer) {
|
||
glViewport(0, 0, 512, 512);
|
||
glClearColor(224 / 255.f, 201 / 255.f, 167 / 255.f, 1.0f);
|
||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||
|
||
|
||
static const std::string defaultShaderName2 = "defaultColorBake";
|
||
static const std::string vPositionName = "vPosition";
|
||
static const std::string vTexCoordName = "vTexCoord";
|
||
static const std::string textureUniformName = "Texture";
|
||
|
||
|
||
renderer.shaderManager.PushShader(defaultShaderName2);
|
||
renderer.RenderUniform1i(textureUniformName, 0);
|
||
renderer.EnableVertexAttribArray(vPositionName);
|
||
renderer.EnableVertexAttribArray(vTexCoordName);
|
||
|
||
float dist = planetData.distanceToPlanetSurface(Environment::shipPosition);
|
||
auto zRange = planetData.calculateZRange(dist);
|
||
const float currentZNear = zRange.first;
|
||
const float currentZFar = zRange.second;
|
||
|
||
|
||
|
||
Triangle tr = planetData.getLodLevel(planetData.getCurrentLodIndex()).triangles[0];
|
||
|
||
// 1. Получаем матрицу вращения (оси в столбцах)
|
||
Matrix3f mr = GetRotationForTriangle(tr);
|
||
|
||
// 2. Трансформируем вершины в локальное пространство экрана, чтобы найти габариты
|
||
// Используем MultMatrixVector(Matrix, Vector).
|
||
// Если ваша функция считает V * M, то передайте Inverse(mr).
|
||
Vector3f rA = MultMatrixVector(mr, tr.data[0]);
|
||
Vector3f rB = MultMatrixVector(mr, tr.data[1]);
|
||
Vector3f rC = MultMatrixVector(mr, tr.data[2]);
|
||
|
||
// 3. Вычисляем реальные границы треугольника после поворота
|
||
float minX = min(rA.v[0], min(rB.v[0], rC.v[0]));
|
||
float maxX = max(rA.v[0], max(rB.v[0], rC.v[0]));
|
||
float minY = min(rA.v[1], min(rB.v[1], rC.v[1]));
|
||
float maxY = max(rA.v[1], max(rB.v[1], rC.v[1]));
|
||
|
||
|
||
// Находим центр и размеры
|
||
float width = maxX - minX;
|
||
float height = maxY - minY;
|
||
float centerX = (minX + maxX) * 0.5f;
|
||
float centerY = (minY + maxY) * 0.5f;
|
||
|
||
//float size = max(width, height);
|
||
//float hSize = size * 0.5f;
|
||
|
||
renderer.PushProjectionMatrix(
|
||
centerX - width*0.5, centerX + width * 0.5,
|
||
centerY - height * 0.5, centerY + height * 0.5,
|
||
//currentZNear, currentZFar);
|
||
150, 200000);
|
||
|
||
renderer.PushMatrix();
|
||
renderer.LoadIdentity();
|
||
|
||
|
||
// Сдвигаем камеру по Z
|
||
renderer.TranslateMatrix(Vector3f{ 0, 0, -45000 });
|
||
|
||
// Применяем вращение
|
||
renderer.RotateMatrix(mr);
|
||
|
||
|
||
// Извлекаем нормаль треугольника (это 3-й столбец нашей матрицы вращения)
|
||
Vector3f planeNormal = { mr.m[2], mr.m[5], mr.m[8] };
|
||
//Vector3f planeNormal = { 0,0,1 };
|
||
|
||
|
||
renderer.RenderUniform3fv("uPlanePoint", &tr.data[0].v[0]);
|
||
renderer.RenderUniform3fv("uPlaneNormal", &planeNormal.v[0]);
|
||
renderer.RenderUniform1f("uMaxHeight", StoneParams::BASE_SCALE * 1.1f); // Соответствует BASE_SCALE + perturbation
|
||
|
||
|
||
|
||
glActiveTexture(GL_TEXTURE0);
|
||
glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID());
|
||
|
||
renderer.DrawVertexRenderStruct(planetRenderStructCut);
|
||
|
||
//glClear(GL_DEPTH_BUFFER_BIT);
|
||
|
||
glEnable(GL_CULL_FACE);
|
||
glCullFace(GL_BACK); // Отсекаем задние грани
|
||
if (planetStonesToBakeRenderStruct.data.PositionData.size() > 0)
|
||
{
|
||
|
||
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
|
||
renderer.DrawVertexRenderStruct(planetStonesToBakeRenderStruct);
|
||
CheckGlError();
|
||
}
|
||
glDisable(GL_CULL_FACE); // Не забываем выключить, чтобы не сломать остальной рендер
|
||
renderer.PopMatrix();
|
||
renderer.PopProjectionMatrix();
|
||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||
renderer.DisableVertexAttribArray(vPositionName);
|
||
renderer.shaderManager.PopShader();
|
||
CheckGlError();
|
||
}
|
||
|
||
|
||
void PlanetObject::draw(Renderer& renderer) {
|
||
|
||
prepareDrawData();
|
||
|
||
{
|
||
if (stoneMapFB == nullptr)
|
||
{
|
||
stoneMapFB = std::make_unique<FrameBuffer>(512, 512);
|
||
}
|
||
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("vTangent");
|
||
renderer.EnableVertexAttribArray("vBinormal");
|
||
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. Применяем динамическую матрицу проекции
|
||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||
currentZNear, currentZFar);
|
||
|
||
renderer.PushMatrix();
|
||
renderer.LoadIdentity();
|
||
//renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||
|
||
//renderer.RotateMatrix(QuatToMatrix(QuatFromRotateAroundX(M_PI / 4.0)));
|
||
//renderer.RotateMatrix(QuatToMatrix(QuatFromRotateAroundY(-M_PI / 4.0)));
|
||
|
||
renderer.TranslateMatrix(-Environment::shipPosition);
|
||
|
||
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);
|
||
*/
|
||
renderer.RenderUniform1i("Texture", 0);
|
||
|
||
Triangle tr = planetData.getLodLevel(planetData.getCurrentLodIndex()).triangles[0]; // Берем базовый треугольник
|
||
Matrix3f mr = GetRotationForTriangle(tr); // Та же матрица, что и при запекании
|
||
|
||
// Позиция камеры (корабля) в мире
|
||
renderer.RenderUniform3fv("uViewPos", &Environment::shipPosition.v[0]);
|
||
|
||
// Передаем матрицу вращения треугольника для перехода в Tangent Space
|
||
renderer.RenderUniformMatrix3fv("uTangentMatrix", false, &mr.m[0]);
|
||
|
||
// Не забудьте масштаб эффекта (глубина камней)
|
||
renderer.RenderUniform1f("uHeightScale", 0.03f);
|
||
//renderer.RenderUniform1f("uHeightScale", -0.01f);
|
||
//renderer.RenderUniform1f("uHeightScale", 0.0f + x / 1000.f);
|
||
//renderer.RenderUniform1f("uHeightScale", 0.0f);
|
||
glBindTexture(GL_TEXTURE_2D, stoneMapFB->getTextureID());
|
||
|
||
renderer.DrawVertexRenderStruct(planetRenderStruct);
|
||
CheckGlError();
|
||
|
||
renderer.PopMatrix();
|
||
renderer.PopProjectionMatrix();
|
||
//renderer.DisableVertexAttribArray(vTexCoord3Name);
|
||
renderer.DisableVertexAttribArray(vTexCoord2Name);
|
||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||
renderer.DisableVertexAttribArray(vNormalName);
|
||
renderer.DisableVertexAttribArray("vTangent");
|
||
renderer.DisableVertexAttribArray("vBinormal");
|
||
renderer.DisableVertexAttribArray(vColorName);
|
||
renderer.DisableVertexAttribArray(vPositionName);
|
||
renderer.shaderManager.PopShader();
|
||
CheckGlError();
|
||
|
||
|
||
}
|
||
|
||
void PlanetObject::drawStones(Renderer& renderer)
|
||
{
|
||
//static const std::string defaultShaderName = "defaultColor";
|
||
static const std::string defaultShaderName2 = "defaultColor2";
|
||
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";
|
||
|
||
renderer.shaderManager.PushShader(defaultShaderName2);
|
||
renderer.RenderUniform1i(textureUniformName, 0);
|
||
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. Применяем динамическую матрицу проекции
|
||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||
currentZNear, currentZFar);
|
||
|
||
renderer.PushMatrix();
|
||
renderer.LoadIdentity();
|
||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||
renderer.TranslateMatrix(-Environment::shipPosition);
|
||
|
||
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]);
|
||
|
||
if (planetStonesRenderStruct.data.PositionData.size() > 0)
|
||
{
|
||
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
|
||
renderer.DrawVertexRenderStruct(planetStonesRenderStruct);
|
||
CheckGlError();
|
||
}
|
||
|
||
|
||
renderer.PopMatrix();
|
||
renderer.PopProjectionMatrix();
|
||
//renderer.DisableVertexAttribArray(vTexCoord3Name);
|
||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||
renderer.DisableVertexAttribArray(vNormalName);
|
||
renderer.DisableVertexAttribArray(vColorName);
|
||
renderer.DisableVertexAttribArray(vPositionName);
|
||
renderer.shaderManager.PopShader();
|
||
CheckGlError();
|
||
|
||
glClear(GL_DEPTH_BUFFER_BIT);
|
||
}
|
||
|
||
void PlanetObject::drawYellowZone(Renderer& renderer)
|
||
{
|
||
|
||
static const std::string defaultShaderName = "defaultColor";
|
||
static const std::string defaultShaderName2 = "defaultColor2";
|
||
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";
|
||
|
||
float dist = planetData.distanceToPlanetSurface(Environment::shipPosition);
|
||
auto zRange = planetData.calculateZRange(dist);
|
||
const float currentZNear = zRange.first;
|
||
const float currentZFar = zRange.second;
|
||
|
||
|
||
glClear(GL_DEPTH_BUFFER_BIT);
|
||
if (planetRenderYellowStruct.data.PositionData.size() > 0)
|
||
{
|
||
|
||
renderer.shaderManager.PushShader(defaultShaderName2);
|
||
renderer.RenderUniform1i(textureUniformName, 0);
|
||
renderer.EnableVertexAttribArray(vPositionName);
|
||
renderer.EnableVertexAttribArray(vTexCoordName);
|
||
|
||
|
||
// 2. Применяем динамическую матрицу проекции
|
||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||
currentZNear, currentZFar);
|
||
|
||
renderer.PushMatrix();
|
||
renderer.LoadIdentity();
|
||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||
|
||
renderer.TranslateMatrix(-Environment::shipPosition);
|
||
|
||
|
||
|
||
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
|
||
renderer.RenderUniform1f("uCurrentZFar", currentZFar);
|
||
|
||
Vector3f color2 = { 1.0, 1.0, 0.0 };
|
||
|
||
glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID());
|
||
|
||
renderer.RenderUniform3fv("uColor", &color2.v[0]);
|
||
renderer.DrawVertexRenderStruct(planetRenderYellowStruct);
|
||
//glDisable(GL_BLEND);
|
||
CheckGlError();
|
||
|
||
|
||
renderer.PopMatrix();
|
||
renderer.PopProjectionMatrix();
|
||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||
|
||
renderer.DisableVertexAttribArray(vPositionName);
|
||
renderer.shaderManager.PopShader();
|
||
CheckGlError();
|
||
|
||
}
|
||
}
|
||
|
||
void PlanetObject::drawAtmosphere(Renderer& renderer) {
|
||
static const std::string defaultShaderName = "defaultAtmosphere";
|
||
static const std::string vPositionName = "vPosition";
|
||
static const std::string vNormalName = "vNormal";
|
||
//glClear(GL_DEPTH_BUFFER_BIT);
|
||
glDepthMask(GL_FALSE);
|
||
|
||
renderer.shaderManager.PushShader(defaultShaderName);
|
||
renderer.EnableVertexAttribArray(vPositionName);
|
||
renderer.EnableVertexAttribArray(vNormalName);
|
||
|
||
|
||
float dist = planetData.distanceToPlanetSurface(Environment::shipPosition);
|
||
auto zRange = planetData.calculateZRange(dist);
|
||
const float currentZNear = zRange.first;
|
||
const float currentZFar = zRange.second;
|
||
|
||
// 2. Применяем динамическую матрицу проекции
|
||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||
currentZNear, currentZFar);
|
||
|
||
renderer.PushMatrix();
|
||
renderer.LoadIdentity();
|
||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||
renderer.TranslateMatrix(-Environment::shipPosition);
|
||
|
||
const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix();
|
||
|
||
Vector3f color = { 0.0, 0.5, 1.0 };
|
||
|
||
renderer.RenderUniform3fv("uColor", &color.v[0]);
|
||
|
||
renderer.RenderUniformMatrix4fv("ModelViewMatrix", false, &viewMatrix.m[0]);
|
||
|
||
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
|
||
|
||
glEnable(GL_BLEND);
|
||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения
|
||
|
||
renderer.DrawVertexRenderStruct(planetAtmosphereRenderStruct);
|
||
glDisable(GL_BLEND);
|
||
glDepthMask(GL_TRUE);
|
||
renderer.PopMatrix();
|
||
renderer.PopProjectionMatrix();
|
||
|
||
renderer.DisableVertexAttribArray(vNormalName);
|
||
renderer.DisableVertexAttribArray(vPositionName);
|
||
renderer.shaderManager.PopShader();
|
||
CheckGlError();
|
||
|
||
}
|
||
|
||
float PlanetObject::distanceToPlanetSurface(const Vector3f& viewerPosition)
|
||
{
|
||
return planetData.distanceToPlanetSurface(viewerPosition);
|
||
}
|
||
|
||
|
||
|
||
} // namespace ZL
|