109
src/RayExt.c
Normal file
109
src/RayExt.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#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=texture(environmentMap, dir); }\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
|
||||
rlDisableColorBlend();
|
||||
rlDisableBackfaceCulling();
|
||||
rlDisableDepthMask();
|
||||
|
||||
DrawModel(skybox.cube, position, 60.0f, (Color) { 255, 255, 255, 255 });
|
||||
|
||||
rlDrawRenderBatchActive();
|
||||
rlEnableDepthMask();
|
||||
rlEnableBackfaceCulling();
|
||||
rlEnableColorBlend();
|
||||
}
|
||||
Reference in New Issue
Block a user