257 lines
8.3 KiB
C
257 lines
8.3 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "libs/cglm/cglm.h"
|
|
#include "libs/glad/include/glad/glad.h"
|
|
#include <SDL2/SDL.h>
|
|
// #include <SDL2/SDL_events.h>
|
|
#include "stb_image.h"
|
|
// #include <SDL2/SDL_image.h>
|
|
// #include <SDL2/SDL_render.h>
|
|
#include "lib.h"
|
|
|
|
//Screen dimension constants
|
|
const int SCREEN_WIDTH = 1920;
|
|
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 res = 16;
|
|
int width, height, c;
|
|
unsigned char *terrain_img = stbi_load("terrain.png", &width, &height, &c, 0);
|
|
int w = width / res;
|
|
int h = height / res;
|
|
float tw = 100.0f, th = 35.0f;
|
|
// int w = 20;
|
|
// int h = 20;
|
|
int vcount = w * h * 3;
|
|
|
|
float *terrainVerts = malloc(vcount * sizeof(float));
|
|
for (int row = 0; row < h; row++) {
|
|
for (int col = 0; col < w; col++) {
|
|
int idx = (row * w + col) * 3;
|
|
terrainVerts[idx+0] = -tw/2.0f + (float)col/w * tw;
|
|
terrainVerts[idx+1] = *(terrain_img + (row * width + col) * c * res) * 0.01f + 1.0f;
|
|
terrainVerts[idx+2] = -th/2.0f + (float)row/h * th;
|
|
// *(v+1) = y * scale_y + shift_y;
|
|
// *(v+1) = -h/2 + row
|
|
}
|
|
}
|
|
stbi_image_free(terrain_img);
|
|
|
|
// There's 1 less row, so (h-1) * width, then we need to add the extra two
|
|
// indices for the degenerate triangles per row, except the first row
|
|
// which only has one extra index, since the first index does not need degeneracy
|
|
// And then since there are duplicate indices in each row
|
|
int icount = (h-1) * (w) * 2 *4;
|
|
unsigned int *terrainIndices = malloc(icount * sizeof(unsigned int));
|
|
|
|
int i = 0;
|
|
for (int row = 0; row < h-1; row++) {
|
|
for (int col = 0; col < w-1; col++) {
|
|
unsigned int topleft = row * w + col;
|
|
unsigned int botleft = (row+1) * w + col;
|
|
unsigned int botright = (row+1) * w + col+1;
|
|
unsigned int topright = row * w + col+1;
|
|
terrainIndices[i++] = topleft;
|
|
terrainIndices[i++] = botleft;
|
|
terrainIndices[i++] = botright;
|
|
terrainIndices[i++] = topleft;
|
|
terrainIndices[i++] = topright;
|
|
terrainIndices[i++] = botright;
|
|
}
|
|
}
|
|
// int i = 0;
|
|
// for (int row = 0; row < h-1; row++) {
|
|
// if (row != 0) {
|
|
// // Duplicate next num
|
|
// terrainIndices[i++] = row * w;
|
|
// }
|
|
// for (int col = 0; col < w; col++) {
|
|
// terrainIndices[i++] = (row + 0) * w + col;
|
|
// terrainIndices[i++] = (row + 1) * w + col;
|
|
// }
|
|
// // Duplicate last num
|
|
// if (row < h-2) {
|
|
// terrainIndices[i] = terrainIndices[i-1];
|
|
// i++;
|
|
// }
|
|
// }
|
|
|
|
// float terrainVerts[] = {
|
|
// float tv[] = {
|
|
// 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,
|
|
// // Second row
|
|
// 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,
|
|
// };
|
|
|
|
printf("Loaded %d vertices\n", w * h);
|
|
|
|
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, vcount * sizeof(float), 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);
|
|
int ebosize = icount * sizeof(unsigned int);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ebosize, 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 = true;
|
|
float x = 0.0f, y = 0.0f;
|
|
Uint64 frame_count = 0;
|
|
float scroll = -10.0f;
|
|
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 = 0.5f;
|
|
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;
|
|
}
|
|
}
|
|
if (e.type == SDL_MOUSEWHEEL) {
|
|
if (e.wheel.y > 0) {
|
|
scroll -= 2.0f;
|
|
} else if(e.wheel.y < 0) {
|
|
scroll += 2.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
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(view, (vec3){x, -y, scroll});
|
|
// glm_translate(view, (vec3){0.0f, 0.0f, -10.0f});
|
|
glm_rotate(model, 45.0f, (vec3){1.0f, 0.0f, 0.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);
|
|
|
|
if (draw_wireframe) {
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
} else {
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
}
|
|
glBindVertexArray(terrainVAO);
|
|
glDrawElements(GL_TRIANGLES, icount, GL_UNSIGNED_INT, (void*)0);
|
|
|
|
SDL_GL_SwapWindow(window);
|
|
}
|
|
|
|
SDL_DestroyWindow( window );
|
|
return 0;
|
|
}
|