Multiview;

This commit is contained in:
bjorn 2019-06-25 01:06:55 -07:00
parent a691192af9
commit 928ccee5f1
8 changed files with 139 additions and 97 deletions

View File

@ -409,8 +409,10 @@ static int l_lovrGraphicsGetFeatures(lua_State* L) {
lua_setfield(L, -2, "compute");
lua_pushboolean(L, features->dxt);
lua_setfield(L, -2, "dxt");
lua_pushboolean(L, features->singlepass);
lua_setfield(L, -2, "singlepass");
lua_pushboolean(L, features->instancedStereo);
lua_setfield(L, -2, "instancedstereo");
lua_pushboolean(L, features->multiview);
lua_setfield(L, -2, "multiview");
return 1;
}
@ -1093,16 +1095,16 @@ static int l_lovrGraphicsNewCanvas(lua_State* L) {
index = 3;
}
TextureFormat format = FORMAT_RGBA;
bool anonymous = attachmentCount == 0;
CanvasFlags flags = {
.depth = { .enabled = true, .readable = false, .format = FORMAT_D16 },
.stereo = true,
.stereo = anonymous,
.msaa = 0,
.mipmaps = true
};
TextureFormat format = FORMAT_RGBA;
bool anonymous = attachmentCount == 0;
if (lua_istable(L, index)) {
lua_getfield(L, index, "depth");
switch (lua_type(L, -1)) {
@ -1142,14 +1144,6 @@ static int l_lovrGraphicsNewCanvas(lua_State* L) {
}
}
if (anonymous) {
Texture* texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, true, flags.mipmaps, flags.msaa);
lovrTextureAllocate(texture, width, height, 1, format);
lovrTextureSetWrap(texture, (TextureWrap) { .s = WRAP_CLAMP, .t = WRAP_CLAMP, .r = WRAP_CLAMP });
attachments[0] = (Attachment) { texture, 0, 0 };
attachmentCount++;
}
if (width == 0 && height == 0 && attachmentCount > 0) {
width = lovrTextureGetWidth(attachments[0].texture, attachments[0].level);
height = lovrTextureGetHeight(attachments[0].texture, attachments[0].level);
@ -1157,6 +1151,14 @@ static int l_lovrGraphicsNewCanvas(lua_State* L) {
Canvas* canvas = lovrCanvasCreate(width, height, flags);
if (anonymous) {
Texture* texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, true, flags.mipmaps, flags.msaa);
lovrTextureAllocate(texture, lovrCanvasGetWidth(canvas), lovrCanvasGetHeight(canvas), 1, format);
lovrTextureSetWrap(texture, (TextureWrap) { .s = WRAP_CLAMP, .t = WRAP_CLAMP, .r = WRAP_CLAMP });
attachments[0] = (Attachment) { texture, 0, 0 };
attachmentCount++;
}
if (attachmentCount > 0) {
lovrCanvasSetAttachments(canvas, attachments, attachmentCount);
if (anonymous) {
@ -1450,6 +1452,7 @@ static void luax_parseshaderflags(lua_State* L, int index, ShaderFlag flags[MAX_
static int l_lovrGraphicsNewShader(lua_State* L) {
ShaderFlag flags[MAX_SHADER_FLAGS];
uint32_t flagCount = 0;
bool multiview = true;
Shader* shader;
if (lua_isstring(L, 1) && (lua_istable(L, 2) || lua_gettop(L) == 1)) {
@ -1459,6 +1462,10 @@ static int l_lovrGraphicsNewShader(lua_State* L) {
lua_getfield(L, 2, "flags");
luax_parseshaderflags(L, -1, flags, &flagCount);
lua_pop(L, 1);
lua_getfield(L, 2, "stereo");
multiview = lua_isnil(L, -1) ? multiview : lua_toboolean(L, -1);
lua_pop(L, 1);
}
shader = lovrShaderCreateDefault(shaderType, flags, flagCount);
@ -1472,9 +1479,13 @@ static int l_lovrGraphicsNewShader(lua_State* L) {
lua_getfield(L, 3, "flags");
luax_parseshaderflags(L, -1, flags, &flagCount);
lua_pop(L, 1);
lua_getfield(L, 2, "stereo");
multiview = lua_isnil(L, -1) ? multiview : lua_toboolean(L, -1);
lua_pop(L, 1);
}
shader = lovrShaderCreateGraphics(vertexSource, fragmentSource, flags, flagCount);
shader = lovrShaderCreateGraphics(vertexSource, fragmentSource, flags, flagCount, multiview);
}
luax_pushtype(L, Shader, shader);

View File

@ -55,7 +55,7 @@ static const size_t BUFFER_STRIDES[] = {
static const BufferType BUFFER_TYPES[] = {
[STREAM_VERTEX] = BUFFER_VERTEX,
[STREAM_INDEX] = BUFFER_INDEX,
[STREAM_DRAW_ID] = BUFFER_GENERIC,
[STREAM_DRAW_ID] = BUFFER_GENERIC, // So it doesn't thrash vertex buffer binding as much
[STREAM_TRANSFORM] = BUFFER_UNIFORM,
[STREAM_COLOR] = BUFFER_UNIFORM
};
@ -641,7 +641,7 @@ void lovrGraphicsFlush() {
.rangeCount = rangeCount,
.width = batch->canvas ? lovrCanvasGetWidth(batch->canvas) : state.width,
.height = batch->canvas ? lovrCanvasGetHeight(batch->canvas) : state.height,
.stereo = batch->type != BATCH_FILL && (batch->canvas ? lovrCanvasIsStereo(batch->canvas) : state.camera.stereo)
.stereo = batch->canvas ? lovrCanvasIsStereo(batch->canvas) : state.camera.stereo
});
}
}
@ -1147,18 +1147,18 @@ void lovrGraphicsFill(Texture* texture, float u, float v, float w, float h) {
.params.fill = { .u = u, .v = v, .w = w, .h = h },
.drawMode = DRAW_TRIANGLE_STRIP,
.shader = SHADER_FILL,
.pipeline = &pipeline,
.diffuseTexture = texture,
.pipeline = &pipeline,
.vertexCount = 4,
.vertices = &vertices
});
if (vertices) {
memcpy(vertices, (float[32]) {
-1, 1, 0, 0, 0, 0, u, v + h,
-1, -1, 0, 0, 0, 0, u, v,
1, 1, 0, 0, 0, 0, u + w, v + h,
1, -1, 0, 0, 0, 0, u + w, v
-1.f, 1.f, 0.f, 0.f, 0.f, 0.f, u, v + h,
-1.f, -1.f, 0.f, 0.f, 0.f, 0.f, u, v,
1.f, 1.f, 0.f, 0.f, 0.f, 0.f, u + w, v + h,
1.f, -1.f, 0.f, 0.f, 0.f, 0.f, u + w, v
}, 32 * sizeof(float));
}
}

View File

@ -284,7 +284,8 @@ typedef struct {
bool astc;
bool compute;
bool dxt;
bool singlepass;
bool instancedStereo;
bool multiview;
bool timers;
} GpuFeatures;

View File

@ -55,6 +55,7 @@ typedef struct {
static struct {
Texture* defaultTexture;
enum { NONE, INSTANCED_STEREO, MULTIVIEW } singlepass;
bool alphaToCoverage;
bool blendEnabled;
BlendMode blendMode;
@ -502,6 +503,10 @@ static void lovrGpuBindBlockBuffer(BlockType type, uint32_t buffer, int slot, si
block->offset = offset;
block->size = size;
glBindBufferRange(target, slot, buffer, offset, size);
// Binding to an indexed target also binds to the generic target
BufferType bufferType = type == BLOCK_UNIFORM ? BUFFER_UNIFORM : BUFFER_SHADER_STORAGE;
state.buffers[bufferType] = buffer;
}
}
@ -639,21 +644,25 @@ static void lovrGpuBindCanvas(Canvas* canvas, bool willDraw) {
GLenum buffers[MAX_CANVAS_ATTACHMENTS] = { GL_NONE };
for (uint32_t i = 0; i < canvas->attachmentCount; i++) {
GLenum buffer = buffers[i] = GL_COLOR_ATTACHMENT0 + i;
GLenum drawBuffer = buffers[i] = GL_COLOR_ATTACHMENT0 + i;
Attachment* attachment = &canvas->attachments[i];
Texture* texture = attachment->texture;
uint32_t slice = attachment->slice;
uint32_t level = attachment->level;
if (canvas->flags.msaa) {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, buffer, GL_RENDERBUFFER, texture->msaaId);
}
if (canvas->flags.stereo && state.singlepass == MULTIVIEW) {
glFramebufferTextureMultisampleMultiviewOVR(GL_READ_FRAMEBUFFER, drawBuffer, texture->id, level, canvas->flags.msaa, slice, 2);
} else {
if (canvas->flags.msaa) {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawBuffer, GL_RENDERBUFFER, texture->msaaId);
}
switch (texture->type) {
case TEXTURE_2D: glFramebufferTexture2D(GL_READ_FRAMEBUFFER, buffer, GL_TEXTURE_2D, texture->id, level); break;
case TEXTURE_CUBE: glFramebufferTexture2D(GL_READ_FRAMEBUFFER, buffer, GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice, texture->id, level); break;
case TEXTURE_ARRAY: glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, buffer, texture->id, level, slice); break;
case TEXTURE_VOLUME: glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, buffer, texture->id, level, slice); break;
switch (texture->type) {
case TEXTURE_2D: glFramebufferTexture2D(GL_READ_FRAMEBUFFER, drawBuffer, GL_TEXTURE_2D, texture->id, level); break;
case TEXTURE_CUBE: glFramebufferTexture2D(GL_READ_FRAMEBUFFER, drawBuffer, GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice, texture->id, level); break;
case TEXTURE_ARRAY: glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, drawBuffer, texture->id, level, slice); break;
case TEXTURE_VOLUME: glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, drawBuffer, texture->id, level, slice); break;
}
}
}
glDrawBuffers(canvas->attachmentCount, buffers);
@ -983,12 +992,14 @@ void lovrGpuInit(getProcAddressProc getProcAddress) {
state.features.astc = GLAD_GL_ES_VERSION_3_2;
state.features.compute = GLAD_GL_ARB_compute_shader;
state.features.dxt = GLAD_GL_EXT_texture_compression_s3tc;
state.features.singlepass = GLAD_GL_ARB_viewport_array && GLAD_GL_AMD_vertex_shader_viewport_index && GLAD_GL_ARB_fragment_layer_viewport;
state.features.instancedStereo = GLAD_GL_ARB_viewport_array && GLAD_GL_AMD_vertex_shader_viewport_index && GLAD_GL_ARB_fragment_layer_viewport;
state.features.multiview = GLAD_GL_OVR_multiview2 && GLAD_GL_OVR_multiview_multisampled_render_to_texture;
state.features.timers = GLAD_GL_VERSION_3_3 || GLAD_GL_EXT_disjoint_timer_query;
glEnable(GL_LINE_SMOOTH);
glEnable(GL_PROGRAM_POINT_SIZE);
glEnable(GL_FRAMEBUFFER_SRGB);
glGetFloatv(GL_POINT_SIZE_RANGE, state.limits.pointSizes);
state.singlepass = (state.features.multiview && GLAD_GL_ES_VERSION_3_0) ? MULTIVIEW : (state.features.instancedStereo ? INSTANCED_STEREO : NONE);
#else
glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, state.limits.pointSizes);
#endif
@ -1136,23 +1147,25 @@ void lovrGpuDiscard(Canvas* canvas, bool color, bool depth, bool stencil) {
}
void lovrGpuDraw(DrawCommand* draw) {
uint32_t viewCount = 1 + draw->stereo;
uint32_t drawCount = state.features.singlepass ? 1 : viewCount;
uint32_t viewsPerDraw = state.features.singlepass ? viewCount : 1;
uint32_t instances = MAX(draw->instances, 1) * viewsPerDraw;
lovrAssert(state.singlepass != MULTIVIEW || draw->shader->multiview == draw->canvas->flags.stereo, "Shader and Canvas multiview settings must match!");
uint32_t viewportCount = (draw->stereo && state.singlepass != MULTIVIEW) ? 2 : 1;
uint32_t drawCount = state.singlepass == NONE ? viewportCount : 1;
uint32_t instanceMultiplier = state.singlepass == INSTANCED_STEREO ? viewportCount : 1;
uint32_t viewportsPerDraw = instanceMultiplier;
uint32_t instances = MAX(draw->instances, 1) * instanceMultiplier;
float w = draw->width / (float) viewCount;
float w = state.singlepass == MULTIVIEW ? draw->width : draw->width / (float) viewportCount;
float h = draw->height;
float viewports[2][4] = { { 0, 0, w, h }, { w, 0, w, h } };
lovrShaderSetInts(draw->shader, "lovrViewportCount", &(int) { viewCount }, 0, 1);
float viewports[2][4] = { { 0.f, 0.f, w, h }, { w, 0.f, w, h } };
lovrShaderSetInts(draw->shader, "lovrViewportCount", &(int) { viewportCount }, 0, 1);
lovrGpuBindCanvas(draw->canvas, true);
lovrGpuBindPipeline(&draw->pipeline);
lovrGpuBindMesh(draw->mesh, draw->shader, viewsPerDraw);
lovrGpuBindMesh(draw->mesh, draw->shader, instanceMultiplier);
for (uint32_t i = 0; i < drawCount; i++) {
lovrGpuSetViewports(&viewports[i][0], viewsPerDraw);
lovrShaderSetInts(draw->shader, "lovrViewportIndex", &(int) { i }, 0, 1);
lovrGpuSetViewports(&viewports[i][0], viewportsPerDraw);
lovrShaderSetInts(draw->shader, "lovrViewID", &(int) { i }, 0, 1);
lovrGpuBindShader(draw->shader);
Mesh* mesh = draw->mesh;
@ -1508,6 +1521,10 @@ void lovrTextureSetWrap(Texture* texture, TextureWrap wrap) {
// Canvas
Canvas* lovrCanvasInit(Canvas* canvas, uint32_t width, uint32_t height, CanvasFlags flags) {
if (flags.stereo && state.singlepass != MULTIVIEW) {
width *= 2;
}
canvas->width = width;
canvas->height = height;
canvas->flags = flags;
@ -1518,7 +1535,11 @@ Canvas* lovrCanvasInit(Canvas* canvas, uint32_t width, uint32_t height, CanvasFl
if (flags.depth.enabled) {
lovrAssert(isTextureFormatDepth(flags.depth.format), "Canvas depth buffer can't use a color TextureFormat");
GLenum attachment = flags.depth.format == FORMAT_D24S8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
if (flags.depth.readable) {
if (flags.stereo && state.singlepass == MULTIVIEW) {
canvas->depth.texture = lovrTextureCreate(TEXTURE_ARRAY, NULL, 0, false, flags.mipmaps, flags.msaa);
lovrTextureAllocate(canvas->depth.texture, width, height, 2, flags.depth.format);
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, attachment, canvas->depth.texture->id, 0, flags.msaa, 0, 2);
} else if (flags.depth.readable) {
canvas->depth.texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, false, flags.mipmaps, flags.msaa);
lovrTextureAllocate(canvas->depth.texture, width, height, 1, flags.depth.format);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, canvas->depth.texture->id, 0);
@ -2005,33 +2026,33 @@ static char* lovrShaderGetFlagCode(ShaderFlag* flags, uint32_t flagCount) {
return code;
}
Shader* lovrShaderInitGraphics(Shader* shader, const char* vertexSource, const char* fragmentSource, ShaderFlag* flags, uint32_t flagCount) {
Shader* lovrShaderInitGraphics(Shader* shader, const char* vertexSource, const char* fragmentSource, ShaderFlag* flags, uint32_t flagCount, bool multiview) {
#if defined(LOVR_WEBGL) || defined(LOVR_GLES)
const char* vertexHeader = "#version 300 es\nprecision highp float;\nprecision highp int;\n";
const char* fragmentHeader = "#version 300 es\nprecision mediump float;\nprecision mediump int;\n";
const char* version = "#version 300 es\n";
const char* precision[2] = { "precision highp float;\nprecision highp int;\n", "precision mediump float;\nprecision mediump int;\n" };
#else
const char* vertexHeader = state.features.compute ? "#version 430\n" : "#version 150\n";
const char* fragmentHeader = "#version 150\n";
const char* version = state.features.compute ? "#version 430\n" : "#version 150\n";
const char* precision[2] = { "", "" };
#endif
const char* vertexSinglepass = state.features.singlepass ?
"#extension GL_AMD_vertex_shader_viewport_index : require\n" "#define SINGLEPASS 1\n" :
"#define SINGLEPASS 0\n";
const char* fragmentSinglepass = state.features.singlepass ?
"#extension GL_ARB_fragment_layer_viewport : require\n" "#define SINGLEPASS 1\n" :
"#define SINGLEPASS 0\n";
const char* singlepass[2] = { "", "" };
if (multiview && state.singlepass == MULTIVIEW) {
singlepass[0] = singlepass[1] = "#extension GL_OVR_multiview2 : require\n#define MULTIVIEW\n";
} else if (state.singlepass == INSTANCED_STEREO) {
singlepass[0] = "#extension GL_AMD_vertex_shader_viewport_index : require\n""#define INSTANCED_STEREO\n";
singlepass[1] = "#extension GL_AMD_fragment_layer_viewport : require\n""#define INSTANCED_STEREO\n";
}
char* flagSource = lovrShaderGetFlagCode(flags, flagCount);
// Vertex
vertexSource = vertexSource == NULL ? lovrUnlitVertexShader : vertexSource;
const char* vertexSources[] = { vertexHeader, vertexSinglepass, flagSource ? flagSource : "", lovrShaderVertexPrefix, vertexSource, lovrShaderVertexSuffix };
const char* vertexSources[] = { version, singlepass[0], precision[0], flagSource ? flagSource : "", lovrShaderVertexPrefix, vertexSource, lovrShaderVertexSuffix };
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSources, sizeof(vertexSources) / sizeof(vertexSources[0]));
// Fragment
fragmentSource = fragmentSource == NULL ? lovrUnlitFragmentShader : fragmentSource;
const char* fragmentSources[] = { fragmentHeader, fragmentSinglepass, flagSource ? flagSource : "", lovrShaderFragmentPrefix, fragmentSource, lovrShaderFragmentSuffix };
const char* fragmentSources[] = { version, singlepass[1], precision[1], flagSource ? flagSource : "", lovrShaderFragmentPrefix, fragmentSource, lovrShaderFragmentSuffix };
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSources, sizeof(fragmentSources) / sizeof(fragmentSources[0]));
free(flagSource);
@ -2077,6 +2098,8 @@ Shader* lovrShaderInitGraphics(Shader* shader, const char* vertexSource, const c
map_set(&shader->attributes, name, glGetAttribLocation(program, name));
}
shader->multiview = multiview;
return shader;
}

View File

@ -61,12 +61,12 @@ static const char* getUniformTypeName(const Uniform* uniform) {
Shader* lovrShaderInitDefault(Shader* shader, DefaultShader type, ShaderFlag* flags, uint32_t flagCount) {
switch (type) {
case SHADER_UNLIT: return lovrShaderInitGraphics(shader, NULL, NULL, flags, flagCount);
case SHADER_STANDARD: return lovrShaderInitGraphics(shader, lovrStandardVertexShader, lovrStandardFragmentShader, flags, flagCount);
case SHADER_CUBE: return lovrShaderInitGraphics(shader, lovrCubeVertexShader, lovrCubeFragmentShader, flags, flagCount);
case SHADER_PANO: return lovrShaderInitGraphics(shader, lovrCubeVertexShader, lovrPanoFragmentShader, flags, flagCount);
case SHADER_FONT: return lovrShaderInitGraphics(shader, NULL, lovrFontFragmentShader, flags, flagCount);
case SHADER_FILL: return lovrShaderInitGraphics(shader, lovrFillVertexShader, NULL, flags, flagCount);
case SHADER_UNLIT: return lovrShaderInitGraphics(shader, NULL, NULL, flags, flagCount, true);
case SHADER_STANDARD: return lovrShaderInitGraphics(shader, lovrStandardVertexShader, lovrStandardFragmentShader, flags, flagCount, true);
case SHADER_CUBE: return lovrShaderInitGraphics(shader, lovrCubeVertexShader, lovrCubeFragmentShader, flags, flagCount, true);
case SHADER_PANO: return lovrShaderInitGraphics(shader, lovrCubeVertexShader, lovrPanoFragmentShader, flags, flagCount, true);
case SHADER_FONT: return lovrShaderInitGraphics(shader, NULL, lovrFontFragmentShader, flags, flagCount, true);
case SHADER_FILL: return lovrShaderInitGraphics(shader, lovrFillVertexShader, NULL, flags, flagCount, true);
default: lovrThrow("Unknown default shader type"); return NULL;
}
}

View File

@ -117,12 +117,13 @@ typedef struct Shader {
map_int_t attributes;
map_int_t uniformMap;
map_int_t blockMap;
bool multiview;
GPU_SHADER_FIELDS
} Shader;
// Shader
Shader* lovrShaderInitGraphics(Shader* shader, const char* vertexSource, const char* fragmentSource, ShaderFlag* flags, uint32_t flagCount);
Shader* lovrShaderInitGraphics(Shader* shader, const char* vertexSource, const char* fragmentSource, ShaderFlag* flags, uint32_t flagCount, bool multiview);
Shader* lovrShaderInitCompute(Shader* shader, const char* source, ShaderFlag* flags, uint32_t flagCount);
Shader* lovrShaderInitDefault(Shader* shader, DefaultShader type, ShaderFlag* flags, uint32_t flagCount);
#define lovrShaderCreateGraphics(...) lovrShaderInitGraphics(lovrAlloc(Shader), __VA_ARGS__)

View File

@ -477,17 +477,24 @@ void bridgeLovrUpdate(BridgeLovrUpdateData *updateData) {
}
}
static void lovrOculusMobileDraw(int framebuffer, int width, int height, float *eyeViewMatrix, float *projectionMatrix) {
lovrGpuDirtyTexture();
void bridgeLovrDraw(BridgeLovrDrawData *drawData) {
lovrGpuDirtyTexture(); // Clear texture state since LÖVR doesn't completely own the GL context
// Initialize a temporary Canvas from the framebuffer handle created by lovr-oculus-mobile
Canvas canvas = { 0 };
lovrCanvasInitFromHandle(&canvas, width, height, (CanvasFlags) { 0 }, framebuffer, 0, 0, 1, true);
CanvasFlags flags = { .stereo = true };
uint32_t width = bridgeLovrMobileData.displayDimensions.width;
uint32_t height = bridgeLovrMobileData.displayDimensions.height;
lovrCanvasInitFromHandle(&canvas, width, height, flags, drawData->framebuffer, 0, 0, 1, true);
Camera camera = { .canvas = &canvas, .stereo = false };
memcpy(camera.viewMatrix[0], eyeViewMatrix, sizeof(camera.viewMatrix[0]));
mat4_translate(camera.viewMatrix[0], 0, -state.offset, 0);
memcpy(camera.projection[0], projectionMatrix, sizeof(camera.projection[0]));
// Set up a camera using the view and projection matrices from lovr-oculus-mobile
Camera camera = { .canvas = &canvas };
mat4_init(camera.viewMatrix[0], bridgeLovrMobileData.updateData.eyeViewMatrix[0]);
mat4_init(camera.viewMatrix[1], bridgeLovrMobileData.updateData.eyeViewMatrix[1]);
mat4_init(camera.projection[0], bridgeLovrMobileData.updateData.projectionMatrix[0]);
mat4_init(camera.projection[1], bridgeLovrMobileData.updateData.projectionMatrix[1]);
mat4_translate(camera.viewMatrix[0], 0.f, -state.offset, 0.f);
mat4_translate(camera.viewMatrix[1], 0.f, -state.offset, 0.f);
lovrGraphicsSetCamera(&camera, true);
@ -499,12 +506,6 @@ static void lovrOculusMobileDraw(int framebuffer, int width, int height, float *
lovrCanvasDestroy(&canvas);
}
void bridgeLovrDraw(BridgeLovrDrawData *drawData) {
int eye = drawData->eye;
lovrOculusMobileDraw(drawData->framebuffer, bridgeLovrMobileData.displayDimensions.width, bridgeLovrMobileData.displayDimensions.height,
bridgeLovrMobileData.updateData.eyeViewMatrix[eye], bridgeLovrMobileData.updateData.projectionMatrix[eye]); // Is this indexing safe?
}
// Android activity has been stopped or resumed
// In order to prevent weird dt jumps, we need to freeze and reset the clock
static bool armedUnpause;

View File

@ -4,8 +4,11 @@ const char* lovrShaderVertexPrefix = ""
"#define VERTEX VERTEX \n"
"#define MAX_BONES 48 \n"
"#define MAX_DRAWS 256 \n"
"#define lovrView lovrViews[lovrViewportIndex] \n"
"#define lovrProjection lovrProjections[lovrViewportIndex] \n"
"#ifndef FLAG_skinned \n"
"#define FLAG_skinned 0 \n"
"#endif \n"
"#define lovrView lovrViews[lovrViewID] \n"
"#define lovrProjection lovrProjections[lovrViewID] \n"
"#define lovrModel lovrModels[lovrDrawID] \n"
"#define lovrTransform (lovrView * lovrModel) \n"
"#define lovrNormalMatrix mat3(transpose(inverse(lovrTransform))) \n"
@ -35,13 +38,13 @@ const char* lovrShaderVertexPrefix = ""
"uniform float lovrPointSize; \n"
"uniform mat4 lovrPose[MAX_BONES]; \n"
"uniform int lovrViewportCount; \n"
"#if SINGLEPASS \n"
"#define lovrViewportIndex gl_ViewportIndex \n"
"#if defined MULTIVIEW \n"
"layout(num_views = 2) in; \n"
"#define lovrViewID gl_ViewID_OVR \n"
"#elif defined INSTANCED_STEREO \n"
"#define lovrViewID gl_ViewportIndex \n"
"#else \n"
"uniform int lovrViewportIndex; \n"
"#endif \n"
"#ifndef FLAG_skinned \n"
"#define FLAG_skinned false \n"
"uniform int lovrViewID; \n"
"#endif \n"
"#line 0 \n";
@ -50,14 +53,14 @@ const char* lovrShaderVertexSuffix = ""
" texCoord = (lovrMaterialTransform * vec3(lovrTexCoord, 1.)).xy; \n"
" vertexColor = lovrVertexColor; \n"
" lovrColor = lovrColors[lovrDrawID]; \n"
"#if SINGLEPASS \n"
"#if defined INSTANCED_STEREO \n"
" gl_ViewportIndex = gl_InstanceID % lovrViewportCount; \n"
"#endif \n"
" gl_PointSize = lovrPointSize; \n"
" vec4 vertexPosition = vec4(lovrPosition, 1.); \n"
" if (FLAG_skinned) { \n"
" vertexPosition = lovrPoseMatrix * vertexPosition; \n"
" } \n"
"#if FLAG_skinned \n"
" vertexPosition = lovrPoseMatrix * vertexPosition; \n"
"#endif \n"
" gl_Position = position(lovrProjection, lovrTransform, vertexPosition); \n"
"}";
@ -80,10 +83,12 @@ const char* lovrShaderFragmentPrefix = ""
"uniform sampler2D lovrNormalTexture; \n"
"uniform samplerCube lovrEnvironmentTexture; \n"
"uniform int lovrViewportCount; \n"
"#if SINGLEPASS \n"
"#define lovrViewportIndex gl_ViewportIndex \n"
"#if defined MULTIVIEW \n"
"#define lovrViewID gl_ViewID_OVR \n"
"#elif defined INSTANCED_STEREO \n"
"#define lovrViewID gl_ViewportIndex \n"
"#else \n"
"uniform int lovrViewportIndex; \n"
"uniform int lovrViewID; \n"
"#endif \n"
"#line 0 \n";
@ -207,21 +212,21 @@ const char* lovrStandardFragmentShader = ""
const char* lovrCubeVertexShader = ""
"out vec3 texturePosition[2]; \n"
"vec4 position(mat4 projection, mat4 transform, vec4 vertex) { \n"
" texturePosition[lovrViewportIndex] = inverse(mat3(transform)) * (inverse(projection) * vertex).xyz; \n"
" texturePosition[lovrViewID] = inverse(mat3(transform)) * (inverse(projection) * vertex).xyz; \n"
" return vertex; \n"
"}";
const char* lovrCubeFragmentShader = ""
"in vec3 texturePosition[2]; \n"
"vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n"
" return graphicsColor * texture(lovrEnvironmentTexture, texturePosition[lovrViewportIndex] * vec3(-1, 1, 1)); \n"
" return graphicsColor * texture(lovrEnvironmentTexture, texturePosition[lovrViewID] * vec3(-1, 1, 1)); \n"
"}";
const char* lovrPanoFragmentShader = ""
"in vec3 texturePosition[2]; \n"
"#define PI 3.141592653589 \n"
"vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n"
" vec3 direction = texturePosition[lovrViewportIndex]; \n"
" vec3 direction = texturePosition[lovrViewID]; \n"
" float theta = acos(-direction.y / length(direction)); \n"
" float phi = atan(direction.x, -direction.z); \n"
" uv = vec2(.5 + phi / (2. * PI), theta / PI); \n"