111 lines
2.9 KiB
C
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();
|
|
}
|