Working chunk and textures

This commit is contained in:
2025-06-01 18:14:05 +02:00
parent 7473b9c66d
commit f164071fb0
21 changed files with 158 additions and 45 deletions
+3 -3
View File
@@ -1,9 +1,9 @@
SRC=src/math_3d.c src/main.c src/mesh.c src/program.c src/resources.c src/camera.c \
src/chunk/chunk.c src/chunk/noise.c src/chunk/chunkmesh.c src/flags.c
src/chunk/chunk.c src/chunk/noise.c src/chunk/chunkmesh.c src/flags.c src/texture.c
OBJ=$(SRC:.c=.o)
CFLAGS=-g -Werror -Wextra -Wall `pkg-config --cflags sdl3 gl`
LDFLAGS=`pkg-config --libs sdl3 gl` -lm
CFLAGS=-Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image gl`
LDFLAGS=`pkg-config --libs sdl3 sdl3-image gl` -lm
TARGET=wschod
CC=gcc
LD=gcc
-11
View File
@@ -1,11 +0,0 @@
#version 100
precision lowp float;
varying vec2 f_uv;
varying float f_height;
void main ()
{
gl_FragColor = vec4 (f_uv.x, 1.0, f_uv.y, 1.0);
}
+21
View File
@@ -0,0 +1,21 @@
#version 100
precision lowp float;
varying vec2 f_uv;
varying vec3 f_material;
varying float f_height;
uniform sampler2D materials[5];
void main ()
{
/* This means there can be four textures on a terrain. Could be
extended, but who cares? */
vec4 result = texture2D (materials[0], f_uv);
result = mix (result, texture2D (materials[1], f_uv), f_material[0]);
result = mix (result, texture2D (materials[2], f_uv), f_material[1]);
result = mix (result, texture2D (materials[3], f_uv), f_material[2]);
gl_FragColor = result * vec4(f_height, f_height, f_height, 1.0);
}
@@ -1,17 +1,20 @@
#version 100
attribute vec3 position;
attribute vec4 position;
attribute vec3 material;
uniform mat4 view;
uniform mat4 projection;
varying vec2 f_uv;
varying vec3 f_material;
varying float f_height;
void main ()
{
f_uv = position.xy / 8.0;
f_material = material;
f_height = position.y;
gl_Position = projection * view * vec4 (position, 1.0);
gl_Position = projection * view * position;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

+2
View File
@@ -9,8 +9,10 @@ pkgs.mkShellNoCC {
gcc
pkg-config
sdl3
sdl3-image
gdb
cglm
glew
valgrind
];
}
+7 -3
View File
@@ -1,5 +1,7 @@
#include "chunk.h"
#include <math.h>
Chunk
Chunk_new ()
{
@@ -18,9 +20,11 @@ Chunk_noise (Chunk *chunk, int xoffset, int yoffset)
{
for (int x = 0; x < CHUNK_DIM; ++x)
{
float val = noise2 ((x + xoffset * CHUNK_DIM), (y + yoffset * CHUNK_DIM)) * 8;
chunk->heightmap[INDEX (x, y)] = val;
chunk->materialmap[INDEX (x, y)] = 0;
(void) xoffset; (void) yoffset;
float val = sinf (x) + sinf (y);
(void) val;
chunk->heightmap[INDEX (x, y)] = (val + 0.5);
chunk->materialmap[INDEX (x, y)] = (int) val;
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
#define CHUNK_DIM 16
#define CHUNK_SIZE (CHUNK_DIM*CHUNK_DIM)
#define INDEX(x, y) (CHUNK_DIM * y + x)
#define INDEX(x, y) (CHUNK_DIM * (y) + (x))
typedef struct Chunk
{
+31 -7
View File
@@ -7,31 +7,43 @@ ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *n
/* nd --- down neighbor; nr --- right neighbor; nc --- corner neighbor */
{
vec3_t *positions = malloc (sizeof (vec3_t) * CHUNKMESH_SIZE);
vec3_t *materials = malloc (sizeof (vec3_t) * CHUNKMESH_SIZE);
unsigned int *indices = malloc (sizeof (unsigned int) * CHUNKMESH_SIZE * 6);
INFO ("Temporarily allocated %zu bytes for ChunkMesh.",
(sizeof (vec3_t) * CHUNKMESH_SIZE * 2
+ sizeof (unsigned int) * CHUNKMESH_SIZE * 6));
int i_i = 0;
for (int y = 0; y < CHUNKMESH_DIM; ++y)
{
for (int x = 0; x < CHUNKMESH_DIM; ++x)
{
float height = chunk->heightmap[INDEX (x, y)];
float material_id = chunk->materialmap[INDEX (x, y)];
if (x == CHUNK_DIM && y < CHUNKMESH_DIM && nr != NULL)
{
height = nr->heightmap[INDEX (0, y)];
material_id = nr->materialmap[INDEX (0, y)];
}
if (y == CHUNK_DIM && x < CHUNKMESH_DIM && nd != NULL)
{
height = nd->heightmap[INDEX (x, 0)];
material_id = nr->materialmap[INDEX (x, 0)];
}
if (x == CHUNK_DIM && y == CHUNK_DIM && nc != NULL)
{
height = nc->heightmap[INDEX (0, 0)];
material_id = nr->materialmap[INDEX (0, 0)];
}
positions[CMINDEX (x, y)] = vec3 (x, height, y);
materials[CMINDEX (x, y)] = vec3
(material_id == 1 ? 1 : 0, material_id == 2 ? 1 : 0,
material_id == 3 ? 1 : 0);
if (x < CHUNK_DIM && y < CHUNK_DIM)
{
@@ -41,11 +53,11 @@ ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *n
int i3 = CMINDEX (x + 1, y + 1);
/*
i0----i1
| |
| |
i2----i3
*/
i0----i1
| \ |
| \ |
i2----i3
*/
indices[i_i++] = i0;
indices[i_i++] = i2;
@@ -59,17 +71,27 @@ ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *n
ChunkMesh mesh;
glGenBuffers (1, &mesh.pbo);
glGenBuffers (1, &mesh.mbo);
glGenBuffers (1, &mesh.ebo);
glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo);
glBufferData (GL_ARRAY_BUFFER, sizeof (vec3_t) * CHUNKMESH_SIZE, positions, GL_STATIC_DRAW);
glEnableVertexAttribArray (0);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (vec3_t), 0);
glBindBuffer (GL_ARRAY_BUFFER, mesh.mbo);
glBufferData (GL_ARRAY_BUFFER, sizeof (vec3_t) * CHUNKMESH_SIZE, materials, GL_STATIC_DRAW);
glEnableVertexAttribArray (1);
glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, sizeof (vec3_t), 0);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo);
glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * CHUNKMESH_SIZE * 6, indices, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
free (positions);
free (materials);
free (indices);
return mesh;
@@ -79,7 +101,7 @@ void
ChunkMesh_render (ChunkMesh *mesh)
{
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo);
if (game_flags.wireframe_enabled)
{
glDrawElements (GL_LINES, CHUNKMESH_SIZE * 6, GL_UNSIGNED_INT, 0);
@@ -88,4 +110,6 @@ ChunkMesh_render (ChunkMesh *mesh)
{
glDrawElements (GL_TRIANGLES, CHUNKMESH_SIZE * 6, GL_UNSIGNED_INT, 0);
}
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
}
+3 -3
View File
@@ -6,14 +6,14 @@
#include "../math_3d.h"
#include "chunk.h"
#define CHUNKMESH_DIM (CHUNK_SIZE+1)
#define CHUNKMESH_DIM (CHUNK_DIM+1)
#define CHUNKMESH_SIZE (CHUNKMESH_DIM*CHUNKMESH_DIM)
#define CMINDEX(x, y) (CHUNKMESH_DIM * y + x)
#define CMINDEX(x, y) (CHUNKMESH_DIM * (y) + (x))
typedef struct ChunkMesh
{
unsigned int pbo;
/* Element Buffer Object, the indices. */
unsigned int mbo;
unsigned int ebo;
} ChunkMesh;
+6 -6
View File
@@ -23,12 +23,12 @@ noise_seed (int seed)
float
noise2 (float x, float y)
{
int X = (int) FASTFLOOR(x) & 0xff;
int Y = (int) FASTFLOOR(y) & 0xff;
x -= FASTFLOOR(x);
y -= FASTFLOOR(y);
float u = FADE(x);
float v = FADE(y);
int X = (int) FASTFLOOR (x) & 0xff;
int Y = (int) FASTFLOOR (y) & 0xff;
x -= FASTFLOOR (x);
y -= FASTFLOOR (y);
float u = FADE (x);
float v = FADE (y);
int A = (perm[X] + Y) & 0xff;
int B = (perm[X + 1] + Y) & 0xff;
+12 -4
View File
@@ -66,6 +66,9 @@ SDL_AppInit (void **appstate, int argc, char **argv)
glViewport(0, 0, 640, 480);
glClearColor (0, 0.3, 0.8, 1);
glEnable (GL_CULL_FACE);
glEnable (GL_DEPTH_TEST);
/* Initialize and load resources. */
Resources_init ();
noise_seed (1337);
@@ -75,14 +78,12 @@ SDL_AppInit (void **appstate, int argc, char **argv)
Chunk_noise (&chunk, 0, 0);
test_chunkmesh = ChunkMesh_from_Chunk_and_neighbors (&chunk, NULL, NULL, NULL);
program_use (resources.programs[1]);
program_print (resources.programs[1]);
/* Set up game state. */
game_state.last_time = SDL_GetTicks ();
/* Set some basic game flags for testing. */
game_flags.can_free_look = 1;
game_flags.wireframe_enabled = 0;
/* Initialize the default camera. */
camera = Camera_default ();
@@ -193,12 +194,19 @@ SDL_AppIterate (void *appstate)
/* Render stuff. */
glClear (GL_COLOR_BUFFER_BIT);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mat4_t view = Camera_get_view (&camera);
mat4_t projection = Camera_get_projection (&camera, 640.0 / 480.0);
program_use (resources.programs[1]);
for (size_t i = 0; i < resources.textures_len; ++i)
{
glActiveTexture (GL_TEXTURE0 + i);
glBindTexture (GL_TEXTURE_2D, resources.textures[i]);
}
program_set_mat4 (resources.programs[1], "view", view);
program_set_mat4 (resources.programs[1], "projection", projection);
ChunkMesh_render (&test_chunkmesh);
+34 -4
View File
@@ -6,7 +6,7 @@ void
Resources_add_program (const char *v_src, const char *f_src)
{
resources.programs_len++;
resources.programs = realloc (resources.programs, sizeof (int) * resources.programs_len);
resources.programs = realloc (resources.programs, sizeof (unsigned int) * resources.programs_len);
resources.programs[resources.programs_len - 1] = program_create (v_src, f_src);
}
@@ -47,18 +47,48 @@ Resources_load_program (const char *v_path, const char *f_path)
free (f_src);
}
void
Resources_add_texture (int width, int height, unsigned char *data)
{
resources.textures_len++;
resources.textures = realloc (resources.textures, sizeof (unsigned int) * resources.textures_len);
resources.textures[resources.textures_len - 1] = texture_create (width, height, data);
}
void
Resources_load_texture (const char *path)
{
SDL_Surface *surface = IMG_Load (path);
if (surface == NULL)
{
WARN ("Failed to load texture from path %s: %s", path, SDL_GetError ());
}
Resources_add_texture (surface->w, surface->h, surface->pixels);
SDL_DestroySurface (surface);
}
void
Resources_init ()
{
resources.programs_len = 0;
resources.programs = malloc (sizeof (int));
Resources_load_program ("res/default.vert", "res/default.frag");
Resources_load_program ("res/chunk.vert", "res/chunk.frag");
resources.programs = malloc (sizeof (unsigned int));
Resources_load_program ("res/shaders/default.vert", "res/shaders/default.frag");
Resources_load_program ("res/shaders/chunk.vert", "res/shaders/chunk.frag");
resources.textures_len = 0;
resources.textures = malloc (sizeof (unsigned int));
Resources_load_texture ("res/textures/dirt.png");
Resources_load_texture ("res/textures/drygrass.png");
Resources_load_texture ("res/textures/grass.png");
Resources_load_texture ("res/textures/asphalt_gravel.png");
}
void
Resources_free ()
{
free (resources.programs);
free (resources.textures);
}
+11 -1
View File
@@ -1,13 +1,23 @@
#pragma once
#include <SDL3_image/SDL_image.h>
#include "program.h"
#include "texture.h"
typedef struct Resources {
size_t programs_len;
int *programs;
unsigned int *programs;
size_t textures_len;
unsigned int *textures;
} Resources;
void Resources_add_program (const char *v_src, const char *f_src);
void Resources_load_program (const char *v_path, const char *f_path);
void Resources_add_texture (int width, int height, unsigned char *data);
void Resources_load_texture (const char *path);
void Resources_init ();
void Resources_free ();
+17
View File
@@ -0,0 +1,17 @@
#include "texture.h"
unsigned int
texture_create (int width, int height, unsigned char *data)
{
unsigned int texture;
glGenTextures (1, &texture);
glBindTexture (GL_TEXTURE_2D, texture);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap (GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, 0);
return texture;
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <SDL3/SDL_opengles2.h>
unsigned int texture_create (int width, int height, unsigned char *data);