123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- #include "Game.h"
- #include "LayeredFramebuffer.h"
- #include "Texture3D.h"
- #include "math/Frustum.h"
- #include "rendering/FileTexture.h"
- #include "rendering/Framebuffer.h"
- #include "rendering/Shader.h"
- #include "rendering/VertexBuffer.h"
- #include "rendering/Window.h"
- #include "utils/Array.h"
- #include "utils/List.h"
- #include "utils/Random.h"
- #include "utils/Utils.h"
- #include "wrapper/GL.h"
- static constexpr float STEP = 1.0f / 31.5f;
- static Window window;
- static Shader cubeShader;
- static Shader noiseShader;
- static Shader particleShader;
- static Shader backgroundShader;
- static Shader blurShader;
- static Framebuffer<1> shadowBuffer;
- static Framebuffer<1> blurShadowBuffer;
- static LayeredFramebuffer noiceBuffer;
- static FileTexture bricks;
- static FileTexture bricksBump;
- static FileTexture bricksNormal;
- static VertexBuffer rectangleBuffer;
- static VertexBuffer emptyBuffer;
- static Frustum frustum{60.0f, 0.1f, 1000.0f, window.getSize()};
- static Matrix projection;
- static Matrix view;
- static Matrix shadowView;
- static Matrix shadowProjectionView;
- static Matrix model;
- static Button up{GLFW_KEY_SPACE, "Up"};
- static Button down{GLFW_KEY_LEFT_SHIFT, "Down"};
- static Button left{GLFW_KEY_A, "left"};
- static Button right{GLFW_KEY_D, "right"};
- static Button front{GLFW_KEY_W, "front"};
- static Button back{GLFW_KEY_S, "back"};
- static Button toggle{GLFW_KEY_T, "toggle"};
- static Button scaleUp{GLFW_KEY_G, "scale up"};
- static Button scaleDown{GLFW_KEY_H, "scale down"};
- static Button stepsUp{GLFW_KEY_Y, "steps up"};
- static Button stepsDown{GLFW_KEY_U, "steps down"};
- static Button fineStepsUp{GLFW_KEY_I, "fine steps up"};
- static Button fineStepsDown{GLFW_KEY_O, "fine steps down"};
- static Button modeToggle{GLFW_KEY_C, "mode toggle"};
- static Button primaryMouse{GLFW_MOUSE_BUTTON_1, "primary click"};
- static Button timeUp{GLFW_KEY_N, "time up"};
- static Button timeDown{GLFW_KEY_M, "time down"};
- static Vector3 oldPosition;
- static Vector3 position{-32.0f, 0.0f, -120.0f};
- static float oldHeight = 0.0f;
- static float height = 0.0f;
- static float heightScale = 0.01f;
- static int steps = 1;
- static int fineSteps = 1;
- static bool mode = false;
- static float timeTicks = 0.0f;
- static Vector3 emitterPos;
- static float emitterAge = 999999.0f;
- static float timeFactor = 1.0f;
- static void tickTimeFactors() {
- if(timeUp.isDown()) {
- timeFactor *= 1.05f;
- }
- if(timeDown.isDown()) {
- timeFactor /= 1.05f;
- }
- timeTicks++;
- }
- static void tickMovement() {
- oldHeight = height;
- oldPosition = position;
- if(up.isDown()) {
- height += 1.0f;
- }
- if(down.isDown()) {
- height -= 1.0f;
- }
- constexpr float speed = 3.5f;
- if(left.isDown()) {
- position += Vector3(speed, 0.0f, 0.0f);
- }
- if(right.isDown()) {
- position -= Vector3(speed, 0.0f, 0.0f);
- }
- if(front.isDown()) {
- position += Vector3(0.0f, 0.0f, speed);
- }
- if(back.isDown()) {
- position -= Vector3(0.0f, 0.0f, speed);
- }
- }
- static void tickParallaxSettings() {
- if(scaleUp.isDown()) {
- heightScale += 0.005f;
- }
- if(scaleDown.isDown()) {
- heightScale -= 0.005f;
- if(heightScale < 0.0f) {
- heightScale = 0.0f;
- }
- }
- if(stepsUp.wasReleased()) {
- steps++;
- }
- if(stepsDown.wasReleased() && steps > 1) {
- steps--;
- }
- if(fineStepsUp.wasReleased()) {
- fineSteps++;
- }
- if(fineStepsDown.wasReleased() && fineSteps > 1) {
- fineSteps--;
- }
- if(modeToggle.wasReleased()) {
- mode = !mode;
- }
- }
- static void tickGame() {
- tickTimeFactors();
- tickMovement();
- tickParallaxSettings();
- }
- static void prepareMatrices(float lag) {
- projection = frustum.updateProjection();
- view.translateTo(Vector3(0.0f, 0.0f, 0.0f));
- view.translate(Utils::interpolate(oldPosition, position, lag));
- float h = -32.0f + (oldHeight - height) * lag;
- view.translateY(h);
- shadowView.translateTo(Vector3(-32.0f - 180.0f, h, -340.0f));
- shadowProjectionView.translateTo(Vector3(0.0f, 0.0f, 0.0f));
- shadowProjectionView.scale(0.5f);
- shadowProjectionView.translate(Vector3(0.5f, 0.5f, 0.5f));
- shadowProjectionView *= projection;
- shadowProjectionView *= shadowView;
- }
- static void renderNoise() {
- GL::setViewport(64, 64);
- noiseShader.use();
- noiceBuffer.bindAndClear();
- noiseShader.setFloat("height", oldHeight * STEP);
- for(int i = 0; i < 64; i++) {
- noiseShader.setFloat("layer", i * STEP - 1.0f);
- noiceBuffer.bindLayer(i);
- rectangleBuffer.draw(6);
- }
- }
- static void renderCubes(Matrix& view) {
- GL::setViewport(window.getSize().width, window.getSize().height);
- cubeShader.use();
- cubeShader.setMatrix("proj", projection.getValues());
- cubeShader.setMatrix("view", view.getValues());
- cubeShader.setMatrix("shadow", shadowProjectionView.getValues());
- cubeShader.setFloat("height", oldHeight * STEP * 0.5f);
- cubeShader.setVector("viewPos", -position + Vector3(0.0f, 32.0f, 0.0f));
- cubeShader.setVector("lightPos", Vector3());
- cubeShader.setFloat("heightScale", heightScale);
- cubeShader.setInt("steps", steps);
- cubeShader.setInt("fineSteps", fineSteps);
- cubeShader.setInt("kajetan", mode);
- if(toggle.isDown()) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- }
- noiceBuffer.bindTextureTo(0);
- bricks.bindTo(1);
- bricksBump.bindTo(2);
- bricksNormal.bindTo(3);
- blurShadowBuffer.bindTextureTo(0, 4);
- shadowBuffer.bindTextureTo(0, 5);
- for(int i = 0; i < 3; i++) {
- model.translateTo(Vector3(80.0f * i, 0.0f, 0.0f));
- cubeShader.setMatrix("model", model.getValues());
- emptyBuffer.drawPoints(64 * 64 * 64);
- }
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
- static void pickParticleCenter() {
- if(!primaryMouse.wasReleased()) {
- return;
- }
- noiceBuffer.bindTextureTo(0);
- static float buffer[64][64][64];
- glGetTexImage(GL_TEXTURE_3D, 0, GL_RED, GL_FLOAT, buffer);
- float hWidth = window.getSize().width * 0.5f;
- float hHeight = window.getSize().height * 0.5f;
- float x = (window.buttons.getMouseX() - hWidth) / hWidth;
- float y = -(window.buttons.getMouseY() - hHeight) / hHeight;
- float aspect = hWidth / hHeight;
- float tan = tanf((0.5f * frustum.fieldOfView) * M_PI / 180.0f);
- float q = 1.0f / tan;
- Vector3 direction(x / (q / aspect), y / q, 1.0f);
- direction[2] = -direction[2];
- direction.normalize();
- Vector3 pos = -position;
- pos[1] = 32.0f;
- pos[1] = 32.0f;
- for(int i = 0; i < 150; i++) {
- int x = pos[0] + 0.5f;
- int y = pos[1] + 0.5f;
- int z = pos[2] + 0.5f;
- if(x >= 0 && x < 64 && y >= 0 && y < 64 && z >= 0 && z < 64 &&
- buffer[x][y][z] > 0.5f) {
- emitterPos = pos + Vector3(0.0f, height, 0.0f);
- emitterAge = timeTicks;
- break;
- }
- pos += direction;
- }
- }
- static void renderParticles(float lag) {
- glPointSize(5.0f);
- particleShader.use();
- particleShader.setMatrix("proj", projection.getValues());
- Matrix m;
- m.translateTo(Utils::interpolate(oldPosition, position, lag));
- m.translateY(-32.0f - (oldHeight + (height - oldHeight) * lag));
- particleShader.setMatrix("view", m.getValues());
- particleShader.setFloat("time", timeTicks + lag);
- GL::enableBlending();
- glDepthMask(false);
- pickParticleCenter();
- particleShader.setFloat("timeFactor", timeFactor);
- particleShader.setVector("position", emitterPos);
- particleShader.setFloat("age", emitterAge);
- particleShader.setVector("color", Vector4(1.0f, 0.0f, 0.0f, 1.0f));
- particleShader.setInt("seedBase", 0);
- emptyBuffer.drawPoints(2000000);
- particleShader.setVector("position", emitterPos);
- particleShader.setFloat("age", emitterAge + 5);
- particleShader.setVector("color", Vector4(0.0f, 1.0f, 0.0f, 1.0f));
- particleShader.setInt("seedBase", 1);
- emptyBuffer.drawPoints(10000);
- particleShader.setVector("position", emitterPos);
- particleShader.setFloat("age", emitterAge + 10);
- particleShader.setVector("color", Vector4(0.0f, 0.0f, 1.0f, 1.0f));
- particleShader.setInt("seedBase", 2);
- emptyBuffer.drawPoints(5000);
- particleShader.setVector("position", emitterPos);
- particleShader.setFloat("age", emitterAge + 20);
- particleShader.setVector("color", Vector4(0.0f, 1.0f, 1.0f, 1.0f));
- particleShader.setInt("seedBase", 2);
- emptyBuffer.drawPoints(5000);
- glDepthMask(true);
- GL::disableBlending();
- }
- static void renderBackground(Matrix& view) {
- backgroundShader.use();
- blurShadowBuffer.bindTextureTo(0, 0);
- backgroundShader.setMatrix("proj", frustum.updateProjection().getValues());
- backgroundShader.setMatrix("view", view.getValues());
- model.translateTo(Vector3(0.0f, 0.0f, 0.0f));
- model.scale(Vector3(260.0f, 120.0f, 1.0f));
- model.translate(Vector3(0.0f, 20.0f, -200.0f));
- model.rotateX(-5.0f);
- backgroundShader.setMatrix("model", model.getValues());
- backgroundShader.setMatrix("shadow", shadowProjectionView.getValues());
- rectangleBuffer.draw(6);
- }
- static void renderGame(float lag) {
- GL::enableDepthTesting();
- prepareMatrices(lag);
- renderNoise();
- shadowBuffer.bindAndClear();
- renderCubes(shadowView);
- renderBackground(shadowView);
- blurShader.use();
- shadowBuffer.bindTextureTo(0, 0);
- blurShadowBuffer.bindAndClear();
- rectangleBuffer.draw(6);
- GL::bindMainFramebuffer();
- GL::clear();
- renderCubes(view);
- renderBackground(view);
- renderParticles(lag);
- }
- void Game::init() {
- WindowOptions options(4, 0, {1024, 620}, false, "test");
- Error error = window.open(options);
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = cubeShader.compile("resources/cubes.vs", "resources/cubes.gs",
- "resources/cubes.fs");
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = noiseShader.compile("resources/noise.vs", nullptr,
- "resources/noise.fs");
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = particleShader.compile("resources/particles.vs",
- "resources/particles.gs",
- "resources/particles.fs");
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = backgroundShader.compile("resources/background.vs", nullptr,
- "resources/background.fs");
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error =
- blurShader.compile("resources/blur.vs", nullptr, "resources/blur.fs");
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = shadowBuffer.init(window.getSize(), TextureFormat::depth32(true));
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = blurShadowBuffer.init(window.getSize(),
- TextureFormat::float32(2, true));
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = bricks.load("resources/bricks.png", 0);
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = bricksBump.load("resources/bricks_bump.png", 0);
- if(error.has()) {
- error.message.printLine();
- return;
- }
- error = bricksNormal.load("resources/bricks_normal.png", 0);
- if(error.has()) {
- error.message.printLine();
- return;
- }
- noiceBuffer.init(64, 64, 64);
- window.buttons.add(up);
- window.buttons.add(down);
- window.buttons.add(left);
- window.buttons.add(right);
- window.buttons.add(front);
- window.buttons.add(back);
- window.buttons.add(toggle);
- window.buttons.add(scaleUp);
- window.buttons.add(scaleDown);
- window.buttons.add(stepsUp);
- window.buttons.add(stepsDown);
- window.buttons.add(fineStepsUp);
- window.buttons.add(fineStepsDown);
- window.buttons.add(modeToggle);
- window.buttons.add(timeUp);
- window.buttons.add(timeDown);
- window.buttons.addMouse(primaryMouse);
- bricks.setLinearFilter();
- bricksBump.setLinearFilter();
- bricksNormal.setLinearFilter();
- rectangleBuffer.init(Attributes().addFloat(2));
- float recData[6][2] = {{-1.0f, -1.0f}, {-1.0, 1.0}, {1.0, -1.0},
- {1.0f, 1.0f}, {-1.0, 1.0}, {1.0, -1.0}};
- rectangleBuffer.setStaticData(sizeof(recData), recData);
- emptyBuffer.init(Attributes());
- struct Intern {
- void tick() {
- tickGame();
- }
- void render(float lag) {
- renderGame(lag);
- }
- bool isRunning() const {
- return true;
- }
- };
- Intern intern;
- window.run(intern, 50'000'000);
- }
|