#include "RayExt.h" #include #include #include #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(); }