diff --git a/CMakeLists.txt b/CMakeLists.txt index 245b226..7d7931e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,8 @@ add_executable(Dicewars_Siedler src/main.cpp src/engine/renderer/MasterRenderer.h src/engine/renderer/TerrainRenderer.cpp src/engine/renderer/TerrainRenderer.h + src/engine/renderer/shaders/TerrainShader.cpp + src/engine/renderer/shaders/TerrainShader.h ) target_include_directories(Dicewars_Siedler PRIVATE diff --git a/assets/shaders/terrainFragmentShader.glsl b/assets/shaders/terrainFragmentShader.glsl new file mode 100644 index 0000000..b213bd0 --- /dev/null +++ b/assets/shaders/terrainFragmentShader.glsl @@ -0,0 +1,28 @@ +#version 400 core + +in vec2 pass_textureCoords; +in vec3 surfaceNormal; +in vec3 toLightVector; + +out vec4 outColor; + +uniform sampler2D textureSampler; +uniform vec3 lightColor; + +uniform bool isHighlighted; + +void main(void) { + vec3 unitNormal = normalize(surfaceNormal); + vec3 unitToLightDir = normalize(toLightVector); + + float cosTheta = dot(unitNormal, unitToLightDir); + float brightness = max(cosTheta, 0.2); + vec3 diffuse = brightness * lightColor; + + if(isHighlighted) { + outColor = vec4(1.0f, 1.0f, 0.0f, 1.0f); + } else { + outColor = vec4(diffuse, 1.0f) * texture(textureSampler, pass_textureCoords); + } + +} \ No newline at end of file diff --git a/assets/shaders/terrainVertexShader.glsl b/assets/shaders/terrainVertexShader.glsl new file mode 100644 index 0000000..02ffb90 --- /dev/null +++ b/assets/shaders/terrainVertexShader.glsl @@ -0,0 +1,23 @@ +#version 400 core + +in vec3 position; +in vec2 textureCoords; +in vec3 normal; + +out vec2 pass_textureCoords; +out vec3 surfaceNormal; +out vec3 toLightVector; + +uniform mat4 transformationMatrix; +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; +uniform vec3 lightPosition; + +void main() { + vec4 worldPosition = transformationMatrix * vec4(position, 1.0f); + gl_Position = projectionMatrix * viewMatrix * worldPosition; + pass_textureCoords = textureCoords; + + surfaceNormal = (transformationMatrix * vec4(normal, 0.0f)).xyz; + toLightVector = lightPosition - worldPosition.xyz; +} diff --git a/src/engine/platform/glfw/MousePicker.cpp b/src/engine/platform/glfw/MousePicker.cpp index d4f11f1..b5f11a5 100644 --- a/src/engine/platform/glfw/MousePicker.cpp +++ b/src/engine/platform/glfw/MousePicker.cpp @@ -26,7 +26,7 @@ glm::vec3 MousePicker::calculateMouseRay() { glm::vec2 MousePicker::getNormalizedDeviceCoords(float mouseX, float mouseY) { float x = (2.f * mouseX) / static_cast(Application::getInstance().getWindow().GetWidth()) - 1.f; - float y = (2.f * mouseY) / static_cast(Application::getInstance().getWindow().GetHeight()) - 1.f; + float y = 1.f - (2.f * mouseY) / static_cast(Application::getInstance().getWindow().GetHeight()); return {x, y}; } diff --git a/src/engine/renderer/TerrainRenderer.cpp b/src/engine/renderer/TerrainRenderer.cpp index c269856..a477b7d 100644 --- a/src/engine/renderer/TerrainRenderer.cpp +++ b/src/engine/renderer/TerrainRenderer.cpp @@ -8,9 +8,9 @@ void TerrainRenderer::prepare(const Camera &camera, const Light &light) { const glm::mat4 viewMatrix = MathUtils::createViewMatrix(camera); - staticShader.start(); - staticShader.loadLight(light.getPosition(), light.getColor()); - staticShader.loadViewMatrix(viewMatrix); + terrainShader.start(); + terrainShader.loadLight(light.getPosition(), light.getColor()); + terrainShader.loadViewMatrix(viewMatrix); } void TerrainRenderer::renderTerrainTiles(const std::unordered_map> &terrainTiles) { @@ -26,7 +26,7 @@ void TerrainRenderer::renderTerrainTiles(const std::unordered_map>& terrainTiles); void finalizeFrame(); private: - StaticShader staticShader; + TerrainShader terrainShader; void prepareTexturedModel(const TexturedModel &texturedModel); void unbindTexturedModel(); diff --git a/src/engine/renderer/shaders/ShaderProgram.cpp b/src/engine/renderer/shaders/ShaderProgram.cpp index b3ffa0a..5a351b3 100644 --- a/src/engine/renderer/shaders/ShaderProgram.cpp +++ b/src/engine/renderer/shaders/ShaderProgram.cpp @@ -57,7 +57,7 @@ void ShaderProgram::loadVector(const int location, const glm::vec3 vector) { } void ShaderProgram::loadBoolean(int location, bool value) { - glUniform1f(location, value ? 1.f: 0.f); + glUniform1i(location, value ? 1: 0); } void ShaderProgram::loadMatrix(int location, glm::mat4 matrix) { diff --git a/src/engine/renderer/shaders/TerrainShader.cpp b/src/engine/renderer/shaders/TerrainShader.cpp new file mode 100644 index 0000000..277318f --- /dev/null +++ b/src/engine/renderer/shaders/TerrainShader.cpp @@ -0,0 +1,50 @@ +// +// Created by sebastian on 08.02.26. +// + +#include "TerrainShader.h" + +TerrainShader::TerrainShader(): ShaderProgram(VERTEX_FILE, FRAGMENT_FILE) { + TerrainShader::bindAttributes(); + TerrainShader::getAllUniformLocations(); +} + +void TerrainShader::loadTransformationMatrix(glm::mat4 matrix) { + loadMatrix(location_transformationMatrix, matrix); +} + +void TerrainShader::loadProjectionMatrix(glm::mat4 matrix) { + loadMatrix(location_projectionMatrix, matrix); +} + +void TerrainShader::loadViewMatrix(glm::mat4 matrix) { + loadMatrix(location_viewMatrix, matrix); +} + +void TerrainShader::loadLight(glm::vec3 position, glm::vec3 color) { + loadVector(location_lightPosition, position); + loadVector(location_lightColor, color); +} + +void TerrainShader::loadIsHighlighted(bool isHighlighted) { + loadBoolean(location_isHighlighted, isHighlighted); +} + + +void TerrainShader::bindAttributes() const { + bindAttribute(0, "position"); + bindAttribute(1, "textureCoords"); + bindAttribute(2, "normal"); +} + +void TerrainShader::getAllUniformLocations() { + location_transformationMatrix = getUniformLocation("transformationMatrix"); + location_projectionMatrix = getUniformLocation("projectionMatrix"); + location_viewMatrix = getUniformLocation("viewMatrix"); + location_lightPosition = getUniformLocation("lightPosition"); + location_lightColor = getUniformLocation("lightColor"); + + location_isHighlighted = getUniformLocation("isHighlighted"); +} + + diff --git a/src/engine/renderer/shaders/TerrainShader.h b/src/engine/renderer/shaders/TerrainShader.h new file mode 100644 index 0000000..dd5bd39 --- /dev/null +++ b/src/engine/renderer/shaders/TerrainShader.h @@ -0,0 +1,37 @@ +// +// Created by sebastian on 08.02.26. +// + +#ifndef TERRAINSHADER_H +#define TERRAINSHADER_H +#include "ShaderProgram.h" + + +class TerrainShader : public ShaderProgram { +public: + TerrainShader(); + void loadTransformationMatrix(glm::mat4 matrix); + void loadProjectionMatrix(glm::mat4 matrix); + void loadViewMatrix(glm::mat4 matrix); + void loadLight(glm::vec3 position, glm::vec3 color); + void loadIsHighlighted(bool isHighlighted); +private: + inline static const std::string VERTEX_FILE = "assets/shaders/terrainVertexShader.glsl"; + inline static const std::string FRAGMENT_FILE = "assets/shaders/terrainFragmentShader.glsl"; + + int location_transformationMatrix; + int location_projectionMatrix; + int location_viewMatrix; + int location_lightPosition; + int location_lightColor; + + int location_isHighlighted; + +protected: + void bindAttributes() const override; + void getAllUniformLocations() override; +}; + + + +#endif //TERRAINSHADER_H diff --git a/src/game/GameLayer.cpp b/src/game/GameLayer.cpp index aee575c..f3cbd0d 100644 --- a/src/game/GameLayer.cpp +++ b/src/game/GameLayer.cpp @@ -54,6 +54,13 @@ void GameLayer::onUpdate() camera->move(moveDir, 0.5f); renderer->submitEntity(entity.get()); + + for (HexTile& tile : map->tiles) { + glm::vec3 intersectionPoint; + bool highlight = tile.intersect(camera->getPosition(), mousePicker->getCurrentRay(), intersectionPoint); + tile.isHighlighted = highlight; + } + std::vector terrainRenderData = map->getTerrainRenderData(hexModel); diff --git a/src/game/hexWorld/HexTile.h b/src/game/hexWorld/HexTile.h index 8cfe655..958b1fe 100644 --- a/src/game/hexWorld/HexTile.h +++ b/src/game/hexWorld/HexTile.h @@ -7,13 +7,27 @@ #include #include "../../engine/renderer/model/TexturedModel.h" +#include "glm/vec2.hpp" #include "glm/vec3.hpp" +#include "glm/ext/quaternion_geometric.hpp" struct HexTile { glm::vec3 worldPos; int q, r; //Axiale Koordinaten (hex-Koordinaten) int ownerID = -1; //Later: ResourceType + float radius; + bool isHighlighted = false; + + bool intersect(const glm::vec3& rayOrigin, const glm::vec3& rayDirection, glm::vec3& intersectionPoint) const { + float t = -rayOrigin.y / rayDirection.y; + if (t < 0) return false; // Ray zeigt nach oben, nicht getroffen + + intersectionPoint = rayOrigin + t * rayDirection; + + glm::vec2 diff(intersectionPoint.x - worldPos.x, intersectionPoint.z - worldPos.z); + return glm::length(diff) <= radius -0.1f; + } }; struct HexRenderData { diff --git a/src/game/hexWorld/Map.cpp b/src/game/hexWorld/Map.cpp index 2891798..1e8080d 100644 --- a/src/game/hexWorld/Map.cpp +++ b/src/game/hexWorld/Map.cpp @@ -8,7 +8,7 @@ std::vector Map::getTerrainRenderData(const std::shared_ptr renderData; renderData.reserve(tiles.size()); for (auto& tile : tiles) { - HexRenderData data = HexRenderData(hexModel, tile.worldPos, false); + HexRenderData data = HexRenderData(hexModel, tile.worldPos, tile.isHighlighted); renderData.push_back(data); } return renderData; diff --git a/src/game/hexWorld/MapGenerator.h b/src/game/hexWorld/MapGenerator.h index b1d9643..4ef028d 100644 --- a/src/game/hexWorld/MapGenerator.h +++ b/src/game/hexWorld/MapGenerator.h @@ -27,6 +27,7 @@ public: float x = xOffset * (q + 0.5f * (r % 2)); float z = zOffset * r; tile.worldPos = glm::vec3(x, 0.0f, z); + tile.radius = hexRadius; map.tiles.push_back(tile); }