minecraft

minecraft
git clone git://git.evenfri.pw/minecraft.git
Log | Files | Refs | README

commit 13072c6043e79e12badb50ddf4451615fe328699
parent c93afd7ea41eaf47dbfb879f082bb47f40aa253e
Author: evenfri <evenfri@4plt.ch>
Date:   Sun,  1 Nov 2026 22:59:23 +0800

feat: blocks, textures

Diffstat:
Aassets/cobblestone.png | 0
Aassets/dirt.png | 0
Aassets/grass_side.png | 0
Aassets/grass_top.png | 0
Aassets/stone.png | 0
Aassets/terrain.png | 0
Ablocks.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcamera.c | 8++++++++
Mdat.h | 21++++++++++++++++++++-
Mfns.h | 6++++++
Mmkfile | 1+
Mrender.c | 106+++++++++++++++++++++++++++++++++++++------------------------------------------
Dterrain.png | 0
13 files changed, 159 insertions(+), 58 deletions(-)

diff --git a/assets/cobblestone.png b/assets/cobblestone.png Binary files differ. diff --git a/assets/dirt.png b/assets/dirt.png Binary files differ. diff --git a/assets/grass_side.png b/assets/grass_side.png Binary files differ. diff --git a/assets/grass_top.png b/assets/grass_top.png Binary files differ. diff --git a/assets/stone.png b/assets/stone.png Binary files differ. diff --git a/assets/terrain.png b/assets/terrain.png Binary files differ. diff --git a/blocks.c b/blocks.c @@ -0,0 +1,75 @@ +#include "minecraft.h" +#include "stb_image.h" + +Block blocks[] = { + { BLOCK_GRASS, { + "assets/grass_side.png", /* back */ + "assets/grass_side.png", /* front */ + "assets/grass_side.png", /* left */ + "assets/grass_side.png", /* right */ + "assets/dirt.png", /* bottom */ + "assets/grass_top.png", /* top */ + }}, + { BLOCK_STONE, { + "assets/stone.png", "assets/stone.png", + "assets/stone.png", "assets/stone.png", + "assets/stone.png", "assets/stone.png", + }}, + { BLOCK_DIRT, { + "assets/dirt.png", "assets/dirt.png", + "assets/dirt.png", "assets/dirt.png", + "assets/dirt.png", "assets/dirt.png", + }}, +}; +int block_count = sizeof(blocks) / sizeof(blocks[0]); + +static unsigned int *block_textures = NULL; + +static unsigned int load_texture(const char *path) { + unsigned int tex; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + int w, h, nrChannels; + stbi_set_flip_vertically_on_load(true); + unsigned char *data = stbi_load(path, &w, &h, &nrChannels, 0); + if (!data) { + printf("err: failed to load texture %s\n", path); + return 0; + } + GLenum fmt = (nrChannels == 4) ? GL_RGBA + : (nrChannels == 3) ? GL_RGB + : GL_RED; + glTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, fmt, + GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); + stbi_image_free(data); + return tex; +} + +void blocks_init(void) { + block_textures = malloc(sizeof(unsigned int) * block_count * FACE_COUNT); + for (int i = 0; i < block_count; i++) + for (int f = 0; f < FACE_COUNT; f++) + block_textures[i * FACE_COUNT + f] = + load_texture(blocks[i].texture_paths[f]); +} + +void blocks_end(void) { + if (block_textures) { + glDeleteTextures(block_count * FACE_COUNT, block_textures); + free(block_textures); + block_textures = NULL; + } +} + +unsigned int block_texture(unsigned int id, int face) { + if (face < 0 || face >= FACE_COUNT) return 0; + for (int i = 0; i < block_count; i++) + if (blocks[i].id == id) + return block_textures[i * FACE_COUNT + face]; + return 0; +} diff --git a/camera.c b/camera.c @@ -76,6 +76,14 @@ mat4 mat4_perspective(float fovy, float aspect, float znear, float zfar) { return r; } +mat4 mat4_translate(float x, float y, float z) { + mat4 r = mat4_identity(); + r.m[12] = x; + r.m[13] = y; + r.m[14] = z; + return r; +} + void camera_process_keyboard(float dt) { float v = camera.speed * dt; diff --git a/dat.h b/dat.h @@ -5,7 +5,6 @@ #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 -// #define WINDOW_TITLE "Minecraft" #define WINDOW_TITLE "window" typedef struct { float x, y, z; } vec3; @@ -24,8 +23,28 @@ typedef struct { float fov; } Camera; +#define FACE_BACK 0 +#define FACE_FRONT 1 +#define FACE_LEFT 2 +#define FACE_RIGHT 3 +#define FACE_BOTTOM 4 +#define FACE_TOP 5 +#define FACE_COUNT 6 + +typedef struct { + unsigned int id; + char *texture_paths[FACE_COUNT]; +} Block; + +#define BLOCK_GRASS 1 +#define BLOCK_STONE 2 +#define BLOCK_DIRT 3 +#define BLOCK_COBBLESTONE 4 + extern GLFWwindow *Window; extern unsigned int Shader; extern Camera camera; +extern Block blocks[]; +extern int block_count; #endif /* DAT_H */ diff --git a/fns.h b/fns.h @@ -18,8 +18,14 @@ mat4 camera_get_view(void); mat4 mat4_identity(void); mat4 mat4_perspective(float fovy, float aspect, float znear, float zfar); +mat4 mat4_translate(float x, float y, float z); void camera_process_keyboard(float dt); void camera_process_mouse(float dx, float dy); +void blocks_init(void); +void blocks_end(void); +unsigned int block_texture(unsigned int id, int face); +void render_block(unsigned int block_id, vec3 pos); + #endif /* FNS_H */ diff --git a/mkfile b/mkfile @@ -10,6 +10,7 @@ ofiles = \ render.$o \ shader.$o \ camera.$o \ + blocks.$o \ main.$o hfiles = \ diff --git a/render.c b/render.c @@ -8,6 +8,7 @@ static int u_model, u_view, u_proj; void render_init() { float vertices[] = { + /* back */ -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, @@ -15,6 +16,7 @@ void render_init() { -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + /* front */ -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, @@ -22,20 +24,23 @@ void render_init() { -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + /* left */ + -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + /* right */ + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + /* bottom */ -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, @@ -43,17 +48,19 @@ void render_init() { -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + /* top */ -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f}; + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f + }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); - glBindVertexArray(VAO); + glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); @@ -69,65 +76,50 @@ void render_init() { // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glGenTextures(1, &Texture); - glBindTexture(GL_TEXTURE_2D, Texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - int width, height, nrChannels; - stbi_set_flip_vertically_on_load(true); - unsigned char *data = stbi_load("terrain.png", - &width, &height, &nrChannels, 0); - if (data) { - GLenum format; - if (nrChannels == 1) - format = GL_RED; - else if (nrChannels == 3) - format = GL_RGB; - else if (nrChannels == 4) - format = GL_RGBA; - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, - GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - } else { - printf("err: failed to load texture\n"); - } - stbi_image_free(data); - glUseProgram(Shader); glUniform1i(glGetUniformLocation(Shader, "texture1"), 0); - u_model = glGetUniformLocation(Shader, "model"); u_view = glGetUniformLocation(Shader, "view"); u_proj = glGetUniformLocation(Shader, "projection"); + blocks_init(); +} + +void render_block(unsigned int block_id, vec3 pos) { + mat4 model = mat4_translate(pos.x, pos.y, pos.z); + glUniformMatrix4fv(u_model, 1, GL_FALSE, model.m); + + for (int face = 0; face < FACE_COUNT; face++) { + unsigned int tex = block_texture(block_id, face); + if (!tex) continue; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex); + glDrawArrays(GL_TRIANGLES, face * 6, 6); + } } void render_frame() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, Texture); - glUseProgram(Shader); - mat4 model = mat4_identity(); - mat4 view = camera_get_view(); + mat4 view = camera_get_view(); mat4 projection = mat4_perspective(camera.fov, - (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, - 0.1f, 100.0f); - - glUniformMatrix4fv(u_model, 1, GL_FALSE, model.m); - glUniformMatrix4fv(u_view, 1, GL_FALSE, view.m); - glUniformMatrix4fv(u_proj, 1, GL_FALSE, projection.m); + (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, + 0.1f, 100.0f); + glUniformMatrix4fv(u_view, 1, GL_FALSE, view.m); + glUniformMatrix4fv(u_proj, 1, GL_FALSE, projection.m); glBindVertexArray(VAO); - glDrawArrays(GL_TRIANGLES, 0, 36); + + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + render_block(BLOCK_GRASS, (vec3){ x, 0.0f, z }); + render_block(BLOCK_DIRT, (vec3){ x, -1.0f, z }); + render_block(BLOCK_STONE, (vec3){ x, -2.0f, z }); + } + } + glfwPollEvents(); glfwSwapBuffers(Window); } diff --git a/terrain.png b/terrain.png Binary files differ.