Files
sinbad/src/appGameFloor.c
T

142 lines
5.8 KiB
C

#include <raylib.h>
#include <rlgl.h>
#include "engineAssets.h"
#include "floor.h"
static void BindWaterTexture(Shader shader, const char *uniformName, Texture2D texture, int slot) {
int loc = GetShaderLocation(shader, uniformName);
if (loc < 0)
return;
rlActiveTextureSlot(slot);
rlEnableTexture(texture.id);
SetShaderValue(shader, loc, &slot, SHADER_UNIFORM_INT);
}
static void PrepareTiledTexture(Texture2D texture) {
SetTextureWrap(texture, TEXTURE_WRAP_REPEAT);
GenTextureMipmaps(&texture);
SetTextureFilter(texture, TEXTURE_FILTER_TRILINEAR);
}
static Texture2D CreateDepthGradientTexture(void) {
Image gradientImage =
GenImageGradientLinear(64, 64, 90, (Color){12, 44, 84, 255}, (Color){64, 168, 186, 255});
Texture2D depthGradient = LoadTextureFromImage(gradientImage);
UnloadImage(gradientImage);
SetTextureWrap(depthGradient, TEXTURE_WRAP_CLAMP);
return depthGradient;
}
static void ConfigureFloorShaderUniforms(Shader shader, Texture2D base, float worldTileSize,
float textureSize) {
float aspect = (float)GetScreenHeight() / (float)GetScreenWidth();
float pixelization = 2048.0f;
float noiseCoordinateScale = worldTileSize * ((float)base.width / textureSize);
int aspectLoc = GetShaderLocation(shader, "aspectRatio");
int pixelLoc = GetShaderLocation(shader, "pixelization");
int noiseCoordinateScaleLoc = GetShaderLocation(shader, "noiseCoordinateScale");
SetShaderValue(shader, aspectLoc, &aspect, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, pixelLoc, &pixelization, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, noiseCoordinateScaleLoc, &noiseCoordinateScale, SHADER_UNIFORM_FLOAT);
}
Floor CreateFloor(void) {
Texture2D base = LoadTextureCached("assets/water_base.png");
Texture2D caustic = LoadTextureCached("assets/water_caustics.png");
Texture2D causticHighlight = LoadTextureCached("assets/water_caustics_highlights.png");
Texture2D noise = LoadTextureCached("assets/water_noise.png");
Texture2D cloud = LoadTextureCached("assets/water_cloudnoise.png");
Texture2D voronoise = LoadTextureCached("assets/water_voronoise.png");
PrepareTiledTexture(caustic);
PrepareTiledTexture(causticHighlight);
PrepareTiledTexture(noise);
PrepareTiledTexture(cloud);
PrepareTiledTexture(voronoise);
Texture2D depthGradient = CreateDepthGradientTexture();
float textureWidth = 64.0f;
Floor floor = {.sprite = {.texture = base,
.frameSize = {textureWidth, textureWidth},
.sourceRec = {0.0f, 0.0f, textureWidth, textureWidth},
.destRec = {0.0f, 0.0f, textureWidth, textureWidth},
.origin = {textureWidth / 2, textureWidth / 2},
.rotation = 0.0f,
.color = WHITE},
.bounds = {0},
.shader = LoadShader("shaders/water.vs", "shaders/water.fs"),
.time = 0.0f};
float worldTileSize = 128.0f;
float textureSize = 32.0f;
floor.sprite.frameSize = (Vector2){worldTileSize, worldTileSize};
floor.sprite.sourceRec = (Rectangle){0, 0, textureSize, textureSize};
floor.sprite.destRec = (Rectangle){0, 0, worldTileSize, worldTileSize};
floor.sprite.origin = (Vector2){0, 0};
ConfigureFloorShaderUniforms(floor.shader, base, worldTileSize, textureSize);
floor.sprite.texture = base;
floor.causticTexture = caustic;
floor.causticHighlightTexture = causticHighlight;
floor.noiseTexture = noise;
floor.cloudTexture = cloud;
floor.voronoiseTexture = voronoise;
floor.depthGradientTexture = depthGradient;
return floor;
}
void UpdateFloor(Floor *floor, Camera2D *camera) {
floor->bounds.x = (int)((camera->target.x - (GetScreenWidth() / 2.0f / camera->zoom)) /
floor->sprite.frameSize.x) -
1;
floor->bounds.width = (int)((camera->target.x + (GetScreenWidth() / 2.0f / camera->zoom)) /
floor->sprite.frameSize.x) +
1;
floor->bounds.y = (int)((camera->target.y - (GetScreenHeight() / 2.0f / camera->zoom)) /
floor->sprite.frameSize.y) -
1;
floor->bounds.height = (int)((camera->target.y + (GetScreenHeight() / 2.0f / camera->zoom)) /
floor->sprite.frameSize.y) +
1;
floor->time += GetFrameTime();
int timeLoc = GetShaderLocation(floor->shader, "time");
SetShaderValue(floor->shader, timeLoc, &floor->time, SHADER_UNIFORM_FLOAT);
}
void RenderFloor(Floor *floor) {
BeginShaderMode(floor->shader);
BindWaterTexture(floor->shader, "causticTexture", floor->causticTexture, 1);
BindWaterTexture(floor->shader, "causticHighlightTexture", floor->causticHighlightTexture, 2);
BindWaterTexture(floor->shader, "causticNoiseTexture", floor->noiseTexture, 3);
BindWaterTexture(floor->shader, "causticFadeNoiseTexture", floor->cloudTexture, 4);
BindWaterTexture(floor->shader, "specularNoiseTexture", floor->voronoiseTexture, 5);
BindWaterTexture(floor->shader, "specularMovementLeftNoiseTexture", floor->voronoiseTexture, 6);
BindWaterTexture(floor->shader, "specularMovementRightNoiseTexture", floor->cloudTexture, 7);
BindWaterTexture(floor->shader, "foamTexture", floor->voronoiseTexture, 8);
BindWaterTexture(floor->shader, "waterDepthGradient", floor->depthGradientTexture, 9);
for (int y = (int)floor->bounds.y; y <= (int)floor->bounds.height; y++) {
for (int x = (int)floor->bounds.x; x <= (int)floor->bounds.width; x++) {
Vector2 floorPosition = {x * floor->sprite.frameSize.x, y * floor->sprite.frameSize.y};
UpdateSpriteDestRec(&floor->sprite, &floorPosition);
RenderSprite(&floor->sprite);
}
}
EndShaderMode();
}
void UnloadFloor(Floor *floor) {
UnloadShader(floor->shader);
UnloadTexture(floor->depthGradientTexture);
}