Compare commits

...

4 Commits

Author SHA1 Message Date
bjorn 5c43ad0792 Pass:fill; 2022-06-24 19:59:48 -07:00
bjorn 0a3ccb4f8a stb_image sets srgb flag properly; 2022-06-24 19:38:57 -07:00
bjorn fbf2a039b7 setMaterial takes Texture in addition to Material; 2022-06-24 19:38:45 -07:00
bjorn f729320793 Fix creating Material from Texture; 2022-06-24 19:38:23 -07:00
7 changed files with 87 additions and 4 deletions

View File

@ -1,7 +1,7 @@
#include "shaders/unlit.vert.h"
#include "shaders/unlit.frag.h"
#include "shaders/font.frag.h"
#include "shaders/fill.vert.h"
#include "shaders/lovr.glsl.h"

14
etc/shaders/fill.vert Normal file
View File

@ -0,0 +1,14 @@
#version 460
#extension GL_EXT_multiview : require
#extension GL_GOOGLE_include_directive : require
#include "lovr.glsl"
void main() {
FragColor = VertexColor * Color;
float x = -1 + float((VertexIndex & 1) << 2);
float y = -1 + float((VertexIndex & 2) << 1);
FragUV = vec2(x, y) * .5 + .5;
Position = vec4(x, y, 0., 1.);
PointSize = 1.f;
}

View File

@ -1104,6 +1104,12 @@ static int l_lovrGraphicsNewMaterial(lua_State* L) {
if (texture) {
info.texture = texture;
info.data.color[0] = 1.f;
info.data.color[1] = 1.f;
info.data.color[2] = 1.f;
info.data.color[3] = 1.f;
info.data.uvScale[0] = 1.f;
info.data.uvScale[1] = 1.f;
} else {
luaL_checktype(L, 1, LUA_TTABLE);

View File

@ -241,7 +241,8 @@ static int l_lovrPassSetDepthClamp(lua_State* L) {
static int l_lovrPassSetMaterial(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
Material* material = luax_totype(L, 2, Material);
lovrPassSetMaterial(pass, material);
Texture* texture = luax_totype(L, 2, Texture);
lovrPassSetMaterial(pass, material, texture);
return 0;
}
@ -552,6 +553,13 @@ static int l_lovrPassText(lua_State* L) {
return 0;
}
static int l_lovrPassFill(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
Texture* texture = luax_totype(L, 2, Texture);
lovrPassFill(pass, texture);
return 0;
}
static int l_lovrPassMesh(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
Buffer* vertices = !lua_toboolean(L, 2) ? NULL : luax_totype(L, 2, Buffer);
@ -802,6 +810,7 @@ const luaL_Reg lovrPass[] = {
{ "sphere", l_lovrPassSphere },
{ "torus", l_lovrPassTorus },
{ "text", l_lovrPassText },
{ "fill", l_lovrPassFill },
{ "mesh", l_lovrPassMesh },
{ "multimesh", l_lovrPassMultimesh },

View File

@ -1141,6 +1141,7 @@ static Image* loadKTX2(Blob* blob) {
static Image* loadSTB(Blob* blob) {
void* data;
uint32_t flags;
TextureFormat format;
int width, height, channels;
if (stbi_is_16_bit_from_memory(blob->data, (int) blob->size)) {
@ -1151,12 +1152,14 @@ static Image* loadSTB(Blob* blob) {
case 4: format = FORMAT_RGBA16; break;
default: lovrThrow("Unsupported channel count for 16 bit image: %d", channels);
}
flags = IMAGE_SRGB;
} else if (stbi_is_hdr_from_memory(blob->data, (int) blob->size)) {
data = stbi_loadf_from_memory(blob->data, (int) blob->size, &width, &height, NULL, 4);
format = FORMAT_RGBA32F;
} else {
data = stbi_load_from_memory(blob->data, (int) blob->size, &width, &height, NULL, 4);
format = FORMAT_RGBA8;
flags = IMAGE_SRGB;
}
if (!data) {
@ -1168,6 +1171,7 @@ static Image* loadSTB(Blob* blob) {
Image* image = calloc(1, sizeof(Image));
lovrAssert(image, "Out of memory");
image->ref = 1;
image->flags = flags;
image->width = width;
image->height = height;
image->format = format;

View File

@ -58,6 +58,7 @@ struct Texture {
uint32_t ref;
gpu_texture* gpu;
gpu_texture* renderView;
Material* material;
TextureInfo info;
Sync sync;
};
@ -176,6 +177,7 @@ typedef enum {
VERTEX_SHAPE,
VERTEX_POINT,
VERTEX_GLYPH,
VERTEX_EMPTY,
VERTEX_FORMAT_COUNT
} VertexFormat;
@ -478,6 +480,16 @@ bool lovrGraphicsInit(bool debug, bool vsync) {
.attributes[4] = { 1, 14, 0, GPU_TYPE_F32x4 }
};
state.vertexFormats[VERTEX_EMPTY] = (gpu_vertex_format) {
.bufferCount = 2,
.attributeCount = 5,
.attributes[0] = { 1, 10, 0, GPU_TYPE_F32x2 },
.attributes[1] = { 1, 11, 0, GPU_TYPE_F32x4 },
.attributes[2] = { 1, 12, 0, GPU_TYPE_F32x2 },
.attributes[3] = { 1, 13, 16, GPU_TYPE_F32x4 },
.attributes[4] = { 1, 14, 0, GPU_TYPE_F32x4 }
};
state.defaultMaterial = lovrMaterialCreate(&(MaterialInfo) {
.data.color = { 1.f, 1.f, 1.f, 1.f },
.texture = state.defaultTexture
@ -1119,6 +1131,7 @@ Texture* lovrTextureCreateView(TextureViewInfo* view) {
void lovrTextureDestroy(void* ref) {
Texture* texture = ref;
if (texture != state.window) {
lovrRelease(texture->material, lovrMaterialDestroy);
lovrRelease(texture->info.parent, lovrTextureDestroy);
if (texture->renderView && texture->renderView != texture->gpu) gpu_texture_destroy(texture->renderView);
if (texture->gpu) gpu_texture_destroy(texture->gpu);
@ -1130,6 +1143,22 @@ const TextureInfo* lovrTextureGetInfo(Texture* texture) {
return &texture->info;
}
static Material* lovrTextureGetMaterial(Texture* texture) {
if (!texture->material) {
texture->material = lovrMaterialCreate(&(MaterialInfo) {
.data.color = { 1.f, 1.f, 1.f, 1.f },
.data.uvScale = { 1.f, 1.f },
.texture = texture
});
// Since the Material refcounts the Texture, this creates a cycle. Release the texture to make
// sure this is a weak relationship (the automaterial does not keep the texture refcounted).
lovrRelease(texture, lovrTextureDestroy);
}
return texture->material;
}
// Sampler
Sampler* lovrGraphicsGetDefaultSampler(FilterMode mode) {
@ -1328,6 +1357,11 @@ Shader* lovrGraphicsGetDefaultShader(DefaultShader type) {
info.stages[1] = lovrBlobCreate((void*) lovr_shader_font_frag, sizeof(lovr_shader_font_frag), "Font Fragment Shader");
info.label = "font";
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;
default: lovrUnreachable();
}
@ -2185,7 +2219,11 @@ void lovrPassSetDepthClamp(Pass* pass, bool clamp) {
}
}
void lovrPassSetMaterial(Pass* pass, Material* material) {
void lovrPassSetMaterial(Pass* pass, Material* material, Texture* texture) {
if (texture) {
material = lovrTextureGetMaterial(texture);
}
material = material ? material : state.defaultMaterial;
if (pass->pipeline->material != material) {
@ -3371,6 +3409,16 @@ void lovrPassText(Pass* pass, Font* font, const char* text, uint32_t length, flo
}
}
void lovrPassFill(Pass* pass, Texture* texture) {
lovrPassDraw(pass, &(Draw) {
.mode = VERTEX_TRIANGLES,
.shader = SHADER_FILL,
.material = texture ? lovrTextureGetMaterial(texture) : NULL,
.vertex.format = VERTEX_EMPTY,
.count = 3
});
}
void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transform, uint32_t start, uint32_t count, uint32_t instances) {
if (count == ~0u) {
count = (indices ? indices : vertices)->info.length - start;

View File

@ -251,6 +251,7 @@ const SamplerInfo* lovrSamplerGetInfo(Sampler* sampler);
typedef enum {
SHADER_UNLIT,
SHADER_FONT,
SHADER_FILL,
DEFAULT_SHADER_COUNT
} DefaultShader;
@ -459,7 +460,7 @@ void lovrPassSetDepthTest(Pass* pass, CompareMode test);
void lovrPassSetDepthWrite(Pass* pass, bool write);
void lovrPassSetDepthOffset(Pass* pass, float offset, float sloped);
void lovrPassSetDepthClamp(Pass* pass, bool clamp);
void lovrPassSetMaterial(Pass* pass, Material* material);
void lovrPassSetMaterial(Pass* pass, Material* material, Texture* texture);
void lovrPassSetSampler(Pass* pass, Sampler* sampler);
void lovrPassSetScissor(Pass* pass, uint32_t scissor[4]);
void lovrPassSetShader(Pass* pass, Shader* shader);
@ -481,6 +482,7 @@ void lovrPassCircle(Pass* pass, float* transform, DrawStyle style, float angle1,
void lovrPassSphere(Pass* pass, float* transform, uint32_t segmentsH, uint32_t segmentsV);
void lovrPassTorus(Pass* pass, float* transform, uint32_t segmentsT, uint32_t segmentsP);
void lovrPassText(Pass* pass, Font* font, const char* text, uint32_t length, float* transform, float wrap, HorizontalAlign halign, VerticalAlign valign);
void lovrPassFill(Pass* pass, Texture* texture);
void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transform, uint32_t start, uint32_t count, uint32_t instances);
void lovrPassMultimesh(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* indirect, uint32_t count, uint32_t offset, uint32_t stride);
void lovrPassCompute(Pass* pass, uint32_t x, uint32_t y, uint32_t z, Buffer* indirect, uint32_t offset);