From 37e603085675aca97f94cce66fcd5d0fa3d50b1a Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 27 Jul 2025 05:42:51 -0600 Subject: Skybox working --- assets/bush.png | Bin 46102 -> 12123 bytes assets/shaders/glsl100/skybox.fs | 31 +++++++++++++++++++++++++++++++ assets/shaders/glsl100/skybox.vs | 24 ++++++++++++++++++++++++ assets/shaders/glsl330/skybox.fs | 30 ++++++++++++++++++++++++++++++ assets/shaders/glsl330/skybox.vs | 24 ++++++++++++++++++++++++ assets/skybox.png | Bin 0 -> 10992 bytes assets/tree.png | Bin 208723 -> 55810 bytes design.org | 4 ++-- src/assets.c | 36 ++++++++++++++++++++++++++++++++++++ src/assets.h | 18 +++++++++++++++++- src/entity.c | 4 ++-- src/entity.h | 6 +++--- src/game.c | 30 ++++++++++++++++++++++++++++++ src/game.h | 1 + src/utils.h | 8 ++++++++ 15 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 assets/shaders/glsl100/skybox.fs create mode 100644 assets/shaders/glsl100/skybox.vs create mode 100644 assets/shaders/glsl330/skybox.fs create mode 100644 assets/shaders/glsl330/skybox.vs create mode 100644 assets/skybox.png diff --git a/assets/bush.png b/assets/bush.png index 07256a4..2d46b4c 100644 Binary files a/assets/bush.png and b/assets/bush.png differ diff --git a/assets/shaders/glsl100/skybox.fs b/assets/shaders/glsl100/skybox.fs new file mode 100644 index 0000000..0ea6876 --- /dev/null +++ b/assets/shaders/glsl100/skybox.fs @@ -0,0 +1,31 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec3 fragPosition; + +// Input uniform values +uniform samplerCube environmentMap; +uniform bool vflipped; +uniform bool doGamma; + +void main() +{ + // Fetch color from texture map + vec4 texelColor = vec4(0.0); + + if (vflipped) texelColor = textureCube(environmentMap, vec3(fragPosition.x, -fragPosition.y, fragPosition.z)); + else texelColor = textureCube(environmentMap, fragPosition); + + vec3 color = vec3(texelColor.x, texelColor.y, texelColor.z); + + if (doGamma) // Apply gamma correction + { + color = color/(color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + } + + // Calculate final fragment color + gl_FragColor = vec4(color, 1.0); +} diff --git a/assets/shaders/glsl100/skybox.vs b/assets/shaders/glsl100/skybox.vs new file mode 100644 index 0000000..e440ace --- /dev/null +++ b/assets/shaders/glsl100/skybox.vs @@ -0,0 +1,24 @@ +#version 100 + +// Input vertex attributes +attribute vec3 vertexPosition; + +// Input uniform values +uniform mat4 matProjection; +uniform mat4 matView; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; + +void main() +{ + // Calculate fragment position based on model transformations + fragPosition = vertexPosition; + + // Remove translation from the view matrix + mat4 rotView = mat4(mat3(matView)); + vec4 clipPos = matProjection*rotView*vec4(vertexPosition, 1.0); + + // Calculate final vertex position + gl_Position = clipPos; +} diff --git a/assets/shaders/glsl330/skybox.fs b/assets/shaders/glsl330/skybox.fs new file mode 100644 index 0000000..d71fef0 --- /dev/null +++ b/assets/shaders/glsl330/skybox.fs @@ -0,0 +1,30 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; + +// Input uniform values +uniform samplerCube environmentMap; +uniform bool vflipped; +uniform bool doGamma; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + // Fetch color from texture map + vec3 color = vec3(0.0); + + if (vflipped) color = texture(environmentMap, vec3(fragPosition.x, -fragPosition.y, fragPosition.z)).rgb; + else color = texture(environmentMap, fragPosition).rgb; + + if (doGamma)// Apply gamma correction + { + color = color/(color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + } + + // Calculate final fragment color + finalColor = vec4(color, 1.0); +} diff --git a/assets/shaders/glsl330/skybox.vs b/assets/shaders/glsl330/skybox.vs new file mode 100644 index 0000000..f41d469 --- /dev/null +++ b/assets/shaders/glsl330/skybox.vs @@ -0,0 +1,24 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; + +// Input uniform values +uniform mat4 matProjection; +uniform mat4 matView; + +// Output vertex attributes (to fragment shader) +out vec3 fragPosition; + +void main() +{ + // Calculate fragment position based on model transformations + fragPosition = vertexPosition; + + // Remove translation from the view matrix + mat4 rotView = mat4(mat3(matView)); + vec4 clipPos = matProjection*rotView*vec4(vertexPosition, 1.0); + + // Calculate final vertex position + gl_Position = clipPos; +} diff --git a/assets/skybox.png b/assets/skybox.png new file mode 100644 index 0000000..36a79b2 Binary files /dev/null and b/assets/skybox.png differ diff --git a/assets/tree.png b/assets/tree.png index af9a24b..30d3fa9 100644 Binary files a/assets/tree.png and b/assets/tree.png differ diff --git a/design.org b/design.org index 1cf2a9e..c5befc7 100644 --- a/design.org +++ b/design.org @@ -94,10 +94,10 @@ creates is possible to beat. A little wack is fine as long as its beatable. Since most of the world will just be a height map a image will be generated first than rest of the world will be based around it. -* TODO World generation check list [2/8] +* TODO World generation check list [3/8] + [X] Basic terrain + [X] Ground texture -+ [ ] Trees/plants ++ [X] Trees/plants + [ ] Sky + [ ] Pond + [ ] Power lines diff --git a/src/assets.c b/src/assets.c index 0434b5c..2ceff83 100644 --- a/src/assets.c +++ b/src/assets.c @@ -8,13 +8,39 @@ const char textureAssetPaths[TEXTURE_ASSET_COUNT][FT_NAMEMAX] = { "flower.png" }; +const char imageAssetPaths[IMAGE_ASSET_COUNT][FT_NAMEMAX] = { + "skybox.png" +}; + +const char shaderAssetNames[SHADER_ASSET_COUNT][FT_NAMEMAX] = { + "skybox" +}; + void initAssets(Assets* assets) { + // Textures. for (int index = 0; index < TEXTURE_ASSET_COUNT; ++index) { assets->textures[index] = LoadTexture( TextFormat("assets/%s", textureAssetPaths[index])); } + + // Images; + for (int index = 0; index < IMAGE_ASSET_COUNT; ++index) + { + assets->images[index] = LoadImage( + TextFormat("assets/%s", imageAssetPaths[index])); + } + + // Shaders. + for (int index = 0; index < SHADER_ASSET_COUNT; ++index) + { + assets->shaders[index] = LoadShader( + TextFormat("assets/shaders/glsl%i/%s.vs", GLSL_VERSION, + shaderAssetNames[index]), + TextFormat("assets/shaders/glsl%i/%s.fs", GLSL_VERSION, + shaderAssetNames[index])); + } } void closeAssets(Assets* assets) @@ -23,4 +49,14 @@ void closeAssets(Assets* assets) { UnloadTexture(assets->textures[index]); } + + for (int index = 0; index < IMAGE_ASSET_COUNT; ++index) + { + UnloadImage(assets->images[index]); + } + + for (int index = 0; index < SHADER_ASSET_COUNT; ++index) + { + UnloadShader(assets->shaders[index]); + } } diff --git a/src/assets.h b/src/assets.h index 2a1ee66..743926c 100644 --- a/src/assets.h +++ b/src/assets.h @@ -4,8 +4,12 @@ #define ASSETS_H #define TEXTURE_ASSET_COUNT 5 +#define IMAGE_ASSET_COUNT 1 +#define SHADER_ASSET_COUNT 1 extern const char textureAssetPaths[TEXTURE_ASSET_COUNT][FT_NAMEMAX]; +extern const char imageAssetPaths[IMAGE_ASSET_COUNT][FT_NAMEMAX]; +extern const char shaderAssetNames[SHADER_ASSET_COUNT][FT_NAMEMAX]; typedef int8_t AssetId; @@ -15,11 +19,23 @@ enum { NICKEL_TEXTURE, TREE_TEXTURE, BUSH_TEXTURE, - FLOWER_TEXTURE + FLOWER_TEXTURE, +}; + +// Image asset ids. +enum { + SKYBOX_IMAGE +}; + +// Shader asset ids. +enum { + SKYBOX_SHADER }; typedef struct { Texture textures[TEXTURE_ASSET_COUNT]; + Image images[IMAGE_ASSET_COUNT]; + Shader shaders[SHADER_ASSET_COUNT]; } Assets; void initAssets(Assets* assets); diff --git a/src/entity.c b/src/entity.c index 2ad7754..6d1aace 100644 --- a/src/entity.c +++ b/src/entity.c @@ -25,10 +25,10 @@ Entity createEntity(EntityId id, Vector3 position) entity.box = entityBoxFromScale(1.0, 32.0, 32.0); break; case TREE: - entity.box = entityBoxFromScale(TREE_SCALE, 225.0, 500.0); + entity.box = entityBoxFromScale(TREE_SCALE, 113.0, 250.0); break; case BUSH: - entity.box = entityBoxFromScale(BUSH_SCALE, 174.0, 124.0); + entity.box = entityBoxFromScale(BUSH_SCALE, 87.0, 62.0); break; case FLOWER: entity.box = entityBoxFromScale(FLOWER_SCALE, 32.0, 54.0); diff --git a/src/entity.h b/src/entity.h index f647e14..a1751aa 100644 --- a/src/entity.h +++ b/src/entity.h @@ -10,9 +10,9 @@ typedef int8_t EntityId; #define ENTITY_COUNT 5 // Entity scales. -#define TREE_SCALE 32.0 -#define BUSH_SCALE 6.0 -#define FLOWER_SCALE 2.0 +#define TREE_SCALE 40.0 +#define BUSH_SCALE 8.0 +#define FLOWER_SCALE 3.0 enum { ENTITY_NONE = -1, diff --git a/src/game.c b/src/game.c index f76a0ee..80efe6d 100644 --- a/src/game.c +++ b/src/game.c @@ -16,6 +16,27 @@ void initGame(Game* game) // Assets. initAssets(&game->assets); + // Skybox. + game->skybox = LoadModelFromMesh(GenMeshCube(1.0, 1.0, 1.0)); + game->skybox.materials[0].shader = game->assets.shaders[SKYBOX_SHADER]; + + SetShaderValue( + game->skybox.materials[0].shader, + GetShaderLocation(game->skybox.materials[0].shader, "environmentMap"), + (int[1]){ MATERIAL_MAP_CUBEMAP }, SHADER_UNIFORM_INT); + SetShaderValue( + game->skybox.materials[0].shader, + GetShaderLocation(game->skybox.materials[0].shader, "doGamma"), + (int[1]){ 0 }, SHADER_UNIFORM_INT); + SetShaderValue( + game->skybox.materials[0].shader, + GetShaderLocation(game->skybox.materials[0].shader, "vflipped"), + (int[1]){ 0 }, SHADER_UNIFORM_INT); + + game->skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = + LoadTextureCubemap(game->assets.images[SKYBOX_IMAGE], + CUBEMAP_LAYOUT_AUTO_DETECT); + // Player. game->player = createPlayer(); game->player.position = (Vector3){0.0, 30.0, 0.0}; @@ -37,6 +58,13 @@ void updateGameScene(Game* game) BeginMode3D(game->player.camera); + // Render skybox. + rlDisableBackfaceCulling(); + rlDisableDepthMask(); + DrawModel(game->skybox, Vector3Zero(), 1.0, WHITE); + rlEnableBackfaceCulling(); + rlEnableDepthMask(); + updatePlayer(&game->player, game); updateWorld(&game->world, game); @@ -68,6 +96,8 @@ void updateGame(Game* game) void closeGame(Game* game) { closeAssets(&game->assets); + UnloadTexture(game->skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture); + UnloadModel(game->skybox); freeWorld(game->world); CloseWindow(); } diff --git a/src/game.h b/src/game.h index ddfdbd5..0990bd2 100644 --- a/src/game.h +++ b/src/game.h @@ -19,6 +19,7 @@ struct Game { Assets assets; Player player; World world; + Model skybox; }; void initGame(Game* game); diff --git a/src/utils.h b/src/utils.h index 08239b8..6532660 100644 --- a/src/utils.h +++ b/src/utils.h @@ -7,6 +7,7 @@ #include #include +#include #include #include "raygui.h" @@ -29,6 +30,13 @@ #define ALLOCATION_ERROR TraceLog(LOG_ERROR, "Allocation error in %s:%d", \ __FILE__, __LINE__) +// GLSL version +#ifdef PLATFORM_DESKTOP + #define GLSL_VERSION 330 +#else // PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + // Typedef hackery. typedef struct Game Game; typedef struct World World; -- cgit v1.2.3