From b934fac1df46422d1c50c1b0dab30fd770a50fea Mon Sep 17 00:00:00 2001 From: bjorn Date: Mon, 4 Jul 2022 00:18:38 -0700 Subject: [PATCH] Pass:skybox; --- etc/shaders.h | 3 +++ etc/shaders/cubemap.frag | 13 ++++++++++ etc/shaders/cubemap.vert | 26 ++++++++++++++++++++ etc/shaders/equirect.frag | 17 +++++++++++++ etc/shaders/lovr.glsl | 12 ++++++---- etc/shaders/unlit.vert | 1 + src/api/l_graphics.c | 4 +++- src/api/l_graphics_pass.c | 8 +++++++ src/modules/graphics/graphics.c | 42 ++++++++++++++++++++++++++++----- src/modules/graphics/graphics.h | 5 +++- 10 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 etc/shaders/cubemap.frag create mode 100644 etc/shaders/cubemap.vert create mode 100644 etc/shaders/equirect.frag diff --git a/etc/shaders.h b/etc/shaders.h index 735fbd2c..f0b54eb3 100644 --- a/etc/shaders.h +++ b/etc/shaders.h @@ -2,6 +2,9 @@ #include "shaders/unlit.frag.h" #include "shaders/font.frag.h" #include "shaders/fill.vert.h" +#include "shaders/cubemap.vert.h" +#include "shaders/cubemap.frag.h" +#include "shaders/equirect.frag.h" #include "shaders/animator.comp.h" #include "shaders/timewizard.comp.h" diff --git a/etc/shaders/cubemap.frag b/etc/shaders/cubemap.frag new file mode 100644 index 00000000..49e25a43 --- /dev/null +++ b/etc/shaders/cubemap.frag @@ -0,0 +1,13 @@ +#version 460 +#extension GL_EXT_multiview : require +#extension GL_GOOGLE_include_directive : require + +#include "lovr.glsl" + +layout(set = 1, binding = 1) uniform textureCube SkyboxTexture; + +layout(location = 2) in vec3 FragDirection; + +void main() { + PixelColors[0] = FragColor * texture(samplerCube(SkyboxTexture, Sampler), FragDirection); +} diff --git a/etc/shaders/cubemap.vert b/etc/shaders/cubemap.vert new file mode 100644 index 00000000..baa0c535 --- /dev/null +++ b/etc/shaders/cubemap.vert @@ -0,0 +1,26 @@ +#version 460 +#extension GL_EXT_multiview : require +#extension GL_GOOGLE_include_directive : require + +#include "lovr.glsl" + +layout(location = 2) out vec3 FragDirection; + +void main() { + FragColor = VertexColor * Color; + + const vec2 uvs[6] = vec2[6]( + vec2(-1, -1), + vec2(-1, +1), + vec2(+1, -1), + vec2(+1, -1), + vec2(-1, +1), + vec2(+1, +1) + ); + + vec2 uv = uvs[VertexIndex % 6]; + vec3 ray = vec3(uv, -1.); + mat3 inverseViewOrientation = transpose(mat3(View)); + FragDirection = normalize(inverseViewOrientation * (InverseProjection * vec4(ray, 1.)).xyz); + Position = vec4(uv, 1, 1); +} diff --git a/etc/shaders/equirect.frag b/etc/shaders/equirect.frag new file mode 100644 index 00000000..c0b111b5 --- /dev/null +++ b/etc/shaders/equirect.frag @@ -0,0 +1,17 @@ +#version 460 +#extension GL_EXT_multiview : require +#extension GL_GOOGLE_include_directive : require + +#define PI 3.141592653589793238462643383 + +#include "lovr.glsl" + +layout(location = 2) in vec3 FragDirection; + +void main() { + vec3 dir = normalize(FragDirection); + float phi = acos(dir.y); + float theta = atan(dir.x, -dir.z); + vec2 uv = vec2(.5 + theta / (2 * PI), phi / PI); + PixelColors[0] = FragColor * texture(sampler2D(Texture, Sampler), uv); +} diff --git a/etc/shaders/lovr.glsl b/etc/shaders/lovr.glsl index c54eb690..0c338bb6 100644 --- a/etc/shaders/lovr.glsl +++ b/etc/shaders/lovr.glsl @@ -60,11 +60,13 @@ layout(location = 0) out vec4 PixelColors[1]; // Varyings #ifdef GL_VERTEX_SHADER -layout(location = 10) out vec4 FragColor; -layout(location = 11) out vec2 FragUV; +layout(location = 10) out vec3 FragNormal; +layout(location = 11) out vec4 FragColor; +layout(location = 12) out vec2 FragUV; #else -layout(location = 10) in vec4 FragColor; -layout(location = 11) in vec2 FragUV; +layout(location = 10) in vec3 FragNormal; +layout(location = 11) in vec4 FragColor; +layout(location = 12) in vec2 FragUV; #endif // Macros @@ -97,7 +99,7 @@ layout(location = 11) in vec2 FragUV; #define ViewProjection cameras[ViewIndex].viewProjection #define InverseProjection cameras[ViewIndex].inverseProjection #define Transform draws[DrawId].transform -#define NormalMatrix draws[DrawId].normalMatrix +#define NormalMatrix mat3(draws[DrawId].normalMatrix) #define Color draws[DrawId].color #define ClipFromLocal (ViewProjection * Transform) diff --git a/etc/shaders/unlit.vert b/etc/shaders/unlit.vert index 4b146197..ce1093a0 100644 --- a/etc/shaders/unlit.vert +++ b/etc/shaders/unlit.vert @@ -6,6 +6,7 @@ void main() { FragColor = VertexColor * Color; + FragNormal = normalize(NormalMatrix * VertexNormal); FragUV = VertexUV; Position = DefaultPosition; PointSize = 1.f; diff --git a/src/api/l_graphics.c b/src/api/l_graphics.c index d088ece0..ac54f40e 100644 --- a/src/api/l_graphics.c +++ b/src/api/l_graphics.c @@ -60,6 +60,8 @@ StringEntry lovrCullMode[] = { StringEntry lovrDefaultShader[] = { [SHADER_UNLIT] = ENTRY("unlit"), + [SHADER_CUBE] = ENTRY("cube"), + [SHADER_FILL] = ENTRY("fill"), [SHADER_FONT] = ENTRY("font"), { 0 } }; @@ -911,7 +913,7 @@ static int l_lovrGraphicsNewTexture(lua_State* L) { lua_pop(L, 1); } - if (info.imageCount == 0 && info.depth == 0) { + if (info.depth == 0) { info.depth = info.type == TEXTURE_CUBE ? 6 : 1; } diff --git a/src/api/l_graphics_pass.c b/src/api/l_graphics_pass.c index 3cb980c7..9cd4a7fa 100644 --- a/src/api/l_graphics_pass.c +++ b/src/api/l_graphics_pass.c @@ -569,6 +569,13 @@ static int l_lovrPassText(lua_State* L) { return 0; } +static int l_lovrPassSkybox(lua_State* L) { + Pass* pass = luax_checktype(L, 1, Pass); + Texture* texture = luax_totype(L, 2, Texture); + lovrPassSkybox(pass, texture); + return 0; +} + static int l_lovrPassFill(lua_State* L) { Pass* pass = luax_checktype(L, 1, Pass); Texture* texture = luax_totype(L, 2, Texture); @@ -864,6 +871,7 @@ const luaL_Reg lovrPass[] = { { "torus", l_lovrPassTorus }, { "cylinder", l_lovrPassCylinder }, { "text", l_lovrPassText }, + { "skybox", l_lovrPassSkybox }, { "fill", l_lovrPassFill }, { "monkey", l_lovrPassMonkey }, { "draw", l_lovrPassDraw }, diff --git a/src/modules/graphics/graphics.c b/src/modules/graphics/graphics.c index 5d65ecb9..61c2a8c1 100644 --- a/src/modules/graphics/graphics.c +++ b/src/modules/graphics/graphics.c @@ -1096,7 +1096,7 @@ Texture* lovrTextureCreate(TextureInfo* info) { Image* image = info->imageCount == 1 ? info->images[0] : info->images[layer]; uint32_t slice = info->imageCount == 1 ? layer : 0; uint32_t size = lovrImageGetLayerSize(image, level); - lovrCheck(size == levelSizes[level], "Texture/Image size mismatch!"); + lovrCheck(size == levelSizes[level] / info->depth, "Texture/Image size mismatch!"); void* pixels = lovrImageGetLayerData(image, level, slice); memcpy(data, pixels, size); data += size; @@ -1426,16 +1426,26 @@ Shader* lovrGraphicsGetDefaultShader(DefaultShader type) { info.stages[1] = lovrBlobCreate((void*) lovr_shader_unlit_frag, sizeof(lovr_shader_unlit_frag), "Unlit Fragment Shader"); info.label = "unlit"; break; - case SHADER_FONT: - info.stages[0] = lovrBlobCreate((void*) lovr_shader_unlit_vert, sizeof(lovr_shader_unlit_vert), "Unlit Vertex Shader"); - info.stages[1] = lovrBlobCreate((void*) lovr_shader_font_frag, sizeof(lovr_shader_font_frag), "Font Fragment Shader"); - info.label = "font"; + case SHADER_CUBE: + info.stages[0] = lovrBlobCreate((void*) lovr_shader_cubemap_vert, sizeof(lovr_shader_cubemap_vert), "Cubemap Vertex Shader"); + info.stages[1] = lovrBlobCreate((void*) lovr_shader_cubemap_frag, sizeof(lovr_shader_cubemap_frag), "Cubemap Fragment Shader"); + info.label = "cubemap"; + break; + case SHADER_PANO: + info.stages[0] = lovrBlobCreate((void*) lovr_shader_cubemap_vert, sizeof(lovr_shader_cubemap_vert), "Cubemap Vertex Shader"); + info.stages[1] = lovrBlobCreate((void*) lovr_shader_equirect_frag, sizeof(lovr_shader_equirect_frag), "Equirect Fragment Shader"); + info.label = "equirect"; break; case SHADER_FILL: info.stages[0] = lovrBlobCreate((void*) lovr_shader_fill_vert, sizeof(lovr_shader_fill_vert), "Fill Vertex Shader"); info.stages[1] = lovrBlobCreate((void*) lovr_shader_unlit_frag, sizeof(lovr_shader_unlit_frag), "Unlit Fragment Shader"); info.label = "fill"; break; + case SHADER_FONT: + info.stages[0] = lovrBlobCreate((void*) lovr_shader_unlit_vert, sizeof(lovr_shader_unlit_vert), "Unlit Vertex Shader"); + info.stages[1] = lovrBlobCreate((void*) lovr_shader_font_frag, sizeof(lovr_shader_font_frag), "Font Fragment Shader"); + info.label = "font"; + break; default: lovrUnreachable(); } @@ -1832,7 +1842,7 @@ Material* lovrMaterialCreate(MaterialInfo* info) { for (uint32_t i = 0; i < COUNTOF(textures); i++) { lovrRetain(textures[i]); Texture* texture = textures[i] ? textures[i] : state.defaultTexture; - lovrCheck(texture->info.type == TEXTURE_2D, "Material textures must be 2D"); + lovrCheck(i == 0 || texture->info.type == TEXTURE_2D, "Material textures must be 2D"); bindings[i + 1] = (gpu_binding) { i + 1, GPU_SLOT_SAMPLED_TEXTURE, .texture = texture->gpu }; } @@ -4189,6 +4199,26 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count tempPop(stack); } +void lovrPassSkybox(Pass* pass, Texture* texture) { + if (texture->info.type == TEXTURE_2D) { + lovrPassDraw(pass, &(Draw) { + .mode = VERTEX_TRIANGLES, + .shader = SHADER_PANO, + .material = texture ? lovrTextureGetMaterial(texture) : NULL, + .vertex.format = VERTEX_EMPTY, + .count = 6 + }); + } else { + lovrPassDraw(pass, &(Draw) { + .mode = VERTEX_TRIANGLES, + .shader = SHADER_CUBE, + .material = texture ? lovrTextureGetMaterial(texture) : NULL, + .vertex.format = VERTEX_EMPTY, + .count = 6 + }); + } +} + void lovrPassFill(Pass* pass, Texture* texture) { lovrPassDraw(pass, &(Draw) { .mode = VERTEX_TRIANGLES, diff --git a/src/modules/graphics/graphics.h b/src/modules/graphics/graphics.h index e2a465e9..b7a5a1c6 100644 --- a/src/modules/graphics/graphics.h +++ b/src/modules/graphics/graphics.h @@ -253,8 +253,10 @@ const SamplerInfo* lovrSamplerGetInfo(Sampler* sampler); typedef enum { SHADER_UNLIT, - SHADER_FONT, + SHADER_CUBE, + SHADER_PANO, SHADER_FILL, + SHADER_FONT, DEFAULT_SHADER_COUNT } DefaultShader; @@ -540,6 +542,7 @@ void lovrPassSphere(Pass* pass, float* transform, uint32_t segmentsH, uint32_t s void lovrPassCylinder(Pass* pass, float* transform, bool capped, float angle1, float angle2, uint32_t segments); void lovrPassTorus(Pass* pass, float* transform, uint32_t segmentsT, uint32_t segmentsP); void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count, float* transform, float wrap, HorizontalAlign halign, VerticalAlign valign); +void lovrPassSkybox(Pass* pass, Texture* texture); void lovrPassFill(Pass* pass, Texture* texture); void lovrPassMonkey(Pass* pass, float* transform); void lovrPassDrawModel(Pass* pass, Model* model, float* transform, uint32_t node, bool recurse, uint32_t instances);