mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 19:55:07 +02:00
BRingin back the stereo code path
This commit is contained in:
parent
15ee56a50f
commit
5bdfceebc5
9 changed files with 225 additions and 34 deletions
|
@ -306,11 +306,20 @@ void GLBackend::render(const Batch& batch) {
|
|||
renderPassTransfer(batch);
|
||||
}
|
||||
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
if (_stereo._enable) {
|
||||
glEnable(GL_CLIP_DISTANCE0);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render");
|
||||
renderPassDraw(batch);
|
||||
}
|
||||
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
if (_stereo._enable) {
|
||||
glDisable(GL_CLIP_DISTANCE0);
|
||||
}
|
||||
#endif
|
||||
// Restore the saved stereo state for the next batch
|
||||
_stereo._enable = savedStereo;
|
||||
}
|
||||
|
@ -325,6 +334,23 @@ void GLBackend::syncCache() {
|
|||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||
void GLBackend::setupStereoSide(int side) {
|
||||
ivec4 vp = _transform._viewport;
|
||||
vp.z /= 2;
|
||||
glViewport(vp.x + side * vp.z, vp.y, vp.z, vp.w);
|
||||
|
||||
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||
glVertexAttribI1i(14, side);
|
||||
#endif
|
||||
#else
|
||||
_transform.bindCurrentCamera(side);
|
||||
#endif
|
||||
|
||||
}
|
||||
#else
|
||||
void GLBackend::setupStereoSide(int side) {
|
||||
ivec4 vp = _transform._viewport;
|
||||
vp.z /= 2;
|
||||
|
@ -332,6 +358,7 @@ void GLBackend::setupStereoSide(int side) {
|
|||
|
||||
_transform.bindCurrentCamera(side);
|
||||
}
|
||||
#endif
|
||||
|
||||
void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) {
|
||||
resetStages();
|
||||
|
@ -384,8 +411,11 @@ void GLBackend::do_popProfileRange(const Batch& batch, size_t paramOffset) {
|
|||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
|
||||
// As long as we don;t use several versions of shaders we can avoid this more complex code path
|
||||
// #define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(shaderUniformLoc, isStereo());
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
#define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(shaderUniformLoc, isStereo())
|
||||
#else
|
||||
#define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc
|
||||
#endif
|
||||
|
||||
void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) {
|
||||
if (_pipeline._program == 0) {
|
||||
|
|
|
@ -29,6 +29,28 @@
|
|||
|
||||
#include "GLShared.h"
|
||||
|
||||
|
||||
// Pick one from the 3: THis version is the most efficient as of now
|
||||
#define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
|
||||
//#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
|
||||
//#define GPU_STEREO_TECHNIQUE_INSTANCED
|
||||
|
||||
|
||||
// Let these be configured by the one define picked above
|
||||
#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
|
||||
#define GPU_STEREO_DRAWCALL_DOUBLED
|
||||
#endif
|
||||
|
||||
#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
|
||||
#define GPU_STEREO_DRAWCALL_DOUBLED
|
||||
#define GPU_STEREO_CAMERA_BUFFER
|
||||
#endif
|
||||
|
||||
#ifdef GPU_STEREO_TECHNIQUE_INSTANCED
|
||||
#define GPU_STEREO_DRAWCALL_INSTANCED
|
||||
#define GPU_STEREO_CAMERA_BUFFER
|
||||
#endif
|
||||
|
||||
namespace gpu { namespace gl {
|
||||
|
||||
class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend> {
|
||||
|
@ -202,7 +224,10 @@ protected:
|
|||
|
||||
void renderPassTransfer(const Batch& batch);
|
||||
void renderPassDraw(const Batch& batch);
|
||||
|
||||
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||
void setupStereoSide(int side);
|
||||
#endif
|
||||
|
||||
virtual void initInput() final;
|
||||
virtual void killInput() final;
|
||||
|
@ -260,7 +285,19 @@ protected:
|
|||
};
|
||||
|
||||
struct TransformStageState {
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
struct Cameras {
|
||||
TransformCamera _cams[2];
|
||||
|
||||
Cameras() {};
|
||||
Cameras(const TransformCamera& cam) { memcpy(_cams, &cam, sizeof(TransformCamera)); };
|
||||
Cameras(const TransformCamera& camL, const TransformCamera& camR) { memcpy(_cams, &camL, sizeof(TransformCamera)); memcpy(_cams + 1, &camR, sizeof(TransformCamera)); };
|
||||
};
|
||||
|
||||
using CameraBufferElement = Cameras;
|
||||
#else
|
||||
using CameraBufferElement = TransformCamera;
|
||||
#endif
|
||||
using TransformCameras = std::vector<CameraBufferElement>;
|
||||
|
||||
TransformCamera _camera;
|
||||
|
|
|
@ -187,7 +187,11 @@ void GLBackend::updateInput() {
|
|||
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
||||
glVertexAttribBinding(slot + locNum, attrib._channel);
|
||||
}
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glVertexBindingDivisor(attrib._channel, attrib._frequency * (isStereo() ? 2 : 1));
|
||||
#else
|
||||
glVertexBindingDivisor(attrib._channel, attrib._frequency);
|
||||
#endif
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
@ -306,7 +310,11 @@ void GLBackend::updateInput() {
|
|||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||
glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride,
|
||||
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1));
|
||||
#else
|
||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: Support properly the IAttrib version
|
||||
|
|
|
@ -48,7 +48,13 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
|||
|
||||
// check the program cache
|
||||
// pick the program version
|
||||
// check the program cache
|
||||
// pick the program version
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
GLuint glprogram = pipelineObject->_program->getProgram(isStereo());
|
||||
#else
|
||||
GLuint glprogram = pipelineObject->_program->getProgram();
|
||||
#endif
|
||||
|
||||
if (_pipeline._program != glprogram) {
|
||||
_pipeline._program = glprogram;
|
||||
|
|
|
@ -31,10 +31,25 @@ void GLBackend::do_setProjectionTransform(const Batch& batch, size_t paramOffset
|
|||
void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) {
|
||||
memcpy(&_transform._viewport, batch.readData(batch._params[paramOffset]._uint), sizeof(Vec4i));
|
||||
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
{
|
||||
ivec4& vp = _transform._viewport;
|
||||
glViewport(vp.x, vp.y, vp.z, vp.w);
|
||||
|
||||
// Where we assign the GL viewport
|
||||
if (_stereo._enable) {
|
||||
vp.z /= 2;
|
||||
if (_stereo._pass) {
|
||||
vp.x += vp.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!_inRenderTransferPass && !isStereo()) {
|
||||
ivec4& vp = _transform._viewport;
|
||||
glViewport(vp.x, vp.y, vp.z, vp.w);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall
|
||||
_transform._invalidViewport = true;
|
||||
|
@ -100,13 +115,21 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
|||
if (_invalidView || _invalidProj || _invalidViewport) {
|
||||
size_t offset = _cameraUboSize * _cameras.size();
|
||||
_cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset));
|
||||
if (stereo._enable) {
|
||||
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view)));
|
||||
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view)));
|
||||
} else {
|
||||
_cameras.push_back((_camera.recomputeDerived(_view)));
|
||||
}
|
||||
|
||||
if (stereo._enable) {
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
_cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view)));
|
||||
#else
|
||||
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view)));
|
||||
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view)));
|
||||
#endif
|
||||
} else {
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
_cameras.push_back(CameraBufferElement(_camera.recomputeDerived(_view)));
|
||||
#else
|
||||
_cameras.push_back((_camera.recomputeDerived(_view)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Flags are clean
|
||||
|
@ -122,9 +145,13 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta
|
|||
}
|
||||
|
||||
if (offset != INVALID_OFFSET) {
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
bindCurrentCamera(0);
|
||||
#else
|
||||
if (!stereo._enable) {
|
||||
bindCurrentCamera(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
@ -148,7 +175,11 @@ void GLBackend::updateTransform(const Batch& batch) {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer);
|
||||
glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0,
|
||||
_transform._drawCallInfoOffsets[batch._currentNamedCall]);
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1));
|
||||
#else
|
||||
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)CHECK_GL_ERROR();
|
||||
|
|
|
@ -54,9 +54,24 @@ static const std::array<std::string, NUM_SHADER_DOMAINS> DOMAIN_DEFINES { {
|
|||
"#define GPU_GEOMETRY_SHADER",
|
||||
} };
|
||||
|
||||
// Stereo specific defines
|
||||
static const std::string stereoVersion {
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
"#define GPU_TRANSFORM_IS_STEREO\n#define GPU_TRANSFORM_STEREO_CAMERA\n#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN"
|
||||
#endif
|
||||
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
"#define GPU_TRANSFORM_IS_STEREO\n#define GPU_TRANSFORM_STEREO_CAMERA\n#define GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED"
|
||||
#else
|
||||
"#define GPU_TRANSFORM_IS_STEREO"
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
// Versions specific of the shader
|
||||
static const std::array<std::string, GLShader::NumVersions> VERSION_DEFINES { {
|
||||
""
|
||||
"",
|
||||
stereoVersion
|
||||
} };
|
||||
|
||||
GLShader* compileBackendShader(GLBackend& backend, const Shader& shader) {
|
||||
|
|
|
@ -19,6 +19,8 @@ public:
|
|||
|
||||
enum Version {
|
||||
Mono = 0,
|
||||
Stereo,
|
||||
|
||||
NumVersions
|
||||
};
|
||||
|
||||
|
|
|
@ -25,10 +25,14 @@ void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
|||
uint32 startVertex = batch._params[paramOffset + 0]._uint;
|
||||
|
||||
if (isStereo()) {
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
|
||||
#else
|
||||
setupStereoSide(0);
|
||||
glDrawArrays(mode, startVertex, numVertices);
|
||||
setupStereoSide(1);
|
||||
glDrawArrays(mode, startVertex, numVertices);
|
||||
#endif
|
||||
|
||||
_stats._DSNumTriangles += 2 * numVertices / 3;
|
||||
_stats._DSNumDrawcalls += 2;
|
||||
|
@ -55,11 +59,14 @@ void GL45Backend::do_drawIndexed(const Batch& batch, size_t paramOffset) {
|
|||
GLvoid* indexBufferByteOffset = reinterpret_cast<GLvoid*>(startIndex * typeByteSize + _input._indexBufferOffset);
|
||||
|
||||
if (isStereo()) {
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2);
|
||||
#else
|
||||
setupStereoSide(0);
|
||||
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||
setupStereoSide(1);
|
||||
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||
|
||||
#endif
|
||||
_stats._DSNumTriangles += 2 * numIndices / 3;
|
||||
_stats._DSNumDrawcalls += 2;
|
||||
} else {
|
||||
|
@ -83,10 +90,14 @@ void GL45Backend::do_drawInstanced(const Batch& batch, size_t paramOffset) {
|
|||
if (isStereo()) {
|
||||
GLint trueNumInstances = 2 * numInstances;
|
||||
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glDrawArraysInstanced(mode, startVertex, numVertices, trueNumInstances);
|
||||
#else
|
||||
setupStereoSide(0);
|
||||
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||
setupStereoSide(1);
|
||||
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||
#endif
|
||||
|
||||
_stats._DSNumTriangles += (trueNumInstances * numVertices) / 3;
|
||||
_stats._DSNumDrawcalls += trueNumInstances;
|
||||
|
@ -112,10 +123,15 @@ void GL45Backend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset
|
|||
|
||||
if (isStereo()) {
|
||||
GLint trueNumInstances = 2 * numInstances;
|
||||
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance);
|
||||
#else
|
||||
setupStereoSide(0);
|
||||
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||
setupStereoSide(1);
|
||||
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||
#endif
|
||||
_stats._DSNumTriangles += (trueNumInstances * numIndices) / 3;
|
||||
_stats._DSNumDrawcalls += trueNumInstances;
|
||||
} else {
|
||||
|
|
|
@ -18,30 +18,60 @@ struct TransformCamera {
|
|||
mat4 _projection;
|
||||
mat4 _projectionInverse;
|
||||
vec4 _viewport;
|
||||
vec4 _stereoInfo;
|
||||
};
|
||||
|
||||
layout(std140) uniform transformCameraBuffer {
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
TransformCamera _camera[2];
|
||||
#else
|
||||
TransformCamera _camera;
|
||||
#endif
|
||||
#else
|
||||
TransformCamera _camera;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
||||
layout(location=14) in int _inStereoSide;
|
||||
#endif
|
||||
|
||||
flat out int _stereoSide;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PIXEL_SHADER
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
flat in int _stereoSide;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TransformCamera getTransformCamera() {
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
#ifdef VERTEX_SHADER
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
||||
_stereoSide = _inStereoSide;
|
||||
#endif
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED
|
||||
_stereoSide = gl_InstanceID % 2;
|
||||
#endif
|
||||
#endif
|
||||
return _camera[_stereoSide];
|
||||
#else
|
||||
return _camera;
|
||||
#endif
|
||||
#else
|
||||
return _camera;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 getEyeWorldPos() {
|
||||
return _camera._viewInverse[3].xyz;
|
||||
}
|
||||
|
||||
|
||||
bool cam_isStereo() {
|
||||
return _camera._stereoInfo.x > 0.0;
|
||||
}
|
||||
|
||||
float cam_getStereoSide() {
|
||||
return _camera._stereoInfo.y;
|
||||
}
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
|
@ -92,6 +122,25 @@ TransformObject getTransformObject() {
|
|||
<$viewport$> = <$cameraTransform$>._viewport;
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformStereoClipsSpace(cameraTransform, clipPos)@>
|
||||
{
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
|
||||
#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN
|
||||
vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));
|
||||
vec2 eyeOffsetScale = vec2(-0.5, +0.5);
|
||||
uint eyeIndex = _stereoSide;
|
||||
gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]);
|
||||
float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w;
|
||||
<$clipPos$>.x = newClipPosX;
|
||||
#endif
|
||||
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
<@func transformModelToEyeWorldAlignedPos(cameraTransform, objectTransform, modelPos, eyeWorldAlignedPos)@>
|
||||
<!// Bring the model pos in the world aligned space centered on the eye axis !>
|
||||
{ // _transformModelToEyeWorldAlignedPos
|
||||
|
@ -108,6 +157,8 @@ TransformObject getTransformObject() {
|
|||
<$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$>
|
||||
|
||||
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
||||
|
||||
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
@ -117,6 +168,8 @@ TransformObject getTransformObject() {
|
|||
<$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$>
|
||||
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
||||
<$eyePos$> = vec4((<$cameraTransform$>._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);
|
||||
|
||||
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
@ -134,15 +187,6 @@ TransformObject getTransformObject() {
|
|||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformModelToWorldDir(cameraTransform, objectTransform, modelDir, worldDir)@>
|
||||
{ // transformModelToEyeDir
|
||||
vec3 mr0 = <$objectTransform$>._modelInverse[0].xyz;
|
||||
vec3 mr1 = <$objectTransform$>._modelInverse[1].xyz;
|
||||
vec3 mr2 = <$objectTransform$>._modelInverse[2].xyz;
|
||||
|
||||
<$worldDir$> = vec3(dot(mr0, <$modelDir$>), dot(mr1, <$modelDir$>), dot(mr2, <$modelDir$>));
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
|
||||
{ // transformModelToEyeDir
|
||||
|
@ -173,6 +217,8 @@ TransformObject getTransformObject() {
|
|||
<@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@>
|
||||
{ // transformEyeToClipPos
|
||||
<$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0);
|
||||
|
||||
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
|
Loading…
Reference in a new issue