mirror of https://github.com/bjornbytes/lovr.git
Equirectangular Skybox rough draft;
This commit is contained in:
parent
ac7a97fe77
commit
4feeb4d4ab
|
@ -683,8 +683,13 @@ int l_lovrGraphicsNewShader(lua_State* L) {
|
|||
int l_lovrGraphicsNewSkybox(lua_State* L) {
|
||||
void* data[6];
|
||||
size_t size[6];
|
||||
SkyboxType type;
|
||||
|
||||
if (lua_istable(L, 1)) {
|
||||
if (lua_gettop(L) == 1 && lua_type(L, 1) == LUA_TSTRING) {
|
||||
const char* filename = lua_tostring(L, 1);
|
||||
data[0] = lovrFilesystemRead(filename, size);
|
||||
type = SKYBOX_PANORAMA;
|
||||
} 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");
|
||||
}
|
||||
|
@ -700,14 +705,18 @@ int l_lovrGraphicsNewSkybox(lua_State* L) {
|
|||
data[i] = lovrFilesystemRead(filename, size + i);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
type = SKYBOX_CUBE;
|
||||
} else {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
const char* filename = luaL_checkstring(L, i + 1);
|
||||
data[i] = lovrFilesystemRead(filename, size + i);
|
||||
}
|
||||
|
||||
type = SKYBOX_CUBE;
|
||||
}
|
||||
|
||||
Skybox* skybox = lovrSkyboxCreate(data, size);
|
||||
Skybox* skybox = lovrSkyboxCreate(data, size, type);
|
||||
luax_pushtype(L, Skybox, skybox);
|
||||
lovrRelease(&skybox->ref);
|
||||
|
||||
|
|
|
@ -677,62 +677,113 @@ void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float a
|
|||
lovrGraphicsOrigin();
|
||||
lovrGraphicsRotate(angle, ax, ay, az);
|
||||
|
||||
float cube[] = {
|
||||
// Front
|
||||
1.f, -1.f, -1.f,
|
||||
1.f, 1.f, -1.f,
|
||||
-1.f, -1.f, -1.f,
|
||||
-1.f, 1.f, -1.f,
|
||||
if (skybox->type == SKYBOX_CUBE) {
|
||||
float cube[] = {
|
||||
// Front
|
||||
1.f, -1.f, -1.f,
|
||||
1.f, 1.f, -1.f,
|
||||
-1.f, -1.f, -1.f,
|
||||
-1.f, 1.f, -1.f,
|
||||
|
||||
// Left
|
||||
-1.f, 1.f, -1.f,
|
||||
-1.f, 1.f, 1.f,
|
||||
-1.f, -1.f, -1.f,
|
||||
-1.f, -1.f, 1.f,
|
||||
// Left
|
||||
-1.f, 1.f, -1.f,
|
||||
-1.f, 1.f, 1.f,
|
||||
-1.f, -1.f, -1.f,
|
||||
-1.f, -1.f, 1.f,
|
||||
|
||||
// Back
|
||||
-1.f, -1.f, 1.f,
|
||||
1.f, -1.f, 1.f,
|
||||
-1.f, 1.f, 1.f,
|
||||
1.f, 1.f, 1.f,
|
||||
// Back
|
||||
-1.f, -1.f, 1.f,
|
||||
1.f, -1.f, 1.f,
|
||||
-1.f, 1.f, 1.f,
|
||||
1.f, 1.f, 1.f,
|
||||
|
||||
// Right
|
||||
1.f, 1.f, 1.f,
|
||||
1.f, -1.f, 1.f,
|
||||
1.f, 1.f, -1.f,
|
||||
1.f, -1.f, -1.f,
|
||||
// Right
|
||||
1.f, 1.f, 1.f,
|
||||
1.f, -1.f, 1.f,
|
||||
1.f, 1.f, -1.f,
|
||||
1.f, -1.f, -1.f,
|
||||
|
||||
// Bottom
|
||||
1.f, -1.f, -1.f,
|
||||
1.f, -1.f, 1.f,
|
||||
-1.f, -1.f, -1.f,
|
||||
-1.f, -1.f, 1.f,
|
||||
// Bottom
|
||||
1.f, -1.f, -1.f,
|
||||
1.f, -1.f, 1.f,
|
||||
-1.f, -1.f, -1.f,
|
||||
-1.f, -1.f, 1.f,
|
||||
|
||||
// Adjust
|
||||
-1.f, -1.f, 1.f,
|
||||
-1.f, 1.f, -1.f,
|
||||
// Adjust
|
||||
-1.f, -1.f, 1.f,
|
||||
-1.f, 1.f, -1.f,
|
||||
|
||||
// Top
|
||||
-1.f, 1.f, -1.f,
|
||||
-1.f, 1.f, 1.f,
|
||||
1.f, 1.f, -1.f,
|
||||
1.f, 1.f, 1.f
|
||||
};
|
||||
// Top
|
||||
-1.f, 1.f, -1.f,
|
||||
-1.f, 1.f, 1.f,
|
||||
1.f, 1.f, -1.f,
|
||||
1.f, 1.f, 1.f
|
||||
};
|
||||
|
||||
lovrGraphicsSetShapeData(cube, 156);
|
||||
lovrGraphicsSetShapeData(cube, 156);
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->texture);
|
||||
glDepthMask(GL_FALSE);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->texture);
|
||||
|
||||
int wasCulling = lovrGraphicsIsCullingEnabled();
|
||||
lovrGraphicsSetCullingEnabled(0);
|
||||
lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, NULL, 0, 0, 0);
|
||||
lovrGraphicsSetCullingEnabled(wasCulling);
|
||||
int wasCulling = lovrGraphicsIsCullingEnabled();
|
||||
lovrGraphicsSetCullingEnabled(0);
|
||||
lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, NULL, 0, 0, 0);
|
||||
lovrGraphicsSetCullingEnabled(wasCulling);
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glDepthMask(GL_TRUE);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glDepthMask(GL_TRUE);
|
||||
} else if (skybox->type == SKYBOX_PANORAMA) {
|
||||
int resolution = 40;
|
||||
float sphere[8000]; // resolution * resolution * 5
|
||||
|
||||
for (int i = 0; i < resolution; i++) {
|
||||
float theta = i * M_PI / resolution;
|
||||
float sinTheta = sin(theta);
|
||||
float cosTheta = cos(theta);
|
||||
|
||||
for (int j = 0; j < resolution; j++) {
|
||||
float phi = j * 2 * M_PI / resolution;
|
||||
float sinPhi = sin(phi);
|
||||
float cosPhi = cos(phi);
|
||||
|
||||
float x = sinPhi * sinTheta;
|
||||
float y = cosTheta;
|
||||
float z = -cosPhi * sinTheta;
|
||||
float u = j / resolution;
|
||||
float v = i / resolution;
|
||||
|
||||
sphere[i * resolution + j * 5 + 0] = x;
|
||||
sphere[i * resolution + j * 5 + 1] = y;
|
||||
sphere[i * resolution + j * 5 + 2] = z;
|
||||
sphere[i * resolution + j * 5 + 3] = u;
|
||||
sphere[i * resolution + j * 5 + 4] = v;
|
||||
}
|
||||
}
|
||||
|
||||
int indices[9600]; // resolution * resolution * 6
|
||||
for (int i = 0; i < resolution; i++) {
|
||||
int offset0 = i * (resolution + 1);
|
||||
int offset1 = (i + 1) * (resolution + 1);
|
||||
for (int j = 0; j < resolution; j++) {
|
||||
int index0 = offset0 + j;
|
||||
int index1 = offset1 + j;
|
||||
indices[i * resolution + j * 6 + 0] = index0;
|
||||
indices[i * resolution + j * 6 + 1] = index1;
|
||||
indices[i * resolution + j * 6 + 2] = index0 + 1;
|
||||
indices[i * resolution + j * 6 + 3] = index1;
|
||||
indices[i * resolution + j * 6 + 4] = index1 + 1;
|
||||
indices[i * resolution + j * 6 + 5] = index0 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
lovrGraphicsSetShapeData(sphere, 8000);
|
||||
lovrGraphicsSetIndexData(indices, 9600);
|
||||
glDepthMask(GL_FALSE);
|
||||
lovrGraphicsDrawPrimitive(GL_TRIANGLES, skybox->texture, 0, 1, 1);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
lovrGraphicsSetShader(lastShader);
|
||||
lovrRelease(&lastShader->ref);
|
||||
|
|
|
@ -2,14 +2,27 @@
|
|||
#include "lib/stb/stb_image.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
Skybox* lovrSkyboxCreate(void** data, size_t* size) {
|
||||
Skybox* lovrSkyboxCreate(void** data, size_t* size, SkyboxType type) {
|
||||
Skybox* skybox = lovrAlloc(sizeof(Skybox), lovrSkyboxDestroy);
|
||||
if (!skybox) return NULL;
|
||||
|
||||
glGenTextures(1, &skybox->texture);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->texture);
|
||||
skybox->type = type;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
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(data[i], size[i], &width, &height, &channels, 3);
|
||||
|
@ -18,15 +31,23 @@ Skybox* lovrSkyboxCreate(void** data, size_t* size) {
|
|||
error("Could not load skybox image %d", i);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
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(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -3,10 +3,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
SKYBOX_CUBE,
|
||||
SKYBOX_PANORAMA
|
||||
} SkyboxType;
|
||||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
SkyboxType type;
|
||||
GLuint texture;
|
||||
} Skybox;
|
||||
|
||||
Skybox* lovrSkyboxCreate(void** data, size_t* size);
|
||||
Skybox* lovrSkyboxCreate(void** data, size_t* size, int count);
|
||||
void lovrSkyboxDestroy(const Ref* ref);
|
||||
|
|
Loading…
Reference in New Issue