From 14b43239b545f128c6298cfb203621d56ea66bcc Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sun, 28 Dec 2025 18:29:25 +0300 Subject: [PATCH] Parallax mapping working on single triangle --- Game.cpp | 10 +- PlanetData.cpp | 79 ++++++----- PlanetData.h | 4 +- PlanetObject.cpp | 130 ++++++++++-------- PlanetObject.h | 1 + Renderer.cpp | 12 ++ Renderer.h | 1 + StoneObject.cpp | 17 ++- shaders/defaultColor_bake.vertex | 34 +++++ shaders/defaultColor_bake_desktop.fragment | 21 +++ shaders/defaultColor_fog_stones.vertex | 26 ++-- .../defaultColor_fog_stones_desktop.fragment | 87 +++++++++--- 12 files changed, 290 insertions(+), 132 deletions(-) create mode 100644 shaders/defaultColor_bake.vertex create mode 100644 shaders/defaultColor_bake_desktop.fragment diff --git a/Game.cpp b/Game.cpp index 43de537..48ae6ec 100755 --- a/Game.cpp +++ b/Game.cpp @@ -146,7 +146,7 @@ namespace ZL 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("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); + renderer.shaderManager.AddShaderFromFiles("defaultColorBake", "./shaders/defaultColor_bake.vertex", "./shaders/defaultColor_bake_desktop.fragment", CONST_ZIP_FILE); #endif cubemapTexture = std::make_shared( @@ -173,6 +173,7 @@ namespace ZL spaceship.AssignFrom(spaceshipBase); spaceship.RefreshVBO(); + //Boxes boxTexture = std::make_unique(CreateTextureDataFromPng("./resources/box/box.png", CONST_ZIP_FILE)); boxBase = LoadFromTextFile02("./resources/box/box.txt", CONST_ZIP_FILE); @@ -473,6 +474,7 @@ namespace ZL skyPercent = (1900.f - distance) / 900.f; } + drawCubemap(skyPercent); planetObject.draw(renderer); if (planetObject.distanceToPlanetSurface(Environment::shipPosition) > 100.f) @@ -636,7 +638,11 @@ namespace ZL } if (event.key.keysym.sym == SDLK_q) { - planetObject.y += 1; + + Environment::shipPosition = { 0, 0, 25000 }; + //Environment::shipPosition = { 50000, 50000, 50000 }; + + //planetObject.y += 1; } if (event.key.keysym.sym == SDLK_w) { diff --git a/PlanetData.cpp b/PlanetData.cpp index 23669af..fc19a4d 100644 --- a/PlanetData.cpp +++ b/PlanetData.cpp @@ -199,6 +199,7 @@ namespace ZL { return r; } + std::vector PlanetData::getTrianglesUnderCamera(const Vector3f& viewerPosition) { // LOD return recursiveTriangleSearch(currentLod, viewerPosition, planetMeshLods); @@ -316,41 +317,51 @@ namespace ZL { LodLevel PlanetData::trianglesToVertices(const std::vector& geometry) { LodLevel result; + result.triangles = geometry; - result.triangles = geometry; + size_t vertexCount = geometry.size() * 3; + result.vertexData.PositionData.reserve(vertexCount); + result.vertexData.NormalData.reserve(vertexCount); + result.vertexData.TexCoordData.reserve(vertexCount); + result.vertexData.TangentData.reserve(vertexCount); // + result.vertexData.BinormalData.reserve(vertexCount); + result.VertexIDs.reserve(vertexCount); - result.vertexData.PositionData.reserve(geometry.size() * 3); - result.vertexData.NormalData.reserve(geometry.size() * 3); - result.vertexData.TexCoordData.reserve(geometry.size() * 3); // <-- - //buffer.TexCoord3Data.reserve(triangles.size() * 3); // <-- - - // UV- - // . - /*const std::array 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 triangleUVs = { - Vector2f(0.5f, 1.0f), + Vector2f(0.5f, 1.0f), Vector2f(0.0f, 0.0f), - Vector2f(1.0f, 0.0f), - + Vector2f(1.0f, 0.0f) }; - result.VertexIDs.reserve(geometry.size() * 3); // ID for (const auto& t : geometry) { + // --- ( GetRotationForTriangle) --- + Vector3f vA = t.data[0]; + Vector3f vB = t.data[1]; + Vector3f vC = t.data[2]; + + Vector3f x_axis = (vC - vB).normalized(); // U + + Vector3f edge1 = vB - vA; + Vector3f edge2 = vC - vA; + Vector3f z_axis = edge1.cross(edge2).normalized(); // + + // ( ) + Vector3f centerToTri = (vA + vB + vC).normalized(); + if (z_axis.dot(centerToTri) < 0) { + z_axis = z_axis * -1.0f; + } + + Vector3f y_axis = z_axis.cross(x_axis).normalized(); // V + for (int i = 0; i < 3; ++i) { - // PositionData result.vertexData.PositionData.push_back(t.data[i]); - - // NormalData ( = ) - result.vertexData.NormalData.push_back(t.data[i].normalized()); + result.vertexData.NormalData.push_back(z_axis); // Parallax result.vertexData.TexCoordData.push_back(triangleUVs[i]); - //result.vertexData.TexCoord2Data.push_back(triangleUVs2[i]); - // VertexIDs + // + result.vertexData.TangentData.push_back(x_axis); + result.vertexData.BinormalData.push_back(y_axis); + result.VertexIDs.push_back(t.ids[i]); } } @@ -361,14 +372,16 @@ namespace ZL { LodLevel PlanetData::generateSphere(int subdivisions, float noiseCoeff) { // 1. ID std::vector geometry = { - {{ 0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}}, // 0 - {{ 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}}, // 1 - {{ 0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}}, // 2 - {{ 0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}}, // 3 - {{ 0.0f, -1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}}, // 4 - {{ 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}}, // 5 - {{ 0.0f, -1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}}, // 6 - {{ 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}, { 1.0f, 0.0f, 0.0f}} // 7 + // (Y > 0) + {{ 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}}, // 0 + {{ 0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}, { 1.0f, 0.0f, 0.0f}}, // 1 + {{ 0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}}, // 2 + {{ 0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}}, // 3 + // (Y < 0) + {{ 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}}, // 4 + {{ 0.0f, -1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}}, // 5 + {{ 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}}, // 6 + {{ 0.0f, -1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}} // 7 }; // ID @@ -420,7 +433,7 @@ namespace ZL { Vector3f dir = lodLevel.vertexData.PositionData[i].normalized(); lodLevel.vertexData.PositionData[i] = dir * perlin.getSurfaceHeight(dir, noiseCoeff); // : NormalData (dir), - lodLevel.vertexData.NormalData[i] = dir; + //lodLevel.vertexData.NormalData[i] = dir; } diff --git a/PlanetData.h b/PlanetData.h index 75f996d..553bd3c 100644 --- a/PlanetData.h +++ b/PlanetData.h @@ -16,8 +16,8 @@ namespace ZL { VertexID generateEdgeID(const VertexID& id1, const VertexID& id2); - constexpr static int MAX_LOD_LEVELS = 6; - //constexpr static int MAX_LOD_LEVELS = 2; + //constexpr static int MAX_LOD_LEVELS = 6; + constexpr static int MAX_LOD_LEVELS = 1; struct Triangle { diff --git a/PlanetObject.cpp b/PlanetObject.cpp index 75be9cc..cb8c067 100644 --- a/PlanetObject.cpp +++ b/PlanetObject.cpp @@ -22,6 +22,7 @@ namespace ZL { // Нам нужна грань BC: от (0, 0, 20000) до (20000, 0, 0) Vector3f x_axis = (vC - vB).normalized(); + // 2. Вычисляем нормаль (ось Z). // Порядок cross product (AB x AC) определит "лицевую" сторону. Vector3f edge1 = vB - vA; @@ -72,47 +73,34 @@ namespace ZL { // Берем максимальный 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[0] = planetRenderStructCut.data.PositionData[3 * 1 + 0]; - planetRenderStructCut.data.PositionData[1] = planetRenderStructCut.data.PositionData[3 * 1 + 1]; - planetRenderStructCut.data.PositionData[2] = planetRenderStructCut.data.PositionData[3 * 1 + 2]; - */ + planetRenderStructCut.data.PositionData.resize(3); - /* - 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 m = MultMatrixMatrix(r2, r1); - - Matrix3f invr = InverseMatrix(m); - - planetRenderStructCut.data.RotateByMatrix(invr);*/ - planetRenderStructCut.RefreshVBO(); //sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/sand2.png", "")); - sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/sandx.png", "")); - stoneTexture = std::make_unique(CreateTextureDataFromPng("./resources/rockx.png", "")); + sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/sand2.png", "")); + stoneTexture = std::make_unique(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*/ }); - planetStonesRenderStruct.AssignFrom(planetStones.mesh); - planetStonesRenderStruct.RefreshVBO(); + planetStonesToBakeRenderStruct.AssignFrom(planetStones.mesh); + planetStonesToBakeRenderStruct.RefreshVBO(); } @@ -170,9 +158,12 @@ namespace ZL { planetRenderYellowStruct.RefreshVBO(); // --- ОБНОВЛЯЕМ КАМНИ (через новую структуру StoneGroup) --- - //planetStones.inflate(triangleIndicesToDraw); - // Используем AssignFrom, он внутри сам вызывает RefreshVBO - //planetStonesRenderStruct.AssignFrom(planetStones.mesh); + if (triangleIndicesToDraw.size() > 0) + { + planetStones.inflate(triangleIndicesToDraw); + // Используем AssignFrom, он внутри сам вызывает RefreshVBO + planetStonesRenderStruct.AssignFrom(planetStones.mesh); + } } } @@ -185,11 +176,13 @@ namespace ZL { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - static const std::string defaultShaderName2 = "defaultColor2"; + + 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); @@ -232,33 +225,48 @@ namespace ZL { renderer.PushProjectionMatrix( centerX - width*0.5, centerX + width * 0.5, centerY - height * 0.5, centerY + height * 0.5, - currentZNear, currentZFar); + //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", 8000.f); // Соответствует BASE_SCALE + perturbation + + + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); - + renderer.DrawVertexRenderStruct(planetRenderStructCut); - glClear(GL_DEPTH_BUFFER_BIT); + //glClear(GL_DEPTH_BUFFER_BIT); - if (planetStonesRenderStruct.data.PositionData.size() > 0) + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); // Отсекаем задние грани + if (planetStonesToBakeRenderStruct.data.PositionData.size() > 0) { glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID()); - renderer.DrawVertexRenderStruct(planetStonesRenderStruct); + renderer.DrawVertexRenderStruct(planetStonesToBakeRenderStruct); CheckGlError(); } - - + glDisable(GL_CULL_FACE); // Не забываем выключить, чтобы не сломать остальной рендер renderer.PopMatrix(); renderer.PopProjectionMatrix(); renderer.DisableVertexAttribArray(vTexCoordName); @@ -272,7 +280,6 @@ namespace ZL { prepareDrawData(); - { if (stoneMapFB == nullptr) { @@ -286,11 +293,12 @@ namespace ZL { } - bakeStoneTexture(renderer); + //bakeStoneTexture(renderer); glViewport(0, 0, Environment::width, Environment::height); //-------------------------- + drawPlanet(renderer); //drawYellowZone(renderer); //drawStones(renderer); @@ -315,6 +323,8 @@ namespace ZL { renderer.EnableVertexAttribArray(vPositionName); renderer.EnableVertexAttribArray(vColorName); renderer.EnableVertexAttribArray(vNormalName); + renderer.EnableVertexAttribArray("vTangent"); + renderer.EnableVertexAttribArray("vBinormal"); renderer.EnableVertexAttribArray(vTexCoordName); //renderer.EnableVertexAttribArray(vTexCoord3Name); @@ -330,12 +340,16 @@ namespace ZL { renderer.PushMatrix(); renderer.LoadIdentity(); - renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom }); + //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; // Вектор, направленный от источника @@ -353,31 +367,36 @@ namespace ZL { renderer.RenderUniform1f("uDistanceToPlanetSurface", dist); renderer.RenderUniform1f("uCurrentZFar", currentZFar); - renderer.RenderUniform1f("testShift1", x/500.f); - renderer.RenderUniform1f("testShift2", y / 5000.f); - + */ renderer.RenderUniform1i("Texture", 0); - renderer.RenderUniform1i("StoneMap", 1); - glActiveTexture(GL_TEXTURE1); + 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.08f); + //renderer.RenderUniform1f("uHeightScale", -0.01f); + renderer.RenderUniform1f("uHeightScale", 0.0f + x / 1000.f); + //renderer.RenderUniform1f("uHeightScale", 0.0f); glBindTexture(GL_TEXTURE_2D, stoneMapFB->getTextureID()); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); - - - renderer.DrawVertexRenderStruct(planetRenderStruct); - //glDisable(GL_BLEND); 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(); @@ -444,15 +463,10 @@ namespace ZL { renderer.RenderUniform3fv("uColor", &color2.v[0]); - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения - 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(); } diff --git a/PlanetObject.h b/PlanetObject.h index 41b3afb..1619fd1 100644 --- a/PlanetObject.h +++ b/PlanetObject.h @@ -31,6 +31,7 @@ namespace ZL { VertexRenderStruct planetRenderYellowStruct; VertexRenderStruct planetAtmosphereRenderStruct; VertexRenderStruct planetStonesRenderStruct; + VertexRenderStruct planetStonesToBakeRenderStruct; StoneGroup planetStones; std::vector triangleIndicesToDraw; diff --git a/Renderer.cpp b/Renderer.cpp index 6b4a6c9..0b335d8 100755 --- a/Renderer.cpp +++ b/Renderer.cpp @@ -713,6 +713,18 @@ namespace ZL { glDisableVertexAttribArray(shader->attribList[attribName]); } + void Renderer::RenderUniformMatrix3fv(const std::string& uniformName, bool transpose, const float* value) + { + auto shader = shaderManager.GetCurrentShader(); + + auto uniform = shader->uniformList.find(uniformName); + + if (uniform != shader->uniformList.end()) + { + glUniformMatrix3fv(uniform->second, 1, transpose, value); + } + } + void Renderer::RenderUniformMatrix4fv(const std::string& uniformName, bool transpose, const float* value) { diff --git a/Renderer.h b/Renderer.h index edc3a8e..2ea2ac4 100755 --- a/Renderer.h +++ b/Renderer.h @@ -124,6 +124,7 @@ namespace ZL { void DisableVertexAttribArray(const std::string& attribName); + void RenderUniformMatrix3fv(const std::string& uniformName, bool transpose, const float* value); void RenderUniformMatrix4fv(const std::string& uniformName, bool transpose, const float* value); void RenderUniform1i(const std::string& uniformName, const int value); void RenderUniform3fv(const std::string& uniformName, const float* value); diff --git a/StoneObject.cpp b/StoneObject.cpp index 024d4a4..da19d53 100644 --- a/StoneObject.cpp +++ b/StoneObject.cpp @@ -38,7 +38,6 @@ namespace ZL { } - // ( phi) // . // , . @@ -46,12 +45,17 @@ namespace ZL { VertexDataStruct CreateBaseConvexPolyhedron(uint64_t seed) { // --- ( ) --- - const float BASE_SCALE = 3.0f; // - //const float BASE_SCALE = 100.0f; // - const float MIN_AXIS_SCALE = 0.5f; // / + //const float BASE_SCALE = 15.0f; // + const float BASE_SCALE = 5000.0f; // + const float MIN_AXIS_SCALE = 1.0f; // / + const float MAX_AXIS_SCALE = 1.0f; // / + const float MIN_PERTURBATION = 0.0f; // + const float MAX_PERTURBATION = 0.0f; // + /*const float MIN_AXIS_SCALE = 0.5f; // / const float MAX_AXIS_SCALE = 1.5f; // / const float MIN_PERTURBATION = 0.05f; // const float MAX_PERTURBATION = 0.25f; // + */ // const size_t SUBDIVISION_LEVEL = 1; // ( , ) std::mt19937 engine(static_cast(seed)); @@ -203,7 +207,7 @@ namespace ZL { StoneGroup CreateStoneGroupData(uint64_t globalSeed, const LodLevel& planetLodLevel) { StoneGroup group; - const int STONES_PER_TRIANGLE = 100; + const int STONES_PER_TRIANGLE = 1; // LOD group.allInstances.resize(planetLodLevel.triangles.size()); @@ -216,8 +220,9 @@ namespace ZL { StoneInstance instance; instance.seed = globalSeed;// + tIdx * 1000 + i; // - instance.position = GetRandomPointOnTriangle(tri, engine); + //instance.position = GetRandomPointOnTriangle(tri, engine); + instance.position = Vector3f(5000.0f, 5000.0f, 5000.0f); // instance.scale = { getRandomFloat(engine, 0.5f, 1.5f), diff --git a/shaders/defaultColor_bake.vertex b/shaders/defaultColor_bake.vertex new file mode 100644 index 0000000..66305c6 --- /dev/null +++ b/shaders/defaultColor_bake.vertex @@ -0,0 +1,34 @@ +// Vertex Shader (Bake Stage) +attribute vec3 vPosition; +attribute vec2 vTexCoord; +attribute vec3 vNormal; // Нормаль самого камня (для освещения при запекании) + +varying vec2 TexCoord; +varying float vHeight; +varying vec3 vWorldNormal; + +// Данные о плоскости треугольника планеты +uniform vec3 uPlanePoint; // Любая вершина треугольника (например, tri.data[0]) +uniform vec3 uPlaneNormal; // Нормаль треугольника планеты (ось Z из GetRotationForTriangle) +uniform float uMaxHeight; // Максимальный размер камня (BASE_SCALE) + +uniform mat4 ProjectionModelViewMatrix; + +void main() +{ + // 1. Вычисляем вектор от плоскости до текущей вершины камня + vec3 vecToVertex = vPosition - uPlanePoint; + + // 2. Проецируем этот вектор на нормаль плоскости (скалярное произведение) + // Это и есть кратчайшее расстояние от точки до плоскости + float distance = dot(vecToVertex, uPlaneNormal); + + // 3. Нормализуем высоту для записи в текстуру (0.0 - уровень земли, 1.0 - пик) + // Clamp гарантирует, что значения не выйдут за пределы, если камень "утоплен" + vHeight = clamp(distance / uMaxHeight, 0.0, 1.0); + + TexCoord = vTexCoord; + vWorldNormal = vNormal; + + gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0); +} \ No newline at end of file diff --git a/shaders/defaultColor_bake_desktop.fragment b/shaders/defaultColor_bake_desktop.fragment new file mode 100644 index 0000000..e570a30 --- /dev/null +++ b/shaders/defaultColor_bake_desktop.fragment @@ -0,0 +1,21 @@ +// Fragment Shader (Bake Stage) +varying vec2 TexCoord; +varying float vHeight; +varying vec3 vWorldNormal; + +uniform sampler2D Texture; // Текстура камня (rock.png) +uniform vec3 uLightDir; // Направление света для базового затенения камней при запекании + +void main() +{ + vec4 stoneColor = texture2D(Texture, TexCoord); + + // Простое Lambert-освещение, чтобы камни не были "плоскими" в текстуре + //float diff = max(dot(normalize(vWorldNormal), normalize(uLightDir)), 0.3); + float diff = 1.0; + + // RGB - цвет камня с учетом света, A - нормализованная высота + //gl_FragColor = vec4(stoneColor.rgb * diff, vHeight); + gl_FragColor = vec4(vHeight, vHeight, vHeight, vHeight); + //gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0); +} \ No newline at end of file diff --git a/shaders/defaultColor_fog_stones.vertex b/shaders/defaultColor_fog_stones.vertex index 1873051..91fbfa0 100644 --- a/shaders/defaultColor_fog_stones.vertex +++ b/shaders/defaultColor_fog_stones.vertex @@ -1,18 +1,26 @@ -// Вершинный шейдер (Vertex Shader) - attribute vec3 vPosition; attribute vec2 vTexCoord; - +attribute vec3 vNormal; +attribute vec3 vTangent; // Новые атрибуты +attribute vec3 vBinormal; varying vec2 TexCoord; +varying vec3 vViewDirTangent; uniform mat4 ProjectionModelViewMatrix; +uniform vec3 uViewPos; - -void main() -{ - - gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0); - +void main() { + gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0); TexCoord = vTexCoord; + + vec3 viewDirWorld = normalize(uViewPos - vPosition); + + // Строим матрицу перехода из атрибутов + // Так как базис ортонормирован, TBN^-1 == TBN_transpose + vViewDirTangent = vec3( + dot(viewDirWorld, vTangent), + dot(viewDirWorld, vBinormal), + dot(viewDirWorld, vNormal) + ); } \ No newline at end of file diff --git a/shaders/defaultColor_fog_stones_desktop.fragment b/shaders/defaultColor_fog_stones_desktop.fragment index 12b33e4..2dd372c 100644 --- a/shaders/defaultColor_fog_stones_desktop.fragment +++ b/shaders/defaultColor_fog_stones_desktop.fragment @@ -1,24 +1,67 @@ -// 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 = 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; +varying vec3 vViewDirTangent; - gl_FragColor = vec4(finalColor, 1.0); -} \ No newline at end of file +uniform sampler2D Texture; // Нам нужен только Alpha канал (высота) +uniform float uHeightScale; + +void main() { + vec3 viewDir = normalize(vViewDirTangent); + float height = texture2D(Texture, TexCoord).a; + + // Рассчитываем вектор смещения P + //vec2 p = viewDir.xy * (height * uHeightScale) / viewDir.z; + //vec2 p = vec2(viewDir.y, -viewDir.x) * (height * uHeightScale); + //vec2 p = viewDir.xy * (height * uHeightScale); + vec2 p = vec2(viewDir.x, -viewDir.y) * (height * uHeightScale); + vec2 finalTexCoord = TexCoord + p; + + // 1. Визуализация сетки по смещенным координатам + // Если сетка кривая или ломается на стыках — значит T, B, N векторы не сошлись + vec2 grid = fract(finalTexCoord * 20.0); // 20 ячеек сетки + float line = (step(0.9, grid.x) + step(0.9, grid.y)); + + // 2. Визуализация вектора смещения через цвет + // Красный = смещение по U, Зеленый = смещение по V + vec3 offsetColor = vec3(p * 10.0 + 0.5, 0.0); // Умножаем на 10 для видимости + + vec3 finalColor = mix(offsetColor, vec3(1.0), line); // Накладываем сетку поверх цвета + + // 3. Подмешиваем карту высот, чтобы видеть "объемы" + gl_FragColor = vec4(finalColor * height, 1.0); +} + +/* +varying vec2 TexCoord; +varying vec3 vViewDirTangent; + +uniform sampler2D Texture; +uniform float uHeightScale; + +void main() { + vec3 viewDir = normalize(vViewDirTangent); + + // Получаем высоту из альфа-канала запеченной текстуры + float height = texture2D(Texture, TexCoord).a; + + // Смещение. Знак минус используется, если мы хотим "вдавить" камни + // Деление на viewDir.z помогает избежать сильных искажений под углом + vec2 p = viewDir.xy * (height * uHeightScale) / viewDir.z; + vec2 finalTexCoord = TexCoord + p; + + gl_FragColor = texture2D(Texture, finalTexCoord); +}*/ + +/* +varying vec2 TexCoord; +varying vec3 vViewDirTangent; // Тот самый вектор из VS + +void main() { + // 1. Нормализуем входящий вектор + vec3 v = normalize(vViewDirTangent); + + // 2. Преобразуем компоненты из [-1, 1] в [0, 1] для визуализации + // X -> Red, Y -> Green, Z -> Blue + vec3 debugColor = v * 0.5 + 0.5; + + gl_FragColor = vec4(debugColor, 1.0); +}*/