Ugrás a tartalomhoz

Szerkesztő:Szerkesztonev Proba/próbalap

A Wikipédiából, a szabad enciklopédiából
  1. pragma once

// C++ includes

  1. include <memory>
  2. include <random>

// GLEW

  1. include <GL/glew.h>

// SDL

  1. include <SDL.h>
  2. include <SDL_opengl.h>

// GLM

  1. include <glm/glm.hpp>
  2. include <glm/gtc/matrix_transform.hpp>
  3. include <glm/gtx/transform2.hpp>
  1. include "includes/gCamera.h"
  1. include "includes/ProgramObject.h"
  2. include "includes/BufferObject.h"
  3. include "includes/VertexArrayObject.h"
  4. include "includes/TextureObject.h"

// mesh

  1. include "includes/ObjParser_OGL3.h"

class CMyApp { public: CMyApp(); ~CMyApp();

bool Init(); void Clean();

void Update(); void Render();

void KeyboardDown(SDL_KeyboardEvent&); void KeyboardUp(SDL_KeyboardEvent&); void MouseMove(SDL_MouseMotionEvent&); void MouseDown(SDL_MouseButtonEvent&); void MouseUp(SDL_MouseButtonEvent&); void MouseWheel(SDL_MouseWheelEvent&); void Resize(int, int);

protected: // shaderekhez szükséges változók ProgramObject m_program; // mesh shader ProgramObject m_programSkybox; // skybox shader

VertexArrayObject m_CubeVao; // VAO IndexBuffer m_CubeIndices; // index buffer ArrayBuffer m_CubeVertexBuffer; // VBO VertexArrayObject m_SkyboxVao; IndexBuffer m_SkyboxIndices; ArrayBuffer m_SkyboxPos;


gCamera m_camera;

Texture2D m_woodTexture; Texture2D m_suzanneTexture; TextureCubeMap m_skyboxTexture;

struct Vertex { glm::vec3 p; glm::vec3 n; glm::vec2 t; };

// mesh adatok std::unique_ptr<Mesh> m_mesh;

// a jobb olvashatóság kedvéért void InitShaders(); void InitCube(); void InitSkyBox();

//domborzat VertexArrayObject groundVao; IndexBuffer groundIb; ArrayBuffer groundVbo;

glm::mat4 groundWorld = glm::scale(glm::vec3(20, 0.3f, 20)) * glm::translate(glm::vec3(-0.5f, 0, -0.5f));

void InitGround(); glm::vec3 Ground(float u, float v);

Texture2D grassTexture;

const int N = 20;

//háttérfák VertexArrayObject forestVao; IndexBuffer forestIb; ArrayBuffer forestVbo; Texture2D forestTexture; void InitForest();


//fa std::unique_ptr<Mesh> cylinderMesh;

VertexArrayObject sphereVao; IndexBuffer sphereIb; ArrayBuffer sphereVbo;

glm::vec3 Sphere(float u, float v);

Texture2D barkTexture; Texture2D leavesTexture; void InitTree(); void DrawTree(glm::mat4 world);

struct Tree { int x, y; glm::vec3 pos; float scale = 1.0f; Tree() {} Tree(int x, int y, glm::vec3 pos, float scale) : x(x), y(y), pos(pos), scale(scale) {} }; std::vector<Tree> trees; bool occupied[20][20];

void SimulateTrees(float deltatime); std::default_random_engine rng; glm::vec3 GridPointToWorldPos(int x, int y);


};

//------------------------------------------------------

  1. include "MyApp.h"
  1. include <math.h>
  2. include <vector>
  1. include <array>
  2. include <list>
  3. include <tuple>
  4. include <imgui/imgui.h>
  5. include "includes/GLUtils.hpp"

CMyApp::CMyApp(void) { m_camera.SetView(glm::vec3(5, 5, 5), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); m_mesh = nullptr; }

CMyApp::~CMyApp(void) { }

void CMyApp::InitCube() { //struct Vertex{ glm::vec3 position; glm::vec3 normals; glm::vec2 texture; }; std::vector<Vertex>vertices;

//front vertices.push_back({ glm::vec3(-0.5, -0.5, +0.5), glm::vec3(0, 0, 1), glm::vec2(0, 0) }); vertices.push_back({ glm::vec3(+0.5, -0.5, +0.5), glm::vec3(0, 0, 1), glm::vec2(1, 0) }); vertices.push_back({ glm::vec3(-0.5, +0.5, +0.5), glm::vec3(0, 0, 1), glm::vec2(0, 1) }); vertices.push_back({ glm::vec3(+0.5, +0.5, +0.5), glm::vec3(0, 0, 1), glm::vec2(1, 1) }); //back vertices.push_back({ glm::vec3(+0.5, -0.5, -0.5), glm::vec3(0, 0, -1), glm::vec2(0, 0) }); vertices.push_back({ glm::vec3(-0.5, -0.5, -0.5), glm::vec3(0, 0, -1), glm::vec2(1, 0) }); vertices.push_back({ glm::vec3(+0.5, +0.5, -0.5), glm::vec3(0, 0, -1), glm::vec2(0, 1) }); vertices.push_back({ glm::vec3(-0.5, +0.5, -0.5), glm::vec3(0, 0, -1), glm::vec2(1, 1) }); //right vertices.push_back({ glm::vec3(+0.5, -0.5, +0.5), glm::vec3(1, 0, 0), glm::vec2(0, 0) }); vertices.push_back({ glm::vec3(+0.5, -0.5, -0.5), glm::vec3(1, 0, 0), glm::vec2(1, 0) }); vertices.push_back({ glm::vec3(+0.5, +0.5, +0.5), glm::vec3(1, 0, 0), glm::vec2(0, 1) }); vertices.push_back({ glm::vec3(+0.5, +0.5, -0.5), glm::vec3(1, 0, 0), glm::vec2(1, 1) }); //left vertices.push_back({ glm::vec3(-0.5, -0.5, -0.5), glm::vec3(-1, 0, 0), glm::vec2(0, 0) }); vertices.push_back({ glm::vec3(-0.5, -0.5, +0.5), glm::vec3(-1, 0, 0), glm::vec2(1, 0) }); vertices.push_back({ glm::vec3(-0.5, +0.5, -0.5), glm::vec3(-1, 0, 0), glm::vec2(0, 1) }); vertices.push_back({ glm::vec3(-0.5, +0.5, +0.5), glm::vec3(-1, 0, 0), glm::vec2(1, 1) }); //top vertices.push_back({ glm::vec3(-0.5, +0.5, +0.5), glm::vec3(0, 1, 0), glm::vec2(0, 0) }); vertices.push_back({ glm::vec3(+0.5, +0.5, +0.5), glm::vec3(0, 1, 0), glm::vec2(1, 0) }); vertices.push_back({ glm::vec3(-0.5, +0.5, -0.5), glm::vec3(0, 1, 0), glm::vec2(0, 1) }); vertices.push_back({ glm::vec3(+0.5, +0.5, -0.5), glm::vec3(0, 1, 0), glm::vec2(1, 1) }); //bottom vertices.push_back({ glm::vec3(-0.5, -0.5, -0.5), glm::vec3(0, -1, 0), glm::vec2(0, 0) }); vertices.push_back({ glm::vec3(+0.5, -0.5, -0.5), glm::vec3(0, -1, 0), glm::vec2(1, 0) }); vertices.push_back({ glm::vec3(-0.5, -0.5, +0.5), glm::vec3(0, -1, 0), glm::vec2(0, 1) }); vertices.push_back({ glm::vec3(+0.5, -0.5, +0.5), glm::vec3(0, -1, 0), glm::vec2(1, 1) });

std::vector<int> indices(36); int index = 0; for (int i = 0; i < 6 * 4; i += 4) { indices[index + 0] = i + 0; indices[index + 1] = i + 1; indices[index + 2] = i + 2; indices[index + 3] = i + 1; indices[index + 4] = i + 3; indices[index + 5] = i + 2; index += 6; }

// // geometria definiálása (std::vector<...>) és GPU pufferekbe való feltöltése BufferData-val //

// vertexek pozíciói: /* Az m_CubeVertexBuffer konstruktora már létrehozott egy GPU puffer azonosítót és a most következő BufferData hívás ezt 1. bind-olni fogja GL_ARRAY_BUFFER target-re (hiszen m_CubeVertexBuffer típusa ArrayBuffer) és 2. glBufferData segítségével áttölti a GPU-ra az argumentumban adott tároló értékeit

*/

m_CubeVertexBuffer.BufferData(vertices);

// és a primitíveket alkotó csúcspontok indexei (az előző tömbökből) - triangle list-el való kirajzolásra felkészülve m_CubeIndices.BufferData(indices);

// geometria VAO-ban való regisztrálása m_CubeVao.Init( { // 0-ás attribútum "lényegében" glm::vec3-ak sorozata és az adatok az m_CubeVertexBuffer GPU pufferben vannak { CreateAttribute< 0, // attribútum: 0 glm::vec3, // CPU oldali adattípus amit a 0-ás attribútum meghatározására használtunk <- az eljárás a glm::vec3-ból kikövetkezteti, hogy 3 darab float-ból áll a 0-ás attribútum 0, // offset: az attribútum tároló elejétől vett offset-je, byte-ban sizeof(Vertex) // stride: a következő csúcspont ezen attribútuma hány byte-ra van az aktuálistól >, m_CubeVertexBuffer }, { CreateAttribute<1, glm::vec3, (sizeof(glm::vec3)), sizeof(Vertex)>, m_CubeVertexBuffer }, { CreateAttribute<2, glm::vec2, (2 * sizeof(glm::vec3)), sizeof(Vertex)>, m_CubeVertexBuffer }, }, m_CubeIndices ); }


glm::vec3 CMyApp::GetCylinderPos(float u, float v) {

float alpha = -u * 2 * M_PI; float h = v * 3.0; float r = 2.0f; return glm::vec3(cosf(alpha) * r, h, sin(alpha) * r);

} void CMyApp::InitCircle() {

Vertex vert[(N + 1) * (M + 1)]; for (int i = 0; i <= N; ++i) for (int j = 0; j <= M; ++j) { float u = i / (float)N; float v = j / (float)M;

vert[i + j * (N + 1)].p = GetCylinderPos(u, v); vert[i + j * (N + 1)].n = glm::normalize(vert[i + j * (N + 1)].p); vert[i + j * (N + 1)].t = glm::vec2(u, v); } circleVbo.BufferData(vert);

std::vector<int> indices; indices.reserve(N * M * 2 * 3);

for (int i = 1; i < N; ++i) { indices.push_back(0 + M * (N + 1)); indices.push_back(i + M * (N + 1)); indices.push_back((i + 1) + M * (N + 1)); } circleIb.BufferData(indices);

circleVao.Init( { {CreateAttribute<0,glm::vec3,0,sizeof(Vertex)>,circleVbo}, {CreateAttribute<1,glm::vec3,sizeof(glm::vec3),sizeof(Vertex)>,circleVbo}, {CreateAttribute<2,glm::vec2,sizeof(glm::vec3) * 2,sizeof(Vertex)>,circleVbo}, }, circleIb ); earthTexture.FromFile("Assets/earth.png");

}

void CMyApp::InitSkyBox() { m_SkyboxPos.BufferData( std::vector<glm::vec3>{ // hátsó lap glm::vec3(-1, -1, -1), glm::vec3(1, -1, -1), glm::vec3(1, 1, -1), glm::vec3(-1, 1, -1), // elülső lap glm::vec3(-1, -1, 1), glm::vec3(1, -1, 1), glm::vec3(1, 1, 1), glm::vec3(-1, 1, 1), } );

// és a primitíveket alkotó csúcspontok indexei (az előző tömbökből) - triangle list-el való kirajzolásra felkészülve m_SkyboxIndices.BufferData( std::vector<int>{ // hátsó lap 0, 1, 2, 2, 3, 0, // elülső lap 4, 6, 5, 6, 4, 7, // bal 0, 3, 4, 4, 3, 7, // jobb 1, 5, 2, 5, 6, 2, // alsó 1, 0, 4, 1, 4, 5, // felső 3, 2, 6, 3, 6, 7, } );

// geometria VAO-ban való regisztrálása m_SkyboxVao.Init( { { CreateAttribute<0, glm::vec3, 0, sizeof(glm::vec3)>, m_SkyboxPos }, }, m_SkyboxIndices );

// skybox texture glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);

m_skyboxTexture.AttachFromFile("assets/xpos.png", false, GL_TEXTURE_CUBE_MAP_POSITIVE_X); m_skyboxTexture.AttachFromFile("assets/xneg.png", false, GL_TEXTURE_CUBE_MAP_NEGATIVE_X); m_skyboxTexture.AttachFromFile("assets/ypos.png", false, GL_TEXTURE_CUBE_MAP_POSITIVE_Y); m_skyboxTexture.AttachFromFile("assets/yneg.png", false, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); m_skyboxTexture.AttachFromFile("assets/zpos.png", false, GL_TEXTURE_CUBE_MAP_POSITIVE_Z); m_skyboxTexture.AttachFromFile("assets/zneg.png", true, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);

// a GL_TEXTURE_MAG_FILTER-t és a GL_TEXTURE_MIN_FILTER-t beállítja az AttachFromFile glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

glBindTexture(GL_TEXTURE_CUBE_MAP, 0); }

void CMyApp::InitShaders() { // a shadereket tároló program létrehozása az OpenGL-hez hasonló módon: m_program.AttachShaders({ { GL_VERTEX_SHADER, "myVert.vert"}, { GL_FRAGMENT_SHADER, "myFrag.frag"} });

// attributomok osszerendelese a VAO es shader kozt m_program.BindAttribLocations({ { 0, "vs_in_pos" }, // VAO 0-as csatorna menjen a vs_in_pos-ba { 1, "vs_in_norm" }, // VAO 1-es csatorna menjen a vs_in_norm-ba { 2, "vs_in_tex" }, // VAO 2-es csatorna menjen a vs_in_tex-be });

m_program.LinkProgram();

// shader program rövid létrehozása, egyetlen függvényhívással a fenti három: m_programSkybox.Init( { { GL_VERTEX_SHADER, "skybox.vert" }, { GL_FRAGMENT_SHADER, "skybox.frag" } }, { { 0, "vs_in_pos" }, // VAO 0-as csatorna menjen a vs_in_pos-ba } ); }

bool CMyApp::Init() { // törlési szín legyen kékes glClearColor(0.125f, 0.25f, 0.5f, 1.0f);

glEnable(GL_CULL_FACE); // kapcsoljuk be a hatrafele nezo lapok eldobasat glEnable(GL_DEPTH_TEST); // mélységi teszt bekapcsolása (takarás)

InitShaders(); InitCube(); InitSkyBox(); InitCircle();

// egyéb textúrák betöltése m_woodTexture.FromFile("assets/wood.jpg"); m_suzanneTexture.FromFile("assets/marron.jpg");

// mesh betöltése m_mesh = std::unique_ptr<Mesh>(ObjParser::parse("assets/Suzanne.obj")); m_mesh->initBuffers();

// kamera m_camera.SetProj(glm::radians(60.0f), 640.0f / 480.0f, 0.01f, 1000.0f);

return true; }

void CMyApp::Clean() { }

void CMyApp::Update() { static Uint32 last_time = SDL_GetTicks(); float delta_time = (SDL_GetTicks() - last_time) / 1000.0f;

m_camera.Update(delta_time);

last_time = SDL_GetTicks(); }

void CMyApp::Render() { // töröljük a frampuffert (GL_COLOR_BUFFER_BIT) és a mélységi Z puffert (GL_DEPTH_BUFFER_BIT) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glm::mat4 viewProj = m_camera.GetViewProj();


// fold glm::mat4 circleWorld = glm::mat4(1.0f); circleVao.Bind(); m_program.Use(); m_program.SetTexture("texImage", 0, earthTexture); m_program.SetUniform("MVP", viewProj * circleWorld); m_program.SetUniform("world", circleWorld); m_program.SetUniform("worldIT", glm::inverse(glm::transpose(circleWorld))); glDrawElements(GL_TRIANGLES, 3 * 2 * (N) * (M), GL_UNSIGNED_INT, nullptr);


//Suzanne glm::mat4 suzanneWorld = glm::mat4(1.0f); m_program.Use(); m_program.SetTexture("texImage", 0, m_suzanneTexture); m_program.SetUniform("MVP", viewProj * suzanneWorld); m_program.SetUniform("world", suzanneWorld); m_program.SetUniform("worldIT", glm::inverse(glm::transpose(suzanneWorld))); //m_mesh->draw();

// kockák //m_program.Use(); nem hívjuk meg újra, hisz ugyanazt a shadert használják m_CubeVao.Bind(); m_program.SetTexture("texImage", 0, m_woodTexture); glm::mat4 cubeWorld;

float time = SDL_GetTicks() / 1000.0f * 2 * float(M_PI) / 10; for (int i = 0; i < 10; ++i) { cubeWorld = glm::rotate(time + 2 * glm::pi<float>() / 10 * i, glm::vec3(0, 1, 0))* glm::translate(glm::vec3(10 + 5 * sin(time), 0, 0))* glm::rotate((i + 1)*time, glm::vec3(0, 1, 0)); m_program.SetUniform("MVP", viewProj * cubeWorld); m_program.SetUniform("world", cubeWorld); m_program.SetUniform("worldIT", glm::inverse(glm::transpose(cubeWorld))); glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr); } m_program.Unuse();

// skybox // mentsük el az előző Z-test eredményt, azaz azt a relációt, ami alapján update-eljük a pixelt. GLint prevDepthFnc; glGetIntegerv(GL_DEPTH_FUNC, &prevDepthFnc);

// most kisebb-egyenlőt használjunk, mert mindent kitolunk a távoli vágósíkokra glDepthFunc(GL_LEQUAL);

m_SkyboxVao.Bind(); m_programSkybox.Use(); m_programSkybox.SetUniform("MVP", viewProj * glm::translate( m_camera.GetEye()) );

// cube map textúra beállítása 0-ás mintavételezőre és annak a shaderre beállítása glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, m_skyboxTexture); glUniform1i(m_programSkybox.GetLocation("skyboxTexture"), 0); // az előző három sor <=> m_programSkybox.SetCubeTexture("skyboxTexture", 0, m_skyboxTexture);

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr); m_programSkybox.Unuse();

// végül állítsuk vissza glDepthFunc(prevDepthFnc);


// 1. feladat: készíts egy vertex shader-fragment shader párt, ami tárolt geometria _nélkül_ kirajzol egy tetszőleges pozícióba egy XYZ tengely-hármast, // ahol az X piros, az Y zöld a Z pedig kék!

//ImGui Testwindow ImGui::ShowTestWindow(); }

void CMyApp::KeyboardDown(SDL_KeyboardEvent& key) { m_camera.KeyboardDown(key); }

void CMyApp::KeyboardUp(SDL_KeyboardEvent& key) { m_camera.KeyboardUp(key); }

void CMyApp::MouseMove(SDL_MouseMotionEvent& mouse) { m_camera.MouseMove(mouse); }

void CMyApp::MouseDown(SDL_MouseButtonEvent& mouse) { }

void CMyApp::MouseUp(SDL_MouseButtonEvent& mouse) { }

void CMyApp::MouseWheel(SDL_MouseWheelEvent& wheel) { }

// a két paraméterbe az új ablakméret szélessége (_w) és magassága (_h) található void CMyApp::Resize(int _w, int _h) { glViewport(0, 0, _w, _h );

m_camera.Resize(_w, _h); }