#include #include #include #include "libs/cglm/cglm.h" #include "libs/glad/include/glad/glad.h" #include // #include // #include "stb_image.h" // #include // #include #include "lib.h" //Screen dimension constants const int SCREEN_WIDTH = 1024; const int SCREEN_HEIGHT = 768; int main(void) { SDL_Window *window = NULL; if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("error initializing SDL: %s\n", SDL_GetError()); return 1; } SDL_GL_LoadLibrary(NULL); // Request an OpenGL 4.5 context (should be core) SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); // Also request a depth buffer SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); window = SDL_CreateWindow("Terrain", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL ); if (window == NULL) { printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() ); return 1; } SDL_GL_CreateContext(window); gladLoadGLLoader(SDL_GL_GetProcAddress); printf("Vendor: %s\n", glGetString(GL_VENDOR)); printf("Renderer: %s\n", glGetString(GL_RENDERER)); printf("Version: %s\n", glGetString(GL_VERSION)); SDL_GL_SetSwapInterval(1); // int w, h, c; // unsigned char *terrain_img = stbi_load("terrain.png", &w, &h, &c, 0); int w = 3; int h = 3; int vcount = w * h * 3; // float scale_y = 1.0f; // float shift_y = 16.0f; // for (int row = 0; row < h; row++) { // for (int col = 0; col < w; col++) { // unsigned char *texel = terrain_img + (row * w + col) * c; // unsigned char y = texel[0]; // float *v = &verts[(row * w + col) * 3]; // *(v+0) = -w/2 + col; // *(v+1) = y * scale_y + shift_y; // *(v+2) = -h/2 + row; // } // } // float *verts = malloc(vcount * sizeof(float)); // float terrainVerts[vcount]; float terrainVerts[] = { 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 2.f, 0.f, 0.f, 3.f, 0.f, 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 0.f, 2.f, 1.f, 0.f, 3.f, 1.f, 0.f, 0.f, 2.f, 0.f, 1.f, 2.f, 0.f, 2.f, 2.f, 0.f, 3.f, 2.f, 0.f, 0.f, 3.f, 0.f, 1.f, 3.f, 0.f, 2.f, 3.f, 0.f, 3.f, 3.f, 0.f, }; // for (int row = 1; row < h / 2; row += 2) { // for (int col = 0; col < w; col++) { // int idx1 = ((row-1) * w + col); // int idx2 = (row * w + col); // terrainVerts[idx1*3+0] = (float)row-1; // terrainVerts[idx1*3+1] = (float)col; // terrainVerts[idx1*3+2] = 0.0f; // terrainVerts[idx1*3+3] = (float)row; // terrainVerts[idx1*3+4] = (float)col; // terrainVerts[idx1*3+5] = 0.0f; // } // } // unsigned int terrainIndices[w*(h-1)*2]; // int i = 0; // for (int row = 0; row < h-1; row++) { // for (int col = 0; col < w; col++) { // terrainIndices[i++] = row * w + col; // terrainIndices[i++] = (row+1) * w + (w+1); // // printf("1 %d 2 %d\n", idx1, idx2); // } // } unsigned int terrainIndices[] = { 0,4,1,5,2,6,3,7,7, 4,4,8,5,9,6,10,7,11,11 }; // = { // 0, 1, 3, // first triangle // 1, 2, 3 // second triangle // }; printf("Loaded %d vertices\n", w * h); // stbi_image_free(terrain_img); // const unsigned int NUM_STRIPS = h - 1; // const unsigned int NUM_VERTS_PER_STRIP = w * 2; unsigned int terrainVAO, terrainVBO, terrainIBO; glGenVertexArrays(1, &terrainVAO); glBindVertexArray(terrainVAO); glGenBuffers(1, &terrainVBO); glBindBuffer(GL_ARRAY_BUFFER, terrainVBO); // glBufferData(GL_ARRAY_BUFFER, vcount * sizeof(float), verts, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(terrainVerts), terrainVerts, GL_STATIC_DRAW); // position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glGenBuffers(1, &terrainIBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, terrainIBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(terrainIndices), terrainIndices, GL_STATIC_DRAW); // Disable depth test and face culling. glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); int screen_width,screen_height; SDL_GetWindowSize(window, &screen_width, &screen_height); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); GLuint shaderProgram = compileShaderProgram("shaders/main.vert", "shaders/main.frag", NULL); int matrixLocation; SDL_Event e; bool quit = false; Uint64 now = SDL_GetPerformanceCounter(); Uint64 last = 0; double dt = 0; bool draw_wireframe = false; float x = 0.0f, y = 0.0f; Uint64 frame_count = 0; while (quit == false) { frame_count++; last = now; now = SDL_GetPerformanceCounter(); dt = (double)((now - last)*1000 / (double)SDL_GetPerformanceFrequency()); (void)dt; const Uint8* keystates = SDL_GetKeyboardState(NULL); float speed = 1.1f; if (keystates[SDL_SCANCODE_W]) { y += speed; } if (keystates[SDL_SCANCODE_S]) { y -= speed; } if (keystates[SDL_SCANCODE_A]) { x += speed; } if (keystates[SDL_SCANCODE_D]) { x -= speed; } while (SDL_PollEvent( &e)) { if (e.type == SDL_QUIT) { quit = true; } else if (e.type == SDL_KEYDOWN) { char key = e.key.keysym.sym; if (key == '1') { draw_wireframe = !draw_wireframe; } } } mat4 projection; glm_mat4_identity(projection); float aspectRatio = (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT; glm_perspective(45.0f, aspectRatio, 0.1f, 1000.0f, projection); mat4 model; glm_mat4_identity(model); mat4 view; glm_mat4_identity(view); glm_translate(model, (vec3){x, 0.0f, y}); glm_translate(model, (vec3){0.0f, 0.0f, -5.0f}); // glm_rotate(model, frame_count * 0.01f, (vec3){0.0f, 0.0f, 1.0f}); matrixLocation = glGetUniformLocation(shaderProgram, "view"); glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, view[0]); matrixLocation = glGetUniformLocation(shaderProgram, "projection"); glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, projection[0]); matrixLocation = glGetUniformLocation(shaderProgram, "model"); glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, model[0]); glUseProgram(shaderProgram); glViewport(0, 0, screen_width, screen_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // for (unsigned strip = 0; strip < NUM_STRIPS; strip++) { // glDrawElements(GL_TRIANGLE_STRIP, // primitive type // NUM_VERTS_PER_STRIP, // number of indices to render // GL_UNSIGNED_INT, // index data type // (void*)(sizeof(unsigned) * (NUM_VERTS_PER_STRIP) * strip)); // offset to starting index // } if (draw_wireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } else { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // glEnableClientState(GL_VERTEX_ARRAY); // glVertexPointer(3, GL_FLOAT, terrainVerts); // glDrawArrays(GL_TRIANGLE_STRIP, 0, w*h); // glDisableClientState(GL_VERTEX_ARRAY); glBindVertexArray(terrainVAO); // glDrawElements(GL_TRIANGLES, 8 * 3, GL_UNSIGNED_INT, 0); // glDrawArrays(GL_TRIANGLES, 0, w*h*3); size_t s = w*2 * sizeof(unsigned int); // glDrawElements(GL_TRIANGLE_STRIP, (w*h)+(w-1)*(h-2), GL_UNSIGNED_INT, (void*)s); glDrawElements(GL_TRIANGLE_STRIP, w*3*2, GL_UNSIGNED_INT, 0); SDL_GL_SwapWindow(window); } SDL_DestroyWindow( window ); return 0; }