Equirectangular Skybox rough draft;

This commit is contained in:
bjorn 2017-03-12 16:45:24 -07:00
parent ac7a97fe77
commit 4feeb4d4ab
4 changed files with 146 additions and 59 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);