Files
lunarwm/src/RayExt.c
2025-08-11 07:12:04 +03:00

111 lines
2.9 KiB
C

#include "RayExt.h"
#include <raylib.h>
#include <raymath.h>
#include <rlgl.h>
#if defined(GRAPHICS_API_OPENGL_ES3)
static char const *SKYBOX_VS = "#version 300 es\n"
"precision mediump float;\n"
"layout(location=0) in vec3 vertexPosition;\n"
"uniform mat4 mvp;\n"
"out vec3 vDir;\n"
"void main(){ vDir=vertexPosition; "
"gl_Position=mvp*vec4(vertexPosition,1.0); }\n";
static char const *SKYBOX_FS
= "#version 300 es\n"
"precision highp float;\n"
"in vec3 vDir;\n"
"uniform samplerCube environmentMap;\n"
"out vec4 finalColor;\n"
"void main(){ vec3 dir=normalize(vDir); "
"finalColor=vec4(texture(environmentMap, normalize(vDir)).rgb, 1.0); }\n";
#endif
void Skybox_init(Skybox *skybox, char const *fp)
{
if (skybox->ok) {
Skybox_destroy(skybox);
}
// 1) Load cubemap from a 3x4 cross image
Image img = LoadImage(fp);
if (img.width == 0 || img.height == 0) {
TraceLog(LOG_ERROR, "Skybox: failed to load image: %s", fp);
skybox->ok = false;
return;
}
TextureCubemap cubemap
= LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT);
UnloadImage(img);
if (cubemap.id == 0) {
TraceLog(LOG_ERROR, "Skybox: failed to create cubemap from %s", fp);
skybox->ok = false;
return;
}
// 2) Make an inward-facing cube mesh
Mesh m = GenMeshCube(
2.0f, 2.0f, 2.0f); // size doesn't matter; depth writes off
// Invert winding so we see the inside
for (int i = 0; i < m.triangleCount; ++i) {
unsigned short *idx = &m.indices[i * 3];
unsigned short tmp = idx[1];
idx[1] = idx[2];
idx[2] = tmp;
}
UploadMesh(&m, false);
Model cube = LoadModelFromMesh(m);
Shader sh = LoadShaderFromMemory(SKYBOX_VS, SKYBOX_FS);
// make raylib aware which sampler is the cubemap
sh.locs[SHADER_LOC_MAP_CUBEMAP] = GetShaderLocation(sh, "environmentMap");
cube.materials[0].shader = sh;
// put the cubemap in the expected material slot
cube.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = cubemap;
// nicer defaults
SetTextureWrap(cubemap, TEXTURE_WRAP_CLAMP);
SetTextureFilter(cubemap, TEXTURE_FILTER_BILINEAR);
skybox->cubemap = cubemap;
skybox->shader = sh;
skybox->cube = cube;
skybox->ok = true;
}
void Skybox_destroy(Skybox *skybox)
{
if (!skybox->ok)
return;
UnloadModel(skybox->cube); // also unloads Mesh
UnloadTexture(skybox->cubemap);
UnloadShader(skybox->shader);
*skybox = (Skybox) { 0 };
}
void Skybox_draw(Skybox const skybox, Vector3 position)
{
if (!skybox.ok)
return;
// Render behind everything without writing depth; cull disabled so we see
// inside faces
rlDisableBackfaceCulling();
rlDisableDepthMask();
rlDisableColorBlend();
DrawModel(skybox.cube, position, 500.0f, (Color) { 255, 255, 255, 255 });
rlDrawRenderBatchActive();
rlEnableColorBlend();
rlEnableDepthMask();
rlEnableBackfaceCulling();
}