mirror of https://github.com/bjornbytes/lovr.git
Use single pass stereo rendering when supported;
This commit is contained in:
parent
7d5f2ba75a
commit
2dc79a48a8
|
@ -121,13 +121,14 @@ void lovrGraphicsSetCamera(Camera* camera, bool clear) {
|
||||||
if (!camera) {
|
if (!camera) {
|
||||||
int width, height;
|
int width, height;
|
||||||
lovrGraphicsGetDimensions(&width, &height);
|
lovrGraphicsGetDimensions(&width, &height);
|
||||||
|
state.camera.stereo = false;
|
||||||
state.camera.canvas = NULL;
|
state.camera.canvas = NULL;
|
||||||
state.camera.viewport[0] = 0;
|
state.camera.viewport[0][0] = 0;
|
||||||
state.camera.viewport[1] = 0;
|
state.camera.viewport[0][1] = 0;
|
||||||
state.camera.viewport[2] = width;
|
state.camera.viewport[0][2] = width;
|
||||||
state.camera.viewport[3] = height;
|
state.camera.viewport[0][3] = height;
|
||||||
mat4_identity(state.camera.viewMatrix);
|
mat4_identity(state.camera.viewMatrix[0]);
|
||||||
mat4_perspective(state.camera.projection, .01f, 100.f, 67 * M_PI / 180., (float) width / height);
|
mat4_perspective(state.camera.projection[0], .01f, 100.f, 67 * M_PI / 180., (float) width / height);
|
||||||
} else {
|
} else {
|
||||||
state.camera = *camera;
|
state.camera = *camera;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,10 +81,11 @@ typedef struct {
|
||||||
} GraphicsStats;
|
} GraphicsStats;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
bool stereo;
|
||||||
Canvas* canvas;
|
Canvas* canvas;
|
||||||
uint32_t viewport[4];
|
float viewport[2][4];
|
||||||
float viewMatrix[16];
|
float viewMatrix[2][16];
|
||||||
float projection[16];
|
float projection[2][16];
|
||||||
} Camera;
|
} Camera;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -57,8 +57,9 @@ static struct {
|
||||||
Texture* textures[MAX_TEXTURES];
|
Texture* textures[MAX_TEXTURES];
|
||||||
uint32_t vertexArray;
|
uint32_t vertexArray;
|
||||||
uint32_t vertexBuffer;
|
uint32_t vertexBuffer;
|
||||||
uint32_t viewport[4];
|
float viewport[4];
|
||||||
bool srgb;
|
bool srgb;
|
||||||
|
bool supportsSinglepass;
|
||||||
GraphicsLimits limits;
|
GraphicsLimits limits;
|
||||||
GraphicsStats stats;
|
GraphicsStats stats;
|
||||||
} state;
|
} state;
|
||||||
|
@ -371,9 +372,9 @@ static void lovrGpuBindVertexBuffer(uint32_t vertexBuffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lovrGpuSetViewport(uint32_t viewport[4]) {
|
static void lovrGpuSetViewport(float viewport[4]) {
|
||||||
if (memcmp(state.viewport, viewport, 4 * sizeof(uint32_t))) {
|
if (memcmp(state.viewport, viewport, 4 * sizeof(float))) {
|
||||||
memcpy(state.viewport, viewport, 4 * sizeof(uint32_t));
|
memcpy(state.viewport, viewport, 4 * sizeof(float));
|
||||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,6 +401,7 @@ void lovrGpuInit(bool srgb, gpuProc (*getProcAddress)(const char*)) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
state.srgb = srgb;
|
state.srgb = srgb;
|
||||||
|
state.supportsSinglepass = GLAD_GL_ARB_viewport_array && GLAD_GL_NV_viewport_array2 && GLAD_GL_NV_stereo_view_rendering;
|
||||||
state.blendMode = -1;
|
state.blendMode = -1;
|
||||||
state.blendAlphaMode = -1;
|
state.blendAlphaMode = -1;
|
||||||
state.culling = false;
|
state.culling = false;
|
||||||
|
@ -626,28 +628,35 @@ void lovrGpuDraw(DrawCommand* command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform
|
// Transform
|
||||||
lovrShaderSetMatrix(shader, "lovrProjection", command->camera.projection, 16);
|
|
||||||
lovrShaderSetMatrix(shader, "lovrView", command->camera.viewMatrix, 16);
|
|
||||||
lovrShaderSetMatrix(shader, "lovrModel", command->transform, 16);
|
lovrShaderSetMatrix(shader, "lovrModel", command->transform, 16);
|
||||||
|
lovrShaderSetMatrix(shader, "lovrViews", command->camera.viewMatrix, 32);
|
||||||
|
lovrShaderSetMatrix(shader, "lovrProjections", command->camera.projection, 32);
|
||||||
|
|
||||||
float modelView[16];
|
float modelView[32];
|
||||||
mat4_multiply(mat4_set(modelView, command->camera.viewMatrix), command->transform);
|
mat4_multiply(mat4_set(modelView, command->camera.viewMatrix[0]), command->transform);
|
||||||
lovrShaderSetMatrix(shader, "lovrTransform", modelView, 16);
|
mat4_multiply(mat4_set(modelView + 16, command->camera.viewMatrix[1]), command->transform);
|
||||||
|
lovrShaderSetMatrix(shader, "lovrTransforms", modelView, 32);
|
||||||
|
|
||||||
if (lovrShaderHasUniform(shader, "lovrNormalMatrix")) {
|
if (lovrShaderHasUniform(shader, "lovrNormalMatrices")) {
|
||||||
if (mat4_invert(modelView)) {
|
if (mat4_invert(modelView) && mat4_invert(modelView + 16)) {
|
||||||
mat4_transpose(modelView);
|
mat4_transpose(modelView);
|
||||||
|
mat4_transpose(modelView + 16);
|
||||||
} else {
|
} else {
|
||||||
mat4_identity(modelView);
|
mat4_identity(modelView);
|
||||||
|
mat4_identity(modelView + 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
float normalMatrix[9] = {
|
float normalMatrices[18] = {
|
||||||
modelView[0], modelView[1], modelView[2],
|
modelView[0], modelView[1], modelView[2],
|
||||||
modelView[4], modelView[5], modelView[6],
|
modelView[4], modelView[5], modelView[6],
|
||||||
modelView[8], modelView[9], modelView[10],
|
modelView[8], modelView[9], modelView[10],
|
||||||
|
|
||||||
|
modelView[16], modelView[17], modelView[18],
|
||||||
|
modelView[20], modelView[21], modelView[22],
|
||||||
|
modelView[24], modelView[25], modelView[26]
|
||||||
};
|
};
|
||||||
|
|
||||||
lovrShaderSetMatrix(shader, "lovrNormalMatrix", normalMatrix, 9);
|
lovrShaderSetMatrix(shader, "lovrNormalMatrices", normalMatrices, 18);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pose
|
// Pose
|
||||||
|
@ -718,47 +727,55 @@ void lovrGpuDraw(DrawCommand* command) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Viewport
|
|
||||||
if (pipeline->canvasCount > 0) {
|
|
||||||
int width = lovrTextureGetWidth((Texture*) pipeline->canvas[0], 0);
|
|
||||||
int height = lovrTextureGetHeight((Texture*) pipeline->canvas[0], 0);
|
|
||||||
lovrGpuSetViewport((uint32_t[4]) { 0, 0, width, height });
|
|
||||||
} else {
|
|
||||||
lovrGpuSetViewport(command->camera.viewport);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind uniforms
|
|
||||||
lovrShaderBind(shader);
|
|
||||||
|
|
||||||
// Bind attributes
|
// Bind attributes
|
||||||
lovrMeshBind(mesh, shader);
|
lovrMeshBind(mesh, shader);
|
||||||
|
|
||||||
// Draw (TODEW)
|
bool stereo = pipeline->canvasCount == 0 && command->camera.stereo == true;
|
||||||
uint32_t rangeStart, rangeCount;
|
int drawCount = 1 + (stereo == true && !state.supportsSinglepass);
|
||||||
lovrMeshGetDrawRange(mesh, &rangeStart, &rangeCount);
|
|
||||||
uint32_t indexCount;
|
|
||||||
size_t indexSize;
|
|
||||||
lovrMeshReadIndices(mesh, &indexCount, &indexSize);
|
|
||||||
GLenum glDrawMode = convertMeshDrawMode(lovrMeshGetDrawMode(mesh));
|
|
||||||
if (indexCount > 0) {
|
|
||||||
size_t count = rangeCount ? rangeCount : indexCount;
|
|
||||||
GLenum indexType = indexSize == sizeof(uint16_t) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
|
||||||
size_t offset = rangeStart * indexSize;
|
|
||||||
if (instances > 1) {
|
|
||||||
glDrawElementsInstanced(glDrawMode, count, indexType, (GLvoid*) offset, instances);
|
|
||||||
} else {
|
|
||||||
glDrawElements(glDrawMode, count, indexType, (GLvoid*) offset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
size_t count = rangeCount ? rangeCount : lovrMeshGetVertexCount(mesh);
|
|
||||||
if (instances > 1) {
|
|
||||||
glDrawArraysInstanced(glDrawMode, rangeStart, count, instances);
|
|
||||||
} else {
|
|
||||||
glDrawArrays(glDrawMode, rangeStart, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.stats.drawCalls++;
|
// Draw (TODEW)
|
||||||
|
for (int i = 0; i < drawCount; i++) {
|
||||||
|
if (pipeline->canvasCount > 0) {
|
||||||
|
int width = lovrTextureGetWidth((Texture*) pipeline->canvas[0], 0);
|
||||||
|
int height = lovrTextureGetHeight((Texture*) pipeline->canvas[0], 0);
|
||||||
|
lovrGpuSetViewport((float[4]) { 0, 0, width, height });
|
||||||
|
} else if (state.supportsSinglepass) {
|
||||||
|
glViewportArrayv(0, 2, command->camera.viewport);
|
||||||
|
} else {
|
||||||
|
lovrGpuSetViewport(command->camera.viewport[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind uniforms
|
||||||
|
int eye = (stereo && state.supportsSinglepass) ? -1 : i;
|
||||||
|
lovrShaderSetInt(shader, "lovrEye", &eye, 1);
|
||||||
|
lovrShaderBind(shader);
|
||||||
|
|
||||||
|
uint32_t rangeStart, rangeCount;
|
||||||
|
lovrMeshGetDrawRange(mesh, &rangeStart, &rangeCount);
|
||||||
|
uint32_t indexCount;
|
||||||
|
size_t indexSize;
|
||||||
|
lovrMeshReadIndices(mesh, &indexCount, &indexSize);
|
||||||
|
GLenum glDrawMode = convertMeshDrawMode(lovrMeshGetDrawMode(mesh));
|
||||||
|
if (indexCount > 0) {
|
||||||
|
size_t count = rangeCount ? rangeCount : indexCount;
|
||||||
|
GLenum indexType = indexSize == sizeof(uint16_t) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||||
|
size_t offset = rangeStart * indexSize;
|
||||||
|
if (instances > 1) {
|
||||||
|
glDrawElementsInstanced(glDrawMode, count, indexType, (GLvoid*) offset, instances);
|
||||||
|
} else {
|
||||||
|
glDrawElements(glDrawMode, count, indexType, (GLvoid*) offset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t count = rangeCount ? rangeCount : lovrMeshGetVertexCount(mesh);
|
||||||
|
if (instances > 1) {
|
||||||
|
glDrawArraysInstanced(glDrawMode, rangeStart, count, instances);
|
||||||
|
} else {
|
||||||
|
glDrawArrays(glDrawMode, rangeStart, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.stats.drawCalls++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGpuPresent() {
|
void lovrGpuPresent() {
|
||||||
|
|
|
@ -277,7 +277,6 @@ static ModelData* fakeControllerNewModelData(Controller* controller) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
static void fakeRenderTo(void (*callback)(void*), void* userdata) {
|
static void fakeRenderTo(void (*callback)(void*), void* userdata) {
|
||||||
if (!state.window || !state.mirrored) {
|
if (!state.window || !state.mirrored) {
|
||||||
return;
|
return;
|
||||||
|
@ -285,20 +284,24 @@ static void fakeRenderTo(void (*callback)(void*), void* userdata) {
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
fakeGetDisplayDimensions(&width, &height);
|
fakeGetDisplayDimensions(&width, &height);
|
||||||
Camera camera = { .viewport = { 0, 0, width, height } };
|
Camera camera = {
|
||||||
|
.stereo = true,
|
||||||
mat4_perspective(camera.projection, state.clipNear, state.clipFar, 67 * M_PI / 180., (float) width / height);
|
.canvas = NULL,
|
||||||
mat4_identity(camera.viewMatrix);
|
.viewport = {
|
||||||
mat4_translate(camera.viewMatrix, 0, state.offset, 0);
|
{ 0, 0, width, height },
|
||||||
mat4_multiply(camera.viewMatrix, state.transform);
|
{ width, 0, width, height }
|
||||||
mat4_invert(camera.viewMatrix);
|
}
|
||||||
|
};
|
||||||
for (int eye = 0; eye < 2; eye++) {
|
|
||||||
camera.viewport[0] = width * eye;
|
|
||||||
lovrGraphicsSetCamera(&camera, eye == 0);
|
|
||||||
callback(userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mat4_perspective(camera.projection[0], state.clipNear, state.clipFar, 67 * M_PI / 180., (float) width / height);
|
||||||
|
mat4_identity(camera.viewMatrix[0]);
|
||||||
|
mat4_translate(camera.viewMatrix[0], 0, state.offset, 0);
|
||||||
|
mat4_multiply(camera.viewMatrix[0], state.transform);
|
||||||
|
mat4_invert(camera.viewMatrix[0]);
|
||||||
|
mat4_set(camera.projection[1], camera.projection[0]);
|
||||||
|
mat4_set(camera.viewMatrix[1], camera.viewMatrix[0]);
|
||||||
|
lovrGraphicsSetCamera(&camera, true);
|
||||||
|
callback(userdata);
|
||||||
lovrGraphicsSetCamera(NULL, false);
|
lovrGraphicsSetCamera(NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -669,26 +669,30 @@ static void openvrRenderTo(void (*callback)(void*), void* userdata) {
|
||||||
mat4_fromMat34(head, state.renderPoses[state.headsetIndex].mDeviceToAbsoluteTracking.m);
|
mat4_fromMat34(head, state.renderPoses[state.headsetIndex].mDeviceToAbsoluteTracking.m);
|
||||||
|
|
||||||
Camera camera = {
|
Camera camera = {
|
||||||
|
.stereo = true,
|
||||||
.canvas = state.canvas,
|
.canvas = state.canvas,
|
||||||
.viewport = { 0, 0, state.renderWidth, state.renderHeight }
|
.viewport = {
|
||||||
|
{ 0, 0, state.renderWidth, state.renderHeight },
|
||||||
|
{ state.renderWidth, 0, state.renderWidth, state.renderHeight }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
EVREye vrEye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;
|
EVREye vrEye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;
|
||||||
mat4_fromMat44(camera.projection, state.system->GetProjectionMatrix(vrEye, state.clipNear, state.clipFar).m);
|
mat4_fromMat44(camera.projection[i], state.system->GetProjectionMatrix(vrEye, state.clipNear, state.clipFar).m);
|
||||||
mat4_identity(camera.viewMatrix);
|
mat4_identity(camera.viewMatrix[i]);
|
||||||
mat4_translate(camera.viewMatrix, 0, state.offset, 0);
|
mat4_translate(camera.viewMatrix[i], 0, state.offset, 0);
|
||||||
mat4_multiply(camera.viewMatrix, head);
|
mat4_multiply(camera.viewMatrix[i], head);
|
||||||
mat4_multiply(camera.viewMatrix, mat4_fromMat34(eye, state.system->GetEyeToHeadTransform(vrEye).m));
|
mat4_multiply(camera.viewMatrix[i], mat4_fromMat34(eye, state.system->GetEyeToHeadTransform(vrEye).m));
|
||||||
mat4_invert(camera.viewMatrix);
|
mat4_invert(camera.viewMatrix[i]);
|
||||||
|
|
||||||
camera.viewport[0] = state.renderWidth * i;
|
|
||||||
lovrGraphicsSetCamera(&camera, i == 0);
|
|
||||||
callback(userdata);
|
|
||||||
lovrGraphicsSetCanvas(NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lovrGraphicsSetCamera(&camera, true);
|
||||||
|
callback(userdata);
|
||||||
|
lovrGraphicsSetCamera(NULL, false);
|
||||||
|
lovrGraphicsSetCanvas(NULL, 0);
|
||||||
lovrCanvasResolve(state.canvas);
|
lovrCanvasResolve(state.canvas);
|
||||||
|
state.isRendering = false;
|
||||||
|
|
||||||
// Submit
|
// Submit
|
||||||
uintptr_t texture = (uintptr_t) lovrTextureGetId((Texture*) state.canvas);
|
uintptr_t texture = (uintptr_t) lovrTextureGetId((Texture*) state.canvas);
|
||||||
|
@ -700,9 +704,6 @@ static void openvrRenderTo(void (*callback)(void*), void* userdata) {
|
||||||
state.compositor->Submit(EVREye_Eye_Right, &eyeTexture, &right, EVRSubmitFlags_Submit_Default);
|
state.compositor->Submit(EVREye_Eye_Right, &eyeTexture, &right, EVRSubmitFlags_Submit_Default);
|
||||||
lovrGpuDirtyTexture(0);
|
lovrGpuDirtyTexture(0);
|
||||||
|
|
||||||
lovrGraphicsSetCamera(NULL, false);
|
|
||||||
state.isRendering = false;
|
|
||||||
|
|
||||||
if (state.isMirrored) {
|
if (state.isMirrored) {
|
||||||
lovrGraphicsPushPipeline();
|
lovrGraphicsPushPipeline();
|
||||||
lovrGraphicsSetColor((Color) { 1, 1, 1, 1 });
|
lovrGraphicsSetColor((Color) { 1, 1, 1, 1 });
|
||||||
|
|
|
@ -89,14 +89,22 @@ static void onMountChanged(bool mounted) {
|
||||||
static void onFrame(float* leftView, float* rightView, float* leftProjection, float* rightProjection, void* userdata) {
|
static void onFrame(float* leftView, float* rightView, float* leftProjection, float* rightProjection, void* userdata) {
|
||||||
int width, height;
|
int width, height;
|
||||||
webvrGetDisplayDimensions(&width, &height);
|
webvrGetDisplayDimensions(&width, &height);
|
||||||
Camera camera = { .viewport = { 0, 0, width, height } };
|
|
||||||
for (int eye = 0; eye < 2; eye++) {
|
Camera camera = {
|
||||||
camera.viewport[0] = width * eye;
|
.stereo = true,
|
||||||
memcpy(camera.projection, eye == 0 ? leftProjection : rightProjection);
|
.canvas = NULL,
|
||||||
memcpy(camera.viewMatrix, eye == 0 ? leftView : rightView);
|
.viewport = {
|
||||||
lovrGraphicsSetCamera(&camera, eye == 0);
|
{ 0, 0, width, height },
|
||||||
state.renderCallback(userdata);
|
{ width, 0, width, height }
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(camera.projection[0], leftProjection);
|
||||||
|
memcpy(camera.projection[1], rightProjection);
|
||||||
|
memcpy(camera.viewMatrix[0], leftView);
|
||||||
|
memcpy(camera.viewMatrix[1], rightView);
|
||||||
|
lovrGraphicsSetCamera(&camera, true);
|
||||||
|
state.renderCallback(userdata);
|
||||||
lovrGraphicsSetCamera(NULL, false);
|
lovrGraphicsSetCamera(NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,15 @@ const char* lovrShaderVertexPrefix = ""
|
||||||
"precision mediump float; \n"
|
"precision mediump float; \n"
|
||||||
#else
|
#else
|
||||||
"#version 150 \n"
|
"#version 150 \n"
|
||||||
|
"#extension GL_NV_viewport_array2 : enable \n"
|
||||||
|
"#extension GL_NV_stereo_view_rendering : enable \n"
|
||||||
#endif
|
#endif
|
||||||
"#define VERTEX VERTEX \n"
|
"#define VERTEX VERTEX \n"
|
||||||
"#define MAX_BONES 48 \n"
|
"#define MAX_BONES 48 \n"
|
||||||
|
"#define lovrView lovrViews[lovrEye] \n"
|
||||||
|
"#define lovrProjection lovrProjections[lovrEye] \n"
|
||||||
|
"#define lovrTransform lovrTransforms[lovrEye] \n"
|
||||||
|
"#define lovrNormalMatrix lovrNormalMatrices[lovrEye] \n"
|
||||||
"in vec3 lovrPosition; \n"
|
"in vec3 lovrPosition; \n"
|
||||||
"in vec3 lovrNormal; \n"
|
"in vec3 lovrNormal; \n"
|
||||||
"in vec2 lovrTexCoord; \n"
|
"in vec2 lovrTexCoord; \n"
|
||||||
|
@ -38,11 +44,12 @@ const char* lovrShaderVertexPrefix = ""
|
||||||
"in vec4 lovrBoneWeights; \n"
|
"in vec4 lovrBoneWeights; \n"
|
||||||
"out vec2 texCoord; \n"
|
"out vec2 texCoord; \n"
|
||||||
"out vec4 vertexColor; \n"
|
"out vec4 vertexColor; \n"
|
||||||
|
"uniform int lovrEye; \n"
|
||||||
"uniform mat4 lovrModel; \n"
|
"uniform mat4 lovrModel; \n"
|
||||||
"uniform mat4 lovrView; \n"
|
"uniform mat4 lovrViews[2]; \n"
|
||||||
"uniform mat4 lovrProjection; \n"
|
"uniform mat4 lovrProjections[2]; \n"
|
||||||
"uniform mat4 lovrTransform; \n"
|
"uniform mat4 lovrTransforms[2]; \n"
|
||||||
"uniform mat3 lovrNormalMatrix; \n"
|
"uniform mat3 lovrNormalMatrices[2]; \n"
|
||||||
"uniform mat3 lovrMaterialTransform; \n"
|
"uniform mat3 lovrMaterialTransform; \n"
|
||||||
"uniform float lovrPointSize; \n"
|
"uniform float lovrPointSize; \n"
|
||||||
"uniform mat4 lovrPose[MAX_BONES]; \n"
|
"uniform mat4 lovrPose[MAX_BONES]; \n"
|
||||||
|
@ -85,6 +92,15 @@ const char* lovrShaderVertexSuffix = ""
|
||||||
" lovrPose[lovrBones[2]] * lovrBoneWeights[2] + \n"
|
" lovrPose[lovrBones[2]] * lovrBoneWeights[2] + \n"
|
||||||
" lovrPose[lovrBones[3]] * lovrBoneWeights[3]; \n"
|
" lovrPose[lovrBones[3]] * lovrBoneWeights[3]; \n"
|
||||||
" gl_PointSize = lovrPointSize; \n"
|
" gl_PointSize = lovrPointSize; \n"
|
||||||
|
"#if defined(GL_NV_viewport_array2) && defined(GL_NV_stereo_view_rendering) \n"
|
||||||
|
" if (lovrEye < 0) { \n"
|
||||||
|
" gl_Position = position(lovrProjections[0], lovrTransforms[0], pose * vec4(lovrPosition, 1.0)); \n"
|
||||||
|
" gl_SecondaryPositionNV = position(lovrProjections[1], lovrTransforms[1], pose * vec4(lovrPosition, 1.0)); \n"
|
||||||
|
" gl_ViewportMask[0] = (1 << 0); \n"
|
||||||
|
" gl_SecondaryViewportMaskNV[0] = (1 << 1); \n"
|
||||||
|
" return; \n"
|
||||||
|
" }\n"
|
||||||
|
"#endif \n"
|
||||||
" gl_Position = position(lovrProjection, lovrTransform, pose * vec4(lovrPosition, 1.0)); \n"
|
" gl_Position = position(lovrProjection, lovrTransform, pose * vec4(lovrPosition, 1.0)); \n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue