overte-JulianGro/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp

159 lines
5.6 KiB
C++

//
// GLBackendTransform.cpp
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 3/8/2015.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "GLBackend.h"
using namespace gpu;
using namespace gpu::gl;
// Transform Stage
void GLBackend::do_setModelTransform(Batch& batch, size_t paramOffset) {
}
void GLBackend::do_setViewTransform(Batch& batch, size_t paramOffset) {
_transform._view = batch._transforms.get(batch._params[paramOffset]._uint);
_transform._viewIsCamera = batch._params[paramOffset + 1]._uint != 0;
_transform._invalidView = true;
}
void GLBackend::do_setProjectionTransform(Batch& batch, size_t paramOffset) {
memcpy(&_transform._projection, batch.editData(batch._params[paramOffset]._uint), sizeof(Mat4));
_transform._invalidProj = true;
}
void GLBackend::do_setViewportTransform(Batch& batch, size_t paramOffset) {
memcpy(&_transform._viewport, batch.editData(batch._params[paramOffset]._uint), sizeof(Vec4i));
if (!_inRenderTransferPass && !isStereo()) {
ivec4& vp = _transform._viewport;
glViewport(vp.x, vp.y, vp.z, vp.w);
}
// The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall
_transform._invalidViewport = true;
}
void GLBackend::do_setDepthRangeTransform(Batch& batch, size_t paramOffset) {
Vec2 depthRange(batch._params[paramOffset + 1]._float, batch._params[paramOffset + 0]._float);
if ((depthRange.x != _transform._depthRange.x) || (depthRange.y != _transform._depthRange.y)) {
_transform._depthRange = depthRange;
glDepthRangef(depthRange.x, depthRange.y);
}
}
void GLBackend::killTransform() {
glDeleteBuffers(1, &_transform._objectBuffer);
glDeleteBuffers(1, &_transform._cameraBuffer);
glDeleteBuffers(1, &_transform._drawCallInfoBuffer);
glDeleteTextures(1, &_transform._objectBufferTexture);
}
void GLBackend::syncTransformStateCache() {
_transform._invalidViewport = true;
_transform._invalidProj = true;
_transform._invalidView = true;
glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport);
glGetFloatv(GL_DEPTH_RANGE, (GLfloat*)&_transform._depthRange);
Mat4 modelView;
auto modelViewInv = glm::inverse(modelView);
_transform._view.evalFromRawMatrix(modelViewInv);
}
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) {
// Check all the dirty flags and update the state accordingly
if (_invalidViewport) {
_camera._viewport = glm::vec4(_viewport);
}
if (_invalidProj) {
_camera._projection = _projection;
}
if (_invalidView) {
// Apply the correction
if (_viewIsCamera && _correction.correction != glm::mat4()) {
// FIXME should I switch to using the camera correction buffer in Transform.slf and leave this out?
Transform result;
_view.mult(result, _view, _correction.correction);
if (_skybox) {
result.setTranslation(vec3());
}
_view = result;
}
// This is when the _view matrix gets assigned
_view.getInverseMatrix(_camera._view);
}
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)));
}
}
// Flags are clean
_invalidView = _invalidProj = _invalidViewport = false;
}
void GLBackend::TransformStageState::update(size_t commandIndex, const StereoState& stereo) const {
size_t offset = INVALID_OFFSET;
while ((_camerasItr != _cameraOffsets.end()) && (commandIndex >= (*_camerasItr).first)) {
offset = (*_camerasItr).second;
_currentCameraOffset = offset;
++_camerasItr;
}
if (offset != INVALID_OFFSET) {
if (!stereo._enable) {
bindCurrentCamera(0);
}
}
(void)CHECK_GL_ERROR();
}
void GLBackend::TransformStageState::bindCurrentCamera(int eye) const {
if (_currentCameraOffset != INVALID_OFFSET) {
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, _currentCameraOffset + eye * _cameraUboSize, sizeof(CameraBufferElement));
}
}
void GLBackend::updateTransform(const Batch& batch) {
_transform.update(_commandIndex, _stereo);
auto& drawCallInfoBuffer = batch.getDrawCallInfoBuffer();
if (batch._currentNamedCall.empty()) {
auto& drawCallInfo = drawCallInfoBuffer[_currentDraw];
glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is disabled
glVertexAttribI2i(gpu::Stream::DRAW_CALL_INFO, drawCallInfo.index, drawCallInfo.unused);
} else {
glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled
glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer);
glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0,
_transform._drawCallInfoOffsets[batch._currentNamedCall]);
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1);
}
(void)CHECK_GL_ERROR();
}
void GLBackend::resetTransformStage() {
}