mirror of https://github.com/bjornbytes/lovr.git
Consolidate Texture and Skybox;
This commit is contained in:
parent
e8f2166e00
commit
a2860361e9
|
@ -229,7 +229,6 @@ set(LOVR_SRC
|
|||
src/api/types/randomGenerator.c
|
||||
src/api/types/shader.c
|
||||
src/api/types/shapes.c
|
||||
src/api/types/skybox.c
|
||||
src/api/types/source.c
|
||||
src/api/types/texture.c
|
||||
src/api/types/transform.c
|
||||
|
@ -244,7 +243,6 @@ set(LOVR_SRC
|
|||
src/graphics/mesh.c
|
||||
src/graphics/model.c
|
||||
src/graphics/shader.c
|
||||
src/graphics/skybox.c
|
||||
src/graphics/texture.c
|
||||
src/headset/headset.c
|
||||
src/lib/glad/glad.c
|
||||
|
|
|
@ -63,14 +63,6 @@ static void luax_readvertices(lua_State* L, int index, vec_float_t* points) {
|
|||
}
|
||||
}
|
||||
|
||||
static Texture* luax_readtexture(lua_State* L, int index) {
|
||||
Blob* blob = luax_readblob(L, index, "Texture");
|
||||
TextureData* textureData = lovrTextureDataFromBlob(blob);
|
||||
Texture* texture = lovrTextureCreate(textureData);
|
||||
lovrRelease(&blob->ref);
|
||||
return texture;
|
||||
}
|
||||
|
||||
// Base
|
||||
|
||||
int l_lovrGraphicsInit(lua_State* L) {
|
||||
|
@ -80,7 +72,6 @@ int l_lovrGraphicsInit(lua_State* L) {
|
|||
luax_registertype(L, "Mesh", lovrMesh);
|
||||
luax_registertype(L, "Model", lovrModel);
|
||||
luax_registertype(L, "Shader", lovrShader);
|
||||
luax_registertype(L, "Skybox", lovrSkybox);
|
||||
luax_registertype(L, "Texture", lovrTexture);
|
||||
|
||||
map_init(&BlendAlphaModes);
|
||||
|
@ -550,15 +541,21 @@ int l_lovrGraphicsCylinder(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrGraphicsSphere(lua_State* L) {
|
||||
Texture* texture = NULL;
|
||||
float transform[16];
|
||||
int index = 1;
|
||||
if (lua_isuserdata(L, 1) && (lua_isuserdata(L, 2) || lua_isnumber(L, 2))) {
|
||||
texture = luax_checktype(L, index++, Texture);
|
||||
}
|
||||
index = luax_readtransform(L, index, transform, 1);
|
||||
int segments = luaL_optnumber(L, index, 30);
|
||||
lovrGraphicsSphere(texture, transform, segments, NULL);
|
||||
lovrGraphicsSphere(transform, segments);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsSkybox(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
float angle = luaL_optnumber(L, 2, 0);
|
||||
float ax = luaL_optnumber(L, 3, 0);
|
||||
float ay = luaL_optnumber(L, 4, 1);
|
||||
float az = luaL_optnumber(L, 5, 0);
|
||||
lovrGraphicsSkybox(texture, angle, ax, ay, az);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -700,51 +697,6 @@ int l_lovrGraphicsNewShader(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsNewSkybox(lua_State* L) {
|
||||
Blob* blobs[6] = { NULL };
|
||||
SkyboxType type;
|
||||
|
||||
if (lua_gettop(L) == 1 && lua_type(L, 1) == LUA_TSTRING) {
|
||||
type = SKYBOX_PANORAMA;
|
||||
blobs[0] = luax_readblob(L, 1, "Skybox");
|
||||
} else if (lua_istable(L, 1)) {
|
||||
if (lua_objlen(L, 1) != 6) {
|
||||
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
lua_rawgeti(L, 1, i + 1);
|
||||
|
||||
if (!lua_isstring(L, -1)) {
|
||||
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
|
||||
}
|
||||
|
||||
blobs[i] = luax_readblob(L, -1, "Skybox");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
type = SKYBOX_CUBE;
|
||||
} else {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
blobs[i] = luax_readblob(L, i + 1, "Skybox");
|
||||
}
|
||||
|
||||
type = SKYBOX_CUBE;
|
||||
}
|
||||
|
||||
Skybox* skybox = lovrSkyboxCreate(blobs, type);
|
||||
luax_pushtype(L, Skybox, skybox);
|
||||
lovrRelease(&skybox->ref);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (blobs[i]) {
|
||||
lovrRelease(&blobs[i]->ref);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsNewTexture(lua_State* L) {
|
||||
Texture* texture;
|
||||
|
||||
|
@ -756,7 +708,34 @@ int l_lovrGraphicsNewTexture(lua_State* L) {
|
|||
TextureData* textureData = lovrTextureDataGetEmpty(width, height, FORMAT_RGBA);
|
||||
texture = lovrTextureCreateWithFramebuffer(textureData, *projection, msaa);
|
||||
} else {
|
||||
texture = luax_readtexture(L, 1);
|
||||
Blob* blobs[6];
|
||||
int isTable = lua_istable(L, 1);
|
||||
int count = isTable ? lua_objlen(L, 1) : lua_gettop(L);
|
||||
|
||||
if (count != 1 && count != 6) {
|
||||
return luaL_error(L, "Expected 1 image for a 2D texture or 6 images for a cube texture, got %d", count);
|
||||
}
|
||||
|
||||
if (isTable) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, -1, i + 1);
|
||||
blobs[i] = luax_readblob(L, -1, "Texture");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < count; i++) {
|
||||
blobs[i] = luax_readblob(L, i + 1, "Texture");
|
||||
}
|
||||
}
|
||||
|
||||
TextureData* slices[6];
|
||||
for (int i = 0; i < count; i++) {
|
||||
slices[i] = lovrTextureDataFromBlob(blobs[i]);
|
||||
lovrRelease(&blobs[i]->ref);
|
||||
}
|
||||
|
||||
TextureType type = (count == 1) ? TEXTURE_2D : TEXTURE_CUBE;
|
||||
texture = lovrTextureCreate(type, slices, count);
|
||||
}
|
||||
|
||||
luax_pushtype(L, Texture, texture);
|
||||
|
@ -812,12 +791,12 @@ const luaL_Reg lovrGraphics[] = {
|
|||
{ "box", l_lovrGraphicsBox },
|
||||
{ "cylinder", l_lovrGraphicsCylinder },
|
||||
{ "sphere", l_lovrGraphicsSphere },
|
||||
{ "skybox", l_lovrGraphicsSkybox },
|
||||
{ "print", l_lovrGraphicsPrint },
|
||||
{ "newFont", l_lovrGraphicsNewFont },
|
||||
{ "newMesh", l_lovrGraphicsNewMesh },
|
||||
{ "newModel", l_lovrGraphicsNewModel },
|
||||
{ "newShader", l_lovrGraphicsNewShader },
|
||||
{ "newSkybox", l_lovrGraphicsNewSkybox },
|
||||
{ "newTexture", l_lovrGraphicsNewTexture },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -38,7 +38,6 @@ extern const luaL_Reg lovrPhysics[];
|
|||
extern const luaL_Reg lovrRandomGenerator[];
|
||||
extern const luaL_Reg lovrShader[];
|
||||
extern const luaL_Reg lovrShape[];
|
||||
extern const luaL_Reg lovrSkybox[];
|
||||
extern const luaL_Reg lovrSliderJoint[];
|
||||
extern const luaL_Reg lovrSource[];
|
||||
extern const luaL_Reg lovrSphereShape[];
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#include "api/lovr.h"
|
||||
#include "graphics/graphics.h"
|
||||
|
||||
int l_lovrSkyboxDraw(lua_State* L) {
|
||||
Skybox* skybox = luax_checktype(L, 1, Skybox);
|
||||
float angle = luaL_optnumber(L, 2, 0.f);
|
||||
float ax = luaL_optnumber(L, 3, 0.f);
|
||||
float ay = luaL_optnumber(L, 4, 0.f);
|
||||
float az = luaL_optnumber(L, 5, 0.f);
|
||||
lovrGraphicsSkybox(skybox, angle, ax, ay, az);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrSkybox[] = {
|
||||
{ "draw", l_lovrSkyboxDraw },
|
||||
{ NULL, NULL }
|
||||
};
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
int l_lovrTextureGetDimensions(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
lua_pushnumber(L, lovrTextureGetWidth(texture));
|
||||
lua_pushnumber(L, lovrTextureGetHeight(texture));
|
||||
lua_pushnumber(L, texture->width);
|
||||
lua_pushnumber(L, texture->height);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -21,22 +21,25 @@ int l_lovrTextureGetFilter(lua_State* L) {
|
|||
|
||||
int l_lovrTextureGetHeight(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
lua_pushnumber(L, lovrTextureGetHeight(texture));
|
||||
lua_pushnumber(L, texture->height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrTextureGetWidth(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
lua_pushnumber(L, lovrTextureGetWidth(texture));
|
||||
lua_pushnumber(L, texture->width);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrTextureGetWrap(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
WrapMode horizontal, vertical;
|
||||
lovrTextureGetWrap(texture, &horizontal, &vertical);
|
||||
luax_pushenum(L, &WrapModes, horizontal);
|
||||
luax_pushenum(L, &WrapModes, vertical);
|
||||
TextureWrap wrap = lovrTextureGetWrap(texture);
|
||||
luax_pushenum(L, &WrapModes, wrap.s);
|
||||
luax_pushenum(L, &WrapModes, wrap.t);
|
||||
if (texture->type == TEXTURE_CUBE) {
|
||||
luax_pushenum(L, &WrapModes, wrap.r);
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -62,9 +65,11 @@ int l_lovrTextureSetFilter(lua_State* L) {
|
|||
|
||||
int l_lovrTextureSetWrap(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
WrapMode* horizontal = (WrapMode*) luax_checkenum(L, 2, &WrapModes, "wrap mode");
|
||||
WrapMode* vertical = (WrapMode*) luax_optenum(L, 3, luaL_checkstring(L, 2), &WrapModes, "wrap mode");
|
||||
lovrTextureSetWrap(texture, *horizontal, *vertical);
|
||||
TextureWrap wrap;
|
||||
wrap.s = *(WrapMode*) luax_checkenum(L, 2, &WrapModes, "wrap mode");
|
||||
wrap.t = *(WrapMode*) luax_optenum(L, 3, luaL_checkstring(L, 2), &WrapModes, "wrap mode");
|
||||
wrap.r = *(WrapMode*) luax_optenum(L, 4, luaL_checkstring(L, 2), &WrapModes, "wrap mode");
|
||||
lovrTextureSetWrap(texture, wrap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,9 +49,9 @@ Font* lovrFontCreate(FontData* fontData) {
|
|||
// Texture
|
||||
TextureData* textureData = lovrTextureDataGetBlank(font->atlas.width, font->atlas.height, 0x0, FORMAT_RGB);
|
||||
TextureFilter filter = { .mode = FILTER_BILINEAR };
|
||||
font->texture = lovrTextureCreate(textureData);
|
||||
font->texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1);
|
||||
lovrTextureSetFilter(font->texture, filter);
|
||||
lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP);
|
||||
lovrTextureSetWrap(font->texture, (TextureWrap) { .s = WRAP_CLAMP, .t = WRAP_CLAMP });
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ void lovrFontExpandTexture(Font* font) {
|
|||
}
|
||||
|
||||
// Resize the texture storage
|
||||
lovrTextureDataResize(font->texture->textureData, atlas->width, atlas->height, 0x0);
|
||||
lovrTextureDataResize(font->texture->slices[0], atlas->width, atlas->height, 0x0);
|
||||
lovrTextureRefresh(font->texture);
|
||||
|
||||
// Reset the cursor
|
||||
|
|
|
@ -734,7 +734,7 @@ void lovrGraphicsCylinder(float x1, float y1, float z1, float x2, float y2, floa
|
|||
#undef PUSH_CYLINDER_TRIANGLE
|
||||
}
|
||||
|
||||
void lovrGraphicsSphere(Texture* texture, mat4 transform, int segments, Skybox* skybox) {
|
||||
void lovrGraphicsSphere(mat4 transform, int segments) {
|
||||
vec_clear(&state.streamData);
|
||||
vec_clear(&state.streamIndices);
|
||||
|
||||
|
@ -751,11 +751,9 @@ void lovrGraphicsSphere(Texture* texture, mat4 transform, int segments, Skybox*
|
|||
vec_push(&state.streamData, y);
|
||||
vec_push(&state.streamData, z);
|
||||
|
||||
if (!skybox) {
|
||||
vec_push(&state.streamData, x);
|
||||
vec_push(&state.streamData, y);
|
||||
vec_push(&state.streamData, z);
|
||||
}
|
||||
vec_push(&state.streamData, x);
|
||||
vec_push(&state.streamData, y);
|
||||
vec_push(&state.streamData, z);
|
||||
|
||||
vec_push(&state.streamData, u);
|
||||
vec_push(&state.streamData, v);
|
||||
|
@ -777,23 +775,20 @@ void lovrGraphicsSphere(Texture* texture, mat4 transform, int segments, Skybox*
|
|||
}
|
||||
}
|
||||
|
||||
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
|
||||
|
||||
if (skybox) {
|
||||
Texture* oldTexture = lovrGraphicsGetTexture();
|
||||
glBindTexture(GL_TEXTURE_2D, skybox->texture);
|
||||
lovrGraphicsDrawPrimitive(GL_TRIANGLES, 0, 1, 1);
|
||||
glBindTexture(GL_TEXTURE_2D, oldTexture->id);
|
||||
} else {
|
||||
lovrGraphicsBindTexture(texture);
|
||||
if (transform) {
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(MATRIX_MODEL, transform);
|
||||
lovrGraphicsDrawPrimitive(GL_TRIANGLES, 1, 1, 1);
|
||||
}
|
||||
|
||||
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
|
||||
lovrGraphicsDrawPrimitive(GL_TRIANGLES, 1, 1, 1);
|
||||
|
||||
if (transform) {
|
||||
lovrGraphicsPop();
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float az) {
|
||||
void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float az) {
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsOrigin();
|
||||
lovrGraphicsRotate(MATRIX_MODEL, angle, ax, ay, az);
|
||||
|
@ -801,7 +796,7 @@ void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float a
|
|||
int wasCulling = lovrGraphicsIsCullingEnabled();
|
||||
lovrGraphicsSetCullingEnabled(0);
|
||||
|
||||
if (skybox->type == SKYBOX_CUBE) {
|
||||
if (texture->type == TEXTURE_CUBE) {
|
||||
float cube[] = {
|
||||
// Front
|
||||
1.f, -1.f, -1.f,
|
||||
|
@ -844,15 +839,14 @@ void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float a
|
|||
1.f, 1.f, 1.f
|
||||
};
|
||||
|
||||
lovrGraphicsSetShapeData(cube, 78);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->texture);
|
||||
lovrGraphicsSetDefaultShader(SHADER_SKYBOX);
|
||||
lovrGraphicsSetShapeData(cube, 78);
|
||||
lovrGraphicsBindTexture(texture);
|
||||
lovrGraphicsPrepare();
|
||||
lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, 0, 0, 0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
} else if (skybox->type == SKYBOX_PANORAMA) {
|
||||
lovrGraphicsSphere(NULL, NULL, 30, skybox);
|
||||
} else if (texture->type == TEXTURE_2D) {
|
||||
lovrGraphicsSphere(NULL, 30);
|
||||
}
|
||||
|
||||
lovrGraphicsSetCullingEnabled(wasCulling);
|
||||
|
@ -925,7 +919,8 @@ Texture* lovrGraphicsGetTexture() {
|
|||
void lovrGraphicsBindTexture(Texture* texture) {
|
||||
if (!texture) {
|
||||
if (!state.defaultTexture) {
|
||||
state.defaultTexture = lovrTextureCreate(lovrTextureDataGetBlank(1, 1, 0xff, FORMAT_RGBA));
|
||||
TextureData* textureData = lovrTextureDataGetBlank(1, 1, 0xff, FORMAT_RGBA);
|
||||
state.defaultTexture = lovrTextureCreate(TEXTURE_2D, &textureData, 1);
|
||||
}
|
||||
|
||||
texture = state.defaultTexture;
|
||||
|
@ -933,7 +928,7 @@ void lovrGraphicsBindTexture(Texture* texture) {
|
|||
|
||||
if (texture != state.texture) {
|
||||
state.texture = texture;
|
||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||
glBindTexture(texture->type, texture->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "graphics/font.h"
|
||||
#include "graphics/shader.h"
|
||||
#include "graphics/skybox.h"
|
||||
#include "graphics/texture.h"
|
||||
#include "math/math.h"
|
||||
#include "lib/glfw.h"
|
||||
|
@ -158,8 +157,8 @@ void lovrGraphicsPlane(DrawMode mode, Texture* texture, mat4 transform);
|
|||
void lovrGraphicsPlaneFullscreen(Texture* texture);
|
||||
void lovrGraphicsBox(DrawMode mode, Texture* texture, mat4 transform);
|
||||
void lovrGraphicsCylinder(float x1, float y1, float z1, float x2, float y2, float z2, float r1, float r2, int capped, int segments);
|
||||
void lovrGraphicsSphere(Texture* texture, mat4 transform, int segments, Skybox* skybox);
|
||||
void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float az);
|
||||
void lovrGraphicsSphere(mat4 transform, int segments);
|
||||
void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float az);
|
||||
void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAlign halign, VerticalAlign valign);
|
||||
|
||||
// Internal State
|
||||
|
|
|
@ -121,6 +121,7 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) {
|
|||
}
|
||||
|
||||
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
|
||||
lovrGraphicsBindTexture(NULL);
|
||||
lovrGraphicsPrepare();
|
||||
lovrGraphicsBindVertexArray(mesh->vao);
|
||||
lovrMeshBindAttributes(mesh);
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
#include "graphics/skybox.h"
|
||||
#include "lib/stb/stb_image.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
Skybox* lovrSkyboxCreate(Blob** blobs, SkyboxType type) {
|
||||
Skybox* skybox = lovrAlloc(sizeof(Skybox), lovrSkyboxDestroy);
|
||||
if (!skybox) return NULL;
|
||||
|
||||
skybox->type = type;
|
||||
|
||||
GLenum binding;
|
||||
int count;
|
||||
|
||||
if (type == SKYBOX_CUBE) {
|
||||
binding = GL_TEXTURE_CUBE_MAP;
|
||||
count = 6;
|
||||
} else {
|
||||
binding = GL_TEXTURE_2D;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
glGenTextures(1, &skybox->texture);
|
||||
glBindTexture(binding, skybox->texture);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int width, height, channels;
|
||||
stbi_set_flip_vertically_on_load(0);
|
||||
unsigned char* image = stbi_load_from_memory(blobs[i]->data, blobs[i]->size, &width, &height, &channels, 3);
|
||||
lovrAssert(image, "Could not load skybox image %d", i);
|
||||
|
||||
if (type == SKYBOX_CUBE) {
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
|
||||
free(image);
|
||||
}
|
||||
|
||||
glTexParameteri(binding, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(binding, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(binding, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(binding, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (type == SKYBOX_CUBE) {
|
||||
glTexParameteri(binding, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
return skybox;
|
||||
}
|
||||
|
||||
void lovrSkyboxDestroy(const Ref* ref) {
|
||||
Skybox* skybox = containerof(ref, Skybox);
|
||||
glDeleteTextures(1, &skybox->texture);
|
||||
free(skybox);
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#include "filesystem/blob.h"
|
||||
#include "lib/glad/glad.h"
|
||||
#include "util.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
SKYBOX_CUBE,
|
||||
SKYBOX_PANORAMA
|
||||
} SkyboxType;
|
||||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
SkyboxType type;
|
||||
GLuint texture;
|
||||
} Skybox;
|
||||
|
||||
Skybox* lovrSkyboxCreate(Blob** blobs, SkyboxType type);
|
||||
void lovrSkyboxDestroy(const Ref* ref);
|
|
@ -6,9 +6,9 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static void lovrTextureCreateStorage(Texture* texture) {
|
||||
TextureData* textureData = texture->textureData;
|
||||
TextureData* textureData = texture->slices[0];
|
||||
|
||||
if (textureData->format.compressed || !textureData->mipmaps.generated) {
|
||||
if (textureData->format.compressed || !textureData->mipmaps.generated || texture->type == TEXTURE_CUBE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -32,30 +32,50 @@ static void lovrTextureCreateStorage(Texture* texture) {
|
|||
#endif
|
||||
}
|
||||
|
||||
Texture* lovrTextureCreate(TextureData* textureData) {
|
||||
static void validateSlices(TextureType type, TextureData* slices[6], int sliceCount) {
|
||||
if (type == TEXTURE_CUBE) {
|
||||
lovrAssert(sliceCount == 6, "Cube textures must have 6 images");
|
||||
int width = slices[0]->width;
|
||||
int height = slices[0]->height;
|
||||
lovrAssert(width == height, "Cube textures must be square");
|
||||
for (int i = 1; i < sliceCount; i++) {
|
||||
int hasSameDimensions = slices[i]->width == width && slices[i]->height == height;
|
||||
lovrAssert(hasSameDimensions, "All textures in a cube texture must have the same dimensions");
|
||||
}
|
||||
} else if (type == TEXTURE_2D) {
|
||||
lovrAssert(sliceCount == 1, "2D textures can only contain a single image");
|
||||
} else {
|
||||
lovrThrow("Unknown texture type");
|
||||
}
|
||||
}
|
||||
|
||||
Texture* lovrTextureCreate(TextureType type, TextureData* slices[6], int sliceCount) {
|
||||
Texture* texture = lovrAlloc(sizeof(Texture), lovrTextureDestroy);
|
||||
if (!texture) return NULL;
|
||||
|
||||
texture->type = type;
|
||||
validateSlices(type, slices, sliceCount);
|
||||
texture->sliceCount = sliceCount;
|
||||
memcpy(texture->slices, slices, sliceCount * sizeof(TextureData*));
|
||||
texture->framebuffer = 0;
|
||||
texture->depthBuffer = 0;
|
||||
texture->textureData = textureData;
|
||||
glGenTextures(1, &texture->id);
|
||||
lovrGraphicsBindTexture(texture);
|
||||
lovrTextureCreateStorage(texture);
|
||||
lovrTextureRefresh(texture);
|
||||
lovrTextureSetFilter(texture, lovrGraphicsGetDefaultFilter());
|
||||
|
||||
lovrTextureSetWrap(texture, WRAP_REPEAT, WRAP_REPEAT);
|
||||
WrapMode wrapMode = (type == TEXTURE_CUBE) ? WRAP_CLAMP : WRAP_REPEAT;
|
||||
lovrTextureSetWrap(texture, (TextureWrap) { .s = wrapMode, .t = wrapMode, .r = wrapMode });
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProjection projection, int msaa) {
|
||||
Texture* texture = lovrTextureCreate(textureData);
|
||||
Texture* texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1);
|
||||
if (!texture) return NULL;
|
||||
|
||||
int width = texture->textureData->width;
|
||||
int height = texture->textureData->height;
|
||||
int width = texture->width;
|
||||
int height = texture->height;
|
||||
texture->projection = projection;
|
||||
texture->msaa = msaa;
|
||||
|
||||
|
@ -102,7 +122,9 @@ Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProje
|
|||
|
||||
void lovrTextureDestroy(const Ref* ref) {
|
||||
Texture* texture = containerof(ref, Texture);
|
||||
lovrTextureDataDestroy(texture->textureData);
|
||||
for (int i = 0; i < texture->sliceCount; i++) {
|
||||
lovrTextureDataDestroy(texture->slices[i]);
|
||||
}
|
||||
if (texture->framebuffer) {
|
||||
glDeleteFramebuffers(1, &texture->framebuffer);
|
||||
}
|
||||
|
@ -112,23 +134,19 @@ void lovrTextureDestroy(const Ref* ref) {
|
|||
|
||||
void lovrTextureBindFramebuffer(Texture* texture) {
|
||||
lovrAssert(texture->framebuffer, "Texture cannot be used as a canvas");
|
||||
|
||||
int w = texture->textureData->width;
|
||||
int h = texture->textureData->height;
|
||||
|
||||
lovrGraphicsBindFramebuffer(texture->framebuffer);
|
||||
lovrGraphicsSetViewport(0, 0, w, h);
|
||||
lovrGraphicsSetViewport(0, 0, texture->width, texture->height);
|
||||
|
||||
if (texture->projection == PROJECTION_ORTHOGRAPHIC) {
|
||||
float projection[16];
|
||||
mat4_orthographic(projection, 0, w, 0, h, -1, 1);
|
||||
mat4_orthographic(projection, 0, texture->width, 0, texture->height, -1, 1);
|
||||
lovrGraphicsSetProjection(projection);
|
||||
} else if (texture->projection == PROJECTION_PERSPECTIVE) {
|
||||
mat4 projection = lovrGraphicsGetProjection();
|
||||
float b = projection[5];
|
||||
float c = projection[10];
|
||||
float d = projection[14];
|
||||
float aspect = (float) w / h;
|
||||
float aspect = (float) texture->width / texture->height;
|
||||
float k = (c - 1.f) / (c + 1.f);
|
||||
float near = (d * (1.f - k)) / (2.f * k);
|
||||
float far = k * near;
|
||||
|
@ -145,51 +163,50 @@ void lovrTextureResolveMSAA(Texture* texture) {
|
|||
return;
|
||||
}
|
||||
|
||||
int w = texture->textureData->width;
|
||||
int h = texture->textureData->height;
|
||||
|
||||
int width = texture->width;
|
||||
int height = texture->height;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, texture->framebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, texture->resolveFramebuffer);
|
||||
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void lovrTextureRefresh(Texture* texture) {
|
||||
TextureData* textureData = texture->textureData;
|
||||
GLenum glInternalFormat = textureData->format.glInternalFormat;
|
||||
GLenum glFormat = textureData->format.glFormat;
|
||||
lovrGraphicsBindTexture(texture);
|
||||
|
||||
if (textureData->format.compressed) {
|
||||
Mipmap m; int i;
|
||||
vec_foreach(&textureData->mipmaps.list, m, i) {
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, m.width, m.height, 0, m.size, m.data);
|
||||
}
|
||||
} else {
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, w, h, 0, glFormat, GL_UNSIGNED_BYTE, textureData->data);
|
||||
if (textureData->mipmaps.generated) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
validateSlices(texture->type, texture->slices, texture->sliceCount);
|
||||
texture->width = texture->slices[0]->width;
|
||||
texture->height = texture->slices[0]->height;
|
||||
|
||||
for (int i = 0; i < texture->sliceCount; i++) {
|
||||
TextureData* textureData = texture->slices[i];
|
||||
GLenum glInternalFormat = textureData->format.glInternalFormat;
|
||||
GLenum glFormat = textureData->format.glFormat;
|
||||
GLenum binding = (texture->type == TEXTURE_CUBE) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + i : GL_TEXTURE_2D;
|
||||
|
||||
if (textureData->format.compressed) {
|
||||
Mipmap m; int i;
|
||||
vec_foreach(&textureData->mipmaps.list, m, i) {
|
||||
glCompressedTexImage2D(binding, i, glInternalFormat, m.width, m.height, 0, m.size, m.data);
|
||||
}
|
||||
} else {
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, w, h, 0, glFormat, GL_UNSIGNED_BYTE, textureData->data);
|
||||
if (textureData->mipmaps.generated) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D); // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lovrTextureGetHeight(Texture* texture) {
|
||||
return texture->textureData->height;
|
||||
}
|
||||
|
||||
int lovrTextureGetWidth(Texture* texture) {
|
||||
return texture->textureData->width;
|
||||
}
|
||||
|
||||
TextureFilter lovrTextureGetFilter(Texture* texture) {
|
||||
return texture->filter;
|
||||
}
|
||||
|
||||
void lovrTextureSetFilter(Texture* texture, TextureFilter filter) {
|
||||
int hasMipmaps = texture->textureData->format.compressed || texture->textureData->mipmaps.generated;
|
||||
int hasMipmaps = texture->slices[0]->format.compressed || texture->slices[0]->mipmaps.generated;
|
||||
float anisotropy = filter.mode == FILTER_ANISOTROPIC ? MAX(filter.anisotropy, 1.) : 1.;
|
||||
lovrGraphicsBindTexture(texture);
|
||||
texture->filter = filter;
|
||||
|
@ -225,15 +242,16 @@ void lovrTextureSetFilter(Texture* texture, TextureFilter filter) {
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
|
||||
}
|
||||
|
||||
void lovrTextureGetWrap(Texture* texture, WrapMode* horizontal, WrapMode* vertical) {
|
||||
*horizontal = texture->wrapHorizontal;
|
||||
*vertical = texture->wrapVertical;
|
||||
TextureWrap lovrTextureGetWrap(Texture* texture) {
|
||||
return texture->wrap;
|
||||
}
|
||||
|
||||
void lovrTextureSetWrap(Texture* texture, WrapMode horizontal, WrapMode vertical) {
|
||||
texture->wrapHorizontal = horizontal;
|
||||
texture->wrapVertical = vertical;
|
||||
void lovrTextureSetWrap(Texture* texture, TextureWrap wrap) {
|
||||
texture->wrap = wrap;
|
||||
lovrGraphicsBindTexture(texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, horizontal);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vertical);
|
||||
glTexParameteri(texture->type, GL_TEXTURE_WRAP_S, wrap.s);
|
||||
glTexParameteri(texture->type, GL_TEXTURE_WRAP_T, wrap.t);
|
||||
if (texture->type == TEXTURE_CUBE) {
|
||||
glTexParameteri(texture->type, GL_TEXTURE_WRAP_R, wrap.r);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
TEXTURE_2D = GL_TEXTURE_2D,
|
||||
TEXTURE_CUBE = GL_TEXTURE_CUBE_MAP
|
||||
} TextureType;
|
||||
|
||||
typedef enum {
|
||||
FILTER_NEAREST,
|
||||
FILTER_BILINEAR,
|
||||
|
@ -22,6 +27,12 @@ typedef enum {
|
|||
WRAP_MIRRORED_REPEAT = GL_MIRRORED_REPEAT
|
||||
} WrapMode;
|
||||
|
||||
typedef struct {
|
||||
WrapMode s;
|
||||
WrapMode t;
|
||||
WrapMode r;
|
||||
} TextureWrap;
|
||||
|
||||
typedef enum {
|
||||
PROJECTION_ORTHOGRAPHIC,
|
||||
PROJECTION_PERSPECTIVE
|
||||
|
@ -29,7 +40,11 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
TextureData* textureData;
|
||||
TextureType type;
|
||||
TextureData* slices[6];
|
||||
int sliceCount;
|
||||
int width;
|
||||
int height;
|
||||
GLuint id;
|
||||
GLuint msaaId;
|
||||
GLuint framebuffer;
|
||||
|
@ -37,22 +52,19 @@ typedef struct {
|
|||
GLuint depthBuffer;
|
||||
TextureProjection projection;
|
||||
TextureFilter filter;
|
||||
WrapMode wrapHorizontal;
|
||||
WrapMode wrapVertical;
|
||||
TextureWrap wrap;
|
||||
int msaa;
|
||||
} Texture;
|
||||
|
||||
GLenum lovrTextureGetGLFormat(TextureFormat format);
|
||||
|
||||
Texture* lovrTextureCreate(TextureData* textureData);
|
||||
Texture* lovrTextureCreate(TextureType type, TextureData* data[6], int count);
|
||||
Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProjection projection, int msaa);
|
||||
void lovrTextureDestroy(const Ref* ref);
|
||||
void lovrTextureBindFramebuffer(Texture* texture);
|
||||
void lovrTextureResolveMSAA(Texture* texture);
|
||||
void lovrTextureRefresh(Texture* texture);
|
||||
int lovrTextureGetHeight(Texture* texture);
|
||||
int lovrTextureGetWidth(Texture* texture);
|
||||
TextureFilter lovrTextureGetFilter(Texture* texture);
|
||||
void lovrTextureSetFilter(Texture* texture, TextureFilter filter);
|
||||
void lovrTextureGetWrap(Texture* texture, WrapMode* horizontal, WrapMode* vertical);
|
||||
void lovrTextureSetWrap(Texture* texture, WrapMode horizontal, WrapMode vertical);
|
||||
TextureWrap lovrTextureGetWrap(Texture* texture);
|
||||
void lovrTextureSetWrap(Texture* texture, TextureWrap wrap);
|
||||
|
|
Loading…
Reference in New Issue