Merge pull request #6871 from Atlante45/feat/draw-call-info

Unify normal and named draw paths
This commit is contained in:
samcake 2016-02-01 14:19:15 -08:00
commit 1b52d700a0
29 changed files with 482 additions and 388 deletions

View file

@ -96,26 +96,31 @@ void renderWorldBox(gpu::Batch& batch) {
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY);
geometryCache->renderWireCubeInstance(batch, Transform(), GREY4);
geometryCache->renderWireCubeInstance(batch, GREY4);
// Draw meter markers along the 3 axis to help with measuring things
const float MARKER_DISTANCE = 1.0f;
const float MARKER_RADIUS = 0.05f;
transform = Transform().setScale(MARKER_RADIUS);
geometryCache->renderSolidSphereInstance(batch, transform, RED);
batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, RED);
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS);
geometryCache->renderSolidSphereInstance(batch, transform, RED);
batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, RED);
transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS);
geometryCache->renderSolidSphereInstance(batch, transform, GREEN);
batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, GREEN);
transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
geometryCache->renderSolidSphereInstance(batch, transform, BLUE);
batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, BLUE);
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
geometryCache->renderSolidSphereInstance(batch, transform, GREY);
batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, GREY);
}
// Return a random vector of average length 1

View file

@ -456,7 +456,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
Transform transform;
transform.setTranslation(position);
transform.postScale(INDICATOR_RADIUS);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, transform, LOOK_AT_INDICATOR_COLOR);
batch.setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, LOOK_AT_INDICATOR_COLOR);
}
// If the avatar is looking at me, indicate that they are
@ -484,9 +485,9 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
eyeDiameter = DEFAULT_EYE_DIAMETER;
}
batch.setModelTransform(Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT));
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch,
Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT),
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
position = getHead()->getRightEyePosition();
transform.setTranslation(position);
@ -494,9 +495,9 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
if (eyeDiameter == 0.0f) {
eyeDiameter = DEFAULT_EYE_DIAMETER;
}
batch.setModelTransform(Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT));
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch,
Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT),
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
}
}

View file

@ -60,7 +60,8 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
transform.setTranslation(position);
transform.setRotation(palm.getRotation());
transform.postScale(SPHERE_RADIUS);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, transform, grayColor);
batch.setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, grayColor);
// draw a green sphere at the old "finger tip"
transform = Transform();
@ -68,7 +69,8 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
transform.setTranslation(position);
transform.setRotation(palm.getRotation());
transform.postScale(SPHERE_RADIUS);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, transform, greenColor);
batch.setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, greenColor);
}
}

View file

@ -467,5 +467,6 @@ void Head::renderLookatTarget(RenderArgs* renderArgs, glm::vec3 lookatPosition)
const float LOOK_AT_TARGET_RADIUS = 0.075f;
transform.postScale(LOOK_AT_TARGET_RADIUS);
const glm::vec4 LOOK_AT_TARGET_COLOR = { 0.8f, 0.0f, 0.0f, 0.75f };
geometryCache->renderSolidSphereInstance(batch, transform, LOOK_AT_TARGET_COLOR);
batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, LOOK_AT_TARGET_COLOR);
}

View file

@ -349,17 +349,15 @@ void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale
// draw a blue sphere at the capsule top point
glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y));
geometryCache->renderSolidSphereInstance(batch,
Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius),
glm::vec4(0.6f, 0.6f, 0.8f, alpha));
batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius));
geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha));
// draw a yellow sphere at the capsule bottom point
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f);
glm::vec3 axis = topPoint - bottomPoint;
geometryCache->renderSolidSphereInstance(batch,
Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius),
glm::vec4(0.8f, 0.8f, 0.6f, alpha));
batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius));
geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha));
// draw a green cylinder between the two points
glm::vec3 origin(0.0f);

View file

@ -60,7 +60,8 @@ void Cube3DOverlay::render(RenderArgs* args) {
// }
transform.setScale(dimensions);
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(*batch, transform, cubeColor);
batch->setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(*batch, cubeColor);
} else {
if (getIsDashedLine()) {
@ -96,9 +97,9 @@ void Cube3DOverlay::render(RenderArgs* args) {
geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor);
} else {
batch->setModelTransform(Transform());
transform.setScale(dimensions);
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(*batch, transform, cubeColor);
batch->setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(*batch, cubeColor);
}
}
}

View file

@ -39,14 +39,13 @@ void Sphere3DOverlay::render(RenderArgs* args) {
auto batch = args->_batch;
if (batch) {
batch->setModelTransform(Transform());
Transform transform = _transform;
transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE);
batch->setModelTransform(transform);
if (_isSolid) {
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(*batch, transform, sphereColor);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(*batch, sphereColor);
} else {
DependencyManager::get<GeometryCache>()->renderWireSphereInstance(*batch, transform, sphereColor);
DependencyManager::get<GeometryCache>()->renderWireSphereInstance(*batch, sphereColor);
}
}
}

View file

@ -61,14 +61,14 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
return;
}
batch.setModelTransform(transToCenter); // we want to include the scale as well
if (_procedural->ready()) {
batch.setModelTransform(transToCenter); // we want to include the scale as well
_procedural->prepare(batch, getPosition(), getDimensions());
auto color = _procedural->getColor(cubeColor);
batch._glColor4f(color.r, color.g, color.b, color.a);
DependencyManager::get<GeometryCache>()->renderCube(batch);
} else {
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(batch, transToCenter, cubeColor);
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(batch, cubeColor);
}
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
args->_details._trianglesRendered += (int)triCount;

View file

@ -440,8 +440,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
bool success;
auto shapeTransform = getTransformToCenter(success);
if (success) {
batch.setModelTransform(Transform()); // we want to include the scale as well
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(batch, shapeTransform, greenColor);
batch.setModelTransform(shapeTransform); // we want to include the scale as well
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(batch, greenColor);
}
}
}

View file

@ -64,15 +64,14 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
return;
}
modelTransform.postScale(SPHERE_ENTITY_SCALE);
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation
if (_procedural->ready()) {
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation
_procedural->prepare(batch, getPosition(), getDimensions());
auto color = _procedural->getColor(sphereColor);
batch._glColor4f(color.r, color.g, color.b, color.a);
DependencyManager::get<GeometryCache>()->renderSphere(batch);
} else {
batch.setModelTransform(Transform());
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, modelTransform, sphereColor);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, sphereColor);
}
static const auto triCount = DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
args->_details._trianglesRendered += (int)triCount;

View file

@ -132,7 +132,6 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch;
batch.setModelTransform(Transform());
bool success;
auto shapeTransform = getTransformToCenter(success);
@ -142,9 +141,11 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
auto geometryCache = DependencyManager::get<GeometryCache>();
if (getShapeType() == SHAPE_TYPE_SPHERE) {
shapeTransform.postScale(SPHERE_ENTITY_SCALE);
geometryCache->renderWireSphereInstance(batch, shapeTransform, DEFAULT_COLOR);
batch.setModelTransform(shapeTransform);
geometryCache->renderWireSphereInstance(batch, DEFAULT_COLOR);
} else {
geometryCache->renderWireCubeInstance(batch, shapeTransform, DEFAULT_COLOR);
batch.setModelTransform(shapeTransform);
geometryCache->renderWireCubeInstance(batch, DEFAULT_COLOR);
}
break;
}

View file

@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef gpu__GPUConfig__
#define gpu__GPUConfig__
#ifndef hifi_gpu_GPUConfig_h
#define hifi_gpu_GPUConfig_h
#define GL_GLEXT_PROTOTYPES 1
@ -38,8 +38,6 @@
#define GPU_FEATURE_PROFILE GPU_CORE
#define GPU_INPUT_PROFILE GPU_CORE_43
#elif defined(ANDROID)
#else
#include <GL/glew.h>
@ -50,4 +48,11 @@
#endif
#if (GPU_INPUT_PROFILE == GPU_CORE_43)
// Deactivate SSBO for now, we've run into some issues
// on GL 4.3 capable GPUs not behaving as expected
//#define GPU_SSBO_DRAW_CALL_INFO
#endif
#endif // hifi_gpu_GPUConfig_h

View file

@ -29,20 +29,6 @@ ProfileRangeBatch::~ProfileRangeBatch() {
using namespace gpu;
Batch::Batch() :
_commands(),
_commandOffsets(),
_params(),
_data(),
_buffers(),
_textures(),
_streamFormats(),
_transforms(),
_pipelines(),
_framebuffers()
{
}
Batch::Batch(const CacheState& cacheState) : Batch() {
_commands.reserve(cacheState.commandsSize);
_commandOffsets.reserve(cacheState.offsetsSize);
@ -88,6 +74,8 @@ void Batch::draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex
_params.push_back(startVertex);
_params.push_back(numVertices);
_params.push_back(primitiveType);
captureDrawCallInfo();
}
void Batch::drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 startIndex) {
@ -96,6 +84,8 @@ void Batch::drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 start
_params.push_back(startIndex);
_params.push_back(numIndices);
_params.push_back(primitiveType);
captureDrawCallInfo();
}
void Batch::drawInstanced(uint32 numInstances, Primitive primitiveType, uint32 numVertices, uint32 startVertex, uint32 startInstance) {
@ -106,6 +96,8 @@ void Batch::drawInstanced(uint32 numInstances, Primitive primitiveType, uint32 n
_params.push_back(numVertices);
_params.push_back(primitiveType);
_params.push_back(numInstances);
captureDrawCallInfo();
}
void Batch::drawIndexedInstanced(uint32 numInstances, Primitive primitiveType, uint32 numIndices, uint32 startIndex, uint32 startInstance) {
@ -116,6 +108,8 @@ void Batch::drawIndexedInstanced(uint32 numInstances, Primitive primitiveType, u
_params.push_back(numIndices);
_params.push_back(primitiveType);
_params.push_back(numInstances);
captureDrawCallInfo();
}
@ -123,12 +117,16 @@ void Batch::multiDrawIndirect(uint32 numCommands, Primitive primitiveType) {
ADD_COMMAND(multiDrawIndirect);
_params.push_back(numCommands);
_params.push_back(primitiveType);
captureDrawCallInfo();
}
void Batch::multiDrawIndexedIndirect(uint32 nbCommands, Primitive primitiveType) {
ADD_COMMAND(multiDrawIndexedIndirect);
_params.push_back(nbCommands);
_params.push_back(primitiveType);
captureDrawCallInfo();
}
void Batch::setInputFormat(const Stream::FormatPointer& format) {
@ -185,7 +183,8 @@ void Batch::setIndirectBuffer(const BufferPointer& buffer, Offset offset, Offset
void Batch::setModelTransform(const Transform& model) {
ADD_COMMAND(setModelTransform);
_params.push_back(_transforms.cache(model));
_currentModel = model;
_invalidModel = true;
}
void Batch::setViewTransform(const Transform& view) {
@ -344,6 +343,19 @@ void Batch::runLambda(std::function<void()> f) {
_params.push_back(_lambdas.cache(f));
}
void Batch::startNamedCall(const std::string& name) {
ADD_COMMAND(startNamedCall);
_params.push_back(_names.cache(name));
_currentNamedCall = name;
}
void Batch::stopNamedCall() {
ADD_COMMAND(stopNamedCall);
_currentNamedCall.clear();
}
void Batch::enableStereo(bool enable) {
_enableStereo = enable;
}
@ -360,14 +372,13 @@ bool Batch::isSkyboxEnabled() const {
return _enableSkybox;
}
void Batch::setupNamedCalls(const std::string& instanceName, size_t count, NamedBatchData::Function function) {
NamedBatchData& instance = _namedData[instanceName];
instance.count += count;
instance.function = function;
}
void Batch::setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function) {
setupNamedCalls(instanceName, 1, function);
NamedBatchData& instance = _namedData[instanceName];
if (!instance.function) {
instance.function = function;
}
captureNamedDrawCallInfo(instanceName);
}
BufferPointer Batch::getNamedBuffer(const std::string& instanceName, uint8_t index) {
@ -376,16 +387,74 @@ BufferPointer Batch::getNamedBuffer(const std::string& instanceName, uint8_t ind
instance.buffers.resize(index + 1);
}
if (!instance.buffers[index]) {
instance.buffers[index].reset(new Buffer());
instance.buffers[index] = std::make_shared<Buffer>();
}
return instance.buffers[index];
}
Batch::DrawCallInfoBuffer& Batch::getDrawCallInfoBuffer() {
if (_currentNamedCall.empty()) {
return _drawCallInfos;
} else {
return _namedData[_currentNamedCall].drawCallInfos;
}
}
const Batch::DrawCallInfoBuffer& Batch::getDrawCallInfoBuffer() const {
if (_currentNamedCall.empty()) {
return _drawCallInfos;
} else {
auto it = _namedData.find(_currentNamedCall);
Q_ASSERT_X(it != _namedData.end(), Q_FUNC_INFO, (_currentNamedCall + " not in _namedData.").data());
return it->second.drawCallInfos;
}
}
void Batch::captureDrawCallInfoImpl() {
if (_invalidModel) {
TransformObject object;
_currentModel.getMatrix(object._model);
// FIXME - we don't want to be using glm::inverse() here but it fixes the flickering issue we are
// seeing with planky blocks in toybox. Our implementation of getInverseMatrix() is buggy in cases
// of non-uniform scale. We need to fix that. In the mean time, glm::inverse() works.
//_model.getInverseMatrix(_object._modelInverse);
object._modelInverse = glm::inverse(object._model);
_objects.push_back(object);
// Flag is clean
_invalidModel = false;
}
auto& drawCallInfos = getDrawCallInfoBuffer();
drawCallInfos.push_back((uint16)_objects.size() - 1);
}
void Batch::captureDrawCallInfo() {
if (!_currentNamedCall.empty()) {
// If we are processing a named call, we don't want to register the raw draw calls
return;
}
captureDrawCallInfoImpl();
}
void Batch::captureNamedDrawCallInfo(std::string name) {
std::swap(_currentNamedCall, name); // Set and save _currentNamedCall
captureDrawCallInfoImpl();
std::swap(_currentNamedCall, name); // Restore _currentNamedCall
}
void Batch::preExecute() {
for (auto& mapItem : _namedData) {
mapItem.second.process(*this);
auto& name = mapItem.first;
auto& instance = mapItem.second;
startNamedCall(name);
instance.process(*this);
stopNamedCall();
}
_namedData.clear();
}
QDebug& operator<<(QDebug& debug, const Batch::CacheState& cacheState) {

View file

@ -29,7 +29,12 @@ class QDebug;
namespace gpu {
enum ReservedSlot {
#ifdef GPU_SSBO_DRAW_CALL_INFO
TRANSFORM_OBJECT_SLOT = 6,
#else
TRANSFORM_OBJECT_SLOT = 31,
#endif
TRANSFORM_CAMERA_SLOT = 7,
};
@ -45,13 +50,31 @@ class Batch {
public:
typedef Stream::Slot Slot;
class DrawCallInfo {
public:
using Index = uint16_t;
DrawCallInfo(Index idx) : index(idx) {}
Index index { 0 };
uint16_t unused { 0 }; // Reserved space for later
};
// Make sure DrawCallInfo has no extra padding
static_assert(sizeof(DrawCallInfo) == 4, "DrawCallInfo size is incorrect.");
using DrawCallInfoBuffer = std::vector<DrawCallInfo>;
struct NamedBatchData {
using BufferPointers = std::vector<BufferPointer>;
using Function = std::function<void(gpu::Batch&, NamedBatchData&)>;
BufferPointers buffers;
size_t count { 0 };
Function function;
DrawCallInfoBuffer drawCallInfos;
size_t count() const { return drawCallInfos.size(); }
void process(Batch& batch) {
if (function) {
@ -62,6 +85,16 @@ public:
using NamedBatchDataMap = std::map<std::string, NamedBatchData>;
DrawCallInfoBuffer _drawCallInfos;
std::string _currentNamedCall;
const DrawCallInfoBuffer& getDrawCallInfoBuffer() const;
DrawCallInfoBuffer& getDrawCallInfoBuffer();
void captureDrawCallInfo();
void captureNamedDrawCallInfo(std::string name);
class CacheState {
public:
size_t commandsSize;
@ -88,7 +121,7 @@ public:
transformsSize(transformsSize), pipelinesSize(pipelinesSize), framebuffersSize(framebuffersSize), queriesSize(queriesSize) { }
};
Batch();
Batch() {}
Batch(const CacheState& cacheState);
explicit Batch(const Batch& batch);
~Batch();
@ -121,13 +154,8 @@ public:
void multiDrawIndirect(uint32 numCommands, Primitive primitiveType);
void multiDrawIndexedIndirect(uint32 numCommands, Primitive primitiveType);
void setupNamedCalls(const std::string& instanceName, size_t count, NamedBatchData::Function function);
void setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function);
BufferPointer getNamedBuffer(const std::string& instanceName, uint8_t index = 0);
void setNamedBuffer(const std::string& instanceName, BufferPointer& buffer, uint8_t index = 0);
// Input Stage
// InputFormat
@ -304,6 +332,9 @@ public:
COMMAND_runLambda,
COMMAND_startNamedCall,
COMMAND_stopNamedCall,
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
@ -395,7 +426,7 @@ public:
typedef Cache<PipelinePointer>::Vector PipelineCaches;
typedef Cache<FramebufferPointer>::Vector FramebufferCaches;
typedef Cache<QueryPointer>::Vector QueryCaches;
typedef Cache<std::string>::Vector ProfileRangeCaches;
typedef Cache<std::string>::Vector StringCaches;
typedef Cache<std::function<void()>>::Vector LambdaCache;
// Cache Data in a byte array if too big to fit in Param
@ -415,6 +446,18 @@ public:
Params _params;
Bytes _data;
// SSBO class... layout MUST match the layout in TransformCamera.slh
class TransformObject {
public:
Mat4 _model;
Mat4 _modelInverse;
};
using TransformObjects = std::vector<TransformObject>;
bool _invalidModel { true };
Transform _currentModel;
TransformObjects _objects;
BufferCaches _buffers;
TextureCaches _textures;
StreamFormatCaches _streamFormats;
@ -423,7 +466,8 @@ public:
FramebufferCaches _framebuffers;
QueryCaches _queries;
LambdaCache _lambdas;
ProfileRangeCaches _profileRanges;
StringCaches _profileRanges;
StringCaches _names;
NamedBatchDataMap _namedData;
@ -431,8 +475,13 @@ public:
bool _enableSkybox{ false };
protected:
void startNamedCall(const std::string& name);
void stopNamedCall();
// Maybe useful but shoudln't be public. Please convince me otherwise
void runLambda(std::function<void()> f);
void captureDrawCallInfoImpl();
};
}

View file

@ -76,13 +76,6 @@ public:
virtual void syncCache() = 0;
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
// UBO class... layout MUST match the layout in TransformCamera.slh
class TransformObject {
public:
Mat4 _model;
Mat4 _modelInverse;
};
// UBO class... layout MUST match the layout in TransformCamera.slh
class TransformCamera {
public:

View file

@ -62,6 +62,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_runLambda),
(&::gpu::GLBackend::do_startNamedCall),
(&::gpu::GLBackend::do_stopNamedCall),
(&::gpu::GLBackend::do_glActiveBindTexture),
(&::gpu::GLBackend::do_glUniform1i),
@ -121,11 +124,7 @@ Backend* GLBackend::createBackend() {
return new GLBackend();
}
GLBackend::GLBackend() :
_input(),
_pipeline(),
_output()
{
GLBackend::GLBackend() {
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uboAlignment);
initInput();
initTransform();
@ -155,31 +154,30 @@ void GLBackend::renderPassTransfer(Batch& batch) {
{ // Sync all the buffers
PROFILE_RANGE("syncCPUTransform");
_transform._cameras.resize(0);
_transform._cameras.clear();
_transform._cameraOffsets.clear();
_transform._objects.resize(0);
_transform._objectOffsets.clear();
for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) {
switch (*command) {
case Batch::COMMAND_draw:
case Batch::COMMAND_drawIndexed:
case Batch::COMMAND_drawInstanced:
case Batch::COMMAND_drawIndexedInstanced:
_transform.preUpdate(_commandIndex, _stereo);
break;
case Batch::COMMAND_draw:
case Batch::COMMAND_drawIndexed:
case Batch::COMMAND_drawInstanced:
case Batch::COMMAND_drawIndexedInstanced:
case Batch::COMMAND_multiDrawIndirect:
case Batch::COMMAND_multiDrawIndexedIndirect:
_transform.preUpdate(_commandIndex, _stereo);
break;
case Batch::COMMAND_setModelTransform:
case Batch::COMMAND_setViewportTransform:
case Batch::COMMAND_setViewTransform:
case Batch::COMMAND_setProjectionTransform: {
CommandCall call = _commandCalls[(*command)];
(this->*(call))(batch, *offset);
break;
}
case Batch::COMMAND_setViewportTransform:
case Batch::COMMAND_setViewTransform:
case Batch::COMMAND_setProjectionTransform: {
CommandCall call = _commandCalls[(*command)];
(this->*(call))(batch, *offset);
break;
}
default:
break;
default:
break;
}
command++;
offset++;
@ -188,12 +186,14 @@ void GLBackend::renderPassTransfer(Batch& batch) {
{ // Sync the transform buffers
PROFILE_RANGE("syncGPUTransform");
_transform.transfer();
_transform.transfer(batch);
}
}
void GLBackend::renderPassDraw(Batch& batch) {
_transform._objectsItr = _transform._objectOffsets.begin();
_currentDraw = -1;
_transform._camerasItr = _transform._cameraOffsets.begin();
const size_t numCommands = batch.getCommands().size();
const Batch::Commands::value_type* command = batch.getCommands().data();
@ -209,6 +209,22 @@ void GLBackend::renderPassDraw(Batch& batch) {
case Batch::COMMAND_setProjectionTransform:
break;
case Batch::COMMAND_draw:
case Batch::COMMAND_drawIndexed:
case Batch::COMMAND_drawInstanced:
case Batch::COMMAND_drawIndexedInstanced:
case Batch::COMMAND_multiDrawIndirect:
case Batch::COMMAND_multiDrawIndexedIndirect: {
// updates for draw calls
++_currentDraw;
updateInput();
updateTransform(batch);
updatePipeline();
CommandCall call = _commandCalls[(*command)];
(this->*(call))(batch, *offset);
break;
}
default: {
CommandCall call = _commandCalls[(*command)];
(this->*(call))(batch, *offset);
@ -306,10 +322,6 @@ void GLBackend::syncCache() {
}
void GLBackend::do_draw(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = _primitiveToGLmode[primitiveType];
uint32 numVertices = batch._params[paramOffset + 1]._uint;
@ -319,10 +331,6 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) {
}
void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = _primitiveToGLmode[primitiveType];
uint32 numIndices = batch._params[paramOffset + 1]._uint;
@ -338,10 +346,6 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) {
}
void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
GLint numInstances = batch._params[paramOffset + 4]._uint;
Primitive primitiveType = (Primitive)batch._params[paramOffset + 3]._uint;
GLenum mode = _primitiveToGLmode[primitiveType];
@ -353,10 +357,6 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) {
}
void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
GLint numInstances = batch._params[paramOffset + 4]._uint;
GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 3]._uint];
uint32 numIndices = batch._params[paramOffset + 2]._uint;
@ -381,10 +381,6 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) {
void GLBackend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) {
#if (GPU_INPUT_PROFILE == GPU_CORE_43)
updateInput();
updateTransform();
updatePipeline();
uint commandCount = batch._params[paramOffset + 0]._uint;
GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 1]._uint];
@ -398,10 +394,6 @@ void GLBackend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) {
void GLBackend::do_multiDrawIndexedIndirect(Batch& batch, size_t paramOffset) {
#if (GPU_INPUT_PROFILE == GPU_CORE_43)
updateInput();
updateTransform();
updatePipeline();
uint commandCount = batch._params[paramOffset + 0]._uint;
GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 1]._uint];
GLenum indexType = _elementTypeToGLType[_input._indexBufferType];
@ -423,6 +415,15 @@ void GLBackend::do_runLambda(Batch& batch, size_t paramOffset) {
f();
}
void GLBackend::do_startNamedCall(Batch& batch, size_t paramOffset) {
batch._currentNamedCall = batch._names.get(batch._params[paramOffset]._uint);
_currentDraw = -1;
}
void GLBackend::do_stopNamedCall(Batch& batch, size_t paramOffset) {
batch._currentNamedCall.clear();
}
void GLBackend::resetStages() {
resetInputStage();
resetPipelineStage();

View file

@ -320,42 +320,38 @@ protected:
void killTransform();
// Synchronize the state cache of this Backend with the actual real state of the GL Context
void syncTransformStateCache();
void updateTransform() const;
void updateTransform(const Batch& batch);
void resetTransformStage();
struct TransformStageState {
using TransformObjects = std::vector<TransformObject>;
using TransformCameras = std::vector<TransformCamera>;
TransformObject _object;
TransformCamera _camera;
TransformObjects _objects;
TransformCameras _cameras;
size_t _cameraUboSize{ 0 };
size_t _objectUboSize{ 0 };
GLuint _objectBuffer{ 0 };
GLuint _cameraBuffer{ 0 };
Transform _model;
mutable std::map<std::string, GLvoid*> _drawCallInfoOffsets;
GLuint _objectBuffer { 0 };
GLuint _cameraBuffer { 0 };
GLuint _drawCallInfoBuffer { 0 };
GLuint _objectBufferTexture { 0 };
size_t _cameraUboSize { 0 };
Transform _view;
Mat4 _projection;
Vec4i _viewport{ 0, 0, 1, 1 };
Vec2 _depthRange{ 0.0f, 1.0f };
bool _invalidModel{true};
bool _invalidView{false};
bool _invalidProj{false};
bool _invalidViewport{ false };
Vec4i _viewport { 0, 0, 1, 1 };
Vec2 _depthRange { 0.0f, 1.0f };
bool _invalidView { false };
bool _invalidProj { false };
bool _invalidViewport { false };
using Pair = std::pair<size_t, size_t>;
using List = std::list<Pair>;
List _cameraOffsets;
List _objectOffsets;
mutable List::const_iterator _objectsItr;
mutable List::const_iterator _camerasItr;
void preUpdate(size_t commandIndex, const StereoState& stereo);
void update(size_t commandIndex, const StereoState& stereo) const;
void transfer() const;
void transfer(const Batch& batch) const;
} _transform;
int32_t _uboAlignment{ 0 };
@ -465,6 +461,9 @@ protected:
void do_runLambda(Batch& batch, size_t paramOffset);
void do_startNamedCall(Batch& batch, size_t paramOffset);
void do_stopNamedCall(Batch& batch, size_t paramOffset);
void resetStages();
// TODO: As long as we have gl calls explicitely issued from interface
@ -486,6 +485,8 @@ protected:
void do_pushProfileRange(Batch& batch, size_t paramOffset);
void do_popProfileRange(Batch& batch, size_t paramOffset);
int _currentDraw { -1 };
typedef void (GLBackend::*CommandCall)(Batch&, size_t);
static CommandCall _commandCalls[Batch::NUM_COMMANDS];

View file

@ -75,9 +75,9 @@ void makeBindings(GLBackend::GLShader* shader) {
glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight");
}
loc = glGetAttribLocation(glprogram, "inInstanceTransform");
if (loc >= 0 && loc != gpu::Stream::INSTANCE_XFM) {
glBindAttribLocation(glprogram, gpu::Stream::INSTANCE_XFM, "inInstanceTransform");
loc = glGetAttribLocation(glprogram, "_drawCallInfo");
if (loc >= 0 && loc != gpu::Stream::DRAW_CALL_INFO) {
glBindAttribLocation(glprogram, gpu::Stream::DRAW_CALL_INFO, "_drawCallInfo");
}
// Link again to take into account the assigned attrib location
@ -92,17 +92,27 @@ void makeBindings(GLBackend::GLShader* shader) {
// now assign the ubo binding, then DON't relink!
//Check for gpu specific uniform slotBindings
loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer");
#ifdef GPU_SSBO_DRAW_CALL_INFO
loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer");
if (loc >= 0) {
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
}
#else
loc = glGetUniformLocation(glprogram, "transformObjectBuffer");
if (loc >= 0) {
glProgramUniform1i(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
}
#endif
loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
if (loc >= 0) {
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
}
(void)CHECK_GL_ERROR();
}
GLBackend::GLShader* compileShader(const Shader& shader) {

View file

@ -16,8 +16,6 @@ using namespace gpu;
// Transform Stage
void GLBackend::do_setModelTransform(Batch& batch, size_t paramOffset) {
_transform._model = batch._transforms.get(batch._params[paramOffset]._uint);
_transform._invalidModel = true;
}
void GLBackend::do_setViewTransform(Batch& batch, size_t paramOffset) {
@ -63,26 +61,29 @@ void GLBackend::do_setDepthRangeTransform(Batch& batch, size_t paramOffset) {
void GLBackend::initTransform() {
glGenBuffers(1, &_transform._objectBuffer);
glGenBuffers(1, &_transform._cameraBuffer);
glGenBuffers(1, &_transform._drawCallInfoBuffer);
#ifndef GPU_SSBO_DRAW_CALL_INFO
glGenTextures(1, &_transform._objectBufferTexture);
#endif
size_t cameraSize = sizeof(TransformCamera);
while (_transform._cameraUboSize < cameraSize) {
_transform._cameraUboSize += _uboAlignment;
}
size_t objectSize = sizeof(TransformObject);
while (_transform._objectUboSize < objectSize) {
_transform._objectUboSize += _uboAlignment;
}
}
void GLBackend::killTransform() {
glDeleteBuffers(1, &_transform._objectBuffer);
glDeleteBuffers(1, &_transform._cameraBuffer);
glDeleteBuffers(1, &_transform._drawCallInfoBuffer);
#ifndef GPU_SSBO_DRAW_CALL_INFO
glDeleteTextures(1, &_transform._objectBufferTexture);
#endif
}
void GLBackend::syncTransformStateCache() {
_transform._invalidViewport = true;
_transform._invalidProj = true;
_transform._invalidView = true;
_transform._invalidModel = true;
glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport);
@ -91,7 +92,6 @@ void GLBackend::syncTransformStateCache() {
Mat4 modelView;
auto modelViewInv = glm::inverse(modelView);
_transform._view.evalFromRawMatrix(modelViewInv);
_transform._model.setIdentity();
}
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) {
@ -108,16 +108,6 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
_view.getInverseMatrix(_camera._view);
}
if (_invalidModel) {
_model.getMatrix(_object._model);
// FIXME - we don't want to be using glm::inverse() here but it fixes the flickering issue we are
// seeing with planky blocks in toybox. Our implementation of getInverseMatrix() is buggy in cases
// of non-uniform scale. We need to fix that. In the mean time, glm::inverse() works.
//_model.getInverseMatrix(_object._modelInverse);
_object._modelInverse = glm::inverse(_object._model);
}
if (_invalidView || _invalidProj || _invalidViewport) {
size_t offset = _cameraUboSize * _cameras.size();
if (stereo._enable) {
@ -131,56 +121,68 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
}
}
if (_invalidModel) {
size_t offset = _objectUboSize * _objects.size();
_objectOffsets.push_back(TransformStageState::Pair(commandIndex, offset));
_objects.push_back(_object);
}
// Flags are clean
_invalidView = _invalidProj = _invalidModel = _invalidViewport = false;
_invalidView = _invalidProj = _invalidViewport = false;
}
void GLBackend::TransformStageState::transfer() const {
void GLBackend::TransformStageState::transfer(const Batch& batch) const {
// FIXME not thread safe
static std::vector<uint8_t> bufferData;
if (!_cameras.empty()) {
glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer);
bufferData.resize(_cameraUboSize * _cameras.size());
for (size_t i = 0; i < _cameras.size(); ++i) {
memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(TransformCamera));
}
glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer);
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
}
if (!_objects.empty()) {
glBindBuffer(GL_UNIFORM_BUFFER, _objectBuffer);
bufferData.resize(_objectUboSize * _objects.size());
for (size_t i = 0; i < _objects.size(); ++i) {
memcpy(bufferData.data() + (_objectUboSize * i), &_objects[i], sizeof(TransformObject));
}
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
}
if (!_cameras.empty() || !_objects.empty()) {
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
if (!batch._objects.empty()) {
auto byteSize = batch._objects.size() * sizeof(Batch::TransformObject);
bufferData.resize(byteSize);
memcpy(bufferData.data(), batch._objects.data(), byteSize);
#ifdef GPU_SSBO_DRAW_CALL_INFO
glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
#else
glBindBuffer(GL_TEXTURE_BUFFER, _objectBuffer);
glBufferData(GL_TEXTURE_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
#endif
}
if (!batch._namedData.empty()) {
bufferData.clear();
for (auto& data : batch._namedData) {
auto currentSize = bufferData.size();
auto bytesToCopy = data.second.drawCallInfos.size() * sizeof(Batch::DrawCallInfo);
bufferData.resize(currentSize + bytesToCopy);
memcpy(bufferData.data() + currentSize, data.second.drawCallInfos.data(), bytesToCopy);
_drawCallInfoOffsets[data.first] = (GLvoid*)currentSize;
}
glBindBuffer(GL_ARRAY_BUFFER, _drawCallInfoBuffer);
glBufferData(GL_ARRAY_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
#ifdef GPU_SSBO_DRAW_CALL_INFO
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer);
#else
glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT);
glBindTexture(GL_TEXTURE_BUFFER, _objectBufferTexture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, _objectBuffer);
#endif
CHECK_GL_ERROR();
}
void GLBackend::TransformStageState::update(size_t commandIndex, const StereoState& stereo) const {
static const size_t INVALID_OFFSET = (size_t)-1;
size_t offset = INVALID_OFFSET;
while ((_objectsItr != _objectOffsets.end()) && (commandIndex >= (*_objectsItr).first)) {
offset = (*_objectsItr).second;
++_objectsItr;
}
if (offset != INVALID_OFFSET) {
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT,
_objectBuffer, offset, sizeof(Backend::TransformObject));
}
offset = INVALID_OFFSET;
while ((_camerasItr != _cameraOffsets.end()) && (commandIndex >= (*_camerasItr).first)) {
offset = (*_camerasItr).second;
++_camerasItr;
@ -191,14 +193,29 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta
offset += _cameraUboSize;
}
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT,
_cameraBuffer, offset, sizeof(Backend::TransformCamera));
_cameraBuffer, offset, sizeof(Backend::TransformCamera));
}
(void)CHECK_GL_ERROR();
}
void GLBackend::updateTransform() const {
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() {

View file

@ -10,13 +10,12 @@
!>
<@if not GPU_INPUTS_SLH@>
<@def GPU_INPUTS_SLH@>
in vec4 inPosition;
in vec4 inNormal;
in vec4 inColor;
in vec4 inTexCoord0;
in vec4 inTangent;
in vec4 inSkinClusterIndex;
in vec4 inSkinClusterWeight;
in vec4 inTexCoord1;
in mat4 inInstanceTransform;
layout(location = 0) in vec4 inPosition;
layout(location = 1) in vec4 inNormal;
layout(location = 2) in vec4 inColor;
layout(location = 3) in vec4 inTexCoord0;
layout(location = 4) in vec4 inTangent;
layout(location = 5) in vec4 inSkinClusterIndex;
layout(location = 6) in vec4 inSkinClusterWeight;
layout(location = 7) in vec4 inTexCoord1;
<@endif@>

View file

@ -34,14 +34,7 @@ const ElementArray& getDefaultElements() {
//SKIN_CLUSTER_WEIGHT = 6,
Element::VEC4F_XYZW,
//TEXCOORD1 = 7,
Element::VEC2F_UV,
//INSTANCE_SCALE = 8,
Element::VEC3F_XYZ,
//INSTANCE_TRANSLATE = 9,
Element::VEC3F_XYZ,
//INSTANCE_XFM = 10,
// FIXME make a matrix element
Element::VEC4F_XYZW
Element::VEC2F_UV
}};
return defaultElements;
}

View file

@ -37,12 +37,10 @@ public:
SKIN_CLUSTER_INDEX = 5,
SKIN_CLUSTER_WEIGHT = 6,
TEXCOORD1 = 7,
INSTANCE_SCALE = 8,
INSTANCE_TRANSLATE = 9,
INSTANCE_XFM = 10,
NUM_INPUT_SLOTS = TEXCOORD1 + 1,
// Instance XFM is a mat4, and as such takes up 4 slots
NUM_INPUT_SLOTS = INSTANCE_XFM + 4,
DRAW_CALL_INFO = 15, // Reserve last input slot for draw call infos
};
typedef uint8 Slot;

View file

@ -10,13 +10,8 @@
<@if not GPU_TRANSFORM_STATE_SLH@>
<@def GPU_TRANSFORM_STATE_SLH@>
<@func declareStandardTransform()@>
struct TransformObject {
mat4 _model;
mat4 _modelInverse;
};
struct TransformCamera {
<@func declareStandardCameraTransform()@>
struct TransformCamera {
mat4 _view;
mat4 _viewInverse;
mat4 _projectionViewUntranslated;
@ -25,13 +20,6 @@ struct TransformCamera {
vec4 _viewport;
};
layout(std140) uniform transformObjectBuffer {
TransformObject _object;
};
TransformObject getTransformObject() {
return _object;
}
layout(std140) uniform transformCameraBuffer {
TransformCamera _camera;
};
@ -40,6 +28,50 @@ TransformCamera getTransformCamera() {
}
<@endfunc@>
<@func declareStandardObjectTransform()@>
struct TransformObject {
mat4 _model;
mat4 _modelInverse;
};
layout(location=15) in ivec2 _drawCallInfo;
<@if FALSE @>
// Disable SSBOs for now
layout(std140) buffer transformObjectBuffer {
TransformObject _object[];
};
TransformObject getTransformObject() {
return _object[_drawCallInfo.x];
}
<@else@>
uniform samplerBuffer transformObjectBuffer;
TransformObject getTransformObject() {
int offset = 8 * _drawCallInfo.x;
TransformObject object;
object._model[0] = texelFetch(transformObjectBuffer, offset);
object._model[1] = texelFetch(transformObjectBuffer, offset + 1);
object._model[2] = texelFetch(transformObjectBuffer, offset + 2);
object._model[3] = texelFetch(transformObjectBuffer, offset + 3);
object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);
object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);
object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);
object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);
return object;
}
<@endif@>
<@endfunc@>
<@func declareStandardTransform()@>
<$declareStandardObjectTransform()$>
<$declareStandardCameraTransform()$>
<@endfunc@>
<@func transformCameraViewport(cameraTransform, viewport)@>
<$viewport$> = <$cameraTransform$>._viewport;
<@endfunc@>
@ -53,15 +85,6 @@ TransformCamera getTransformCamera() {
}
<@endfunc@>
<@func transformInstancedModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // transformModelToClipPos
vec4 _eyepos = (inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0);
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos;
}
<@endfunc@>
<@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
@ -74,30 +97,12 @@ TransformCamera getTransformCamera() {
}
<@endfunc@>
<@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // transformModelToClipPos
vec4 _worldpos = (inInstanceTransform * <$modelPos$>);
<$eyePos$> = (<$cameraTransform$>._view * _worldpos);
vec4 _eyepos =(inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0);
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos;
// <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>);
}
<@endfunc@>
<@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@>
{ // transformModelToWorldPos
<$worldPos$> = (<$objectTransform$>._model * <$modelPos$>);
}
<@endfunc@>
<@func transformInstancedModelToWorldPos(objectTransform, modelPos, worldPos)@>
{ // transformModelToWorldPos
<$worldPos$> = (inInstanceTransform * <$modelPos$>);
}
<@endfunc@>
<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
{ // transformModelToEyeDir
vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x);
@ -112,21 +117,6 @@ TransformCamera getTransformCamera() {
}
<@endfunc@>
<@func transformInstancedModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
{ // transformModelToEyeDir
mat4 modelInverse = inverse(inInstanceTransform);
vec3 mr0 = vec3(modelInverse[0].x, modelInverse[1].x, modelInverse[2].x);
vec3 mr1 = vec3(modelInverse[0].y, modelInverse[1].y, modelInverse[2].y);
vec3 mr2 = vec3(modelInverse[0].z, modelInverse[1].z, modelInverse[2].z);
vec3 mvc0 = vec3(dot(<$cameraTransform$>._viewInverse[0].xyz, mr0), dot(<$cameraTransform$>._viewInverse[0].xyz, mr1), dot(<$cameraTransform$>._viewInverse[0].xyz, mr2));
vec3 mvc1 = vec3(dot(<$cameraTransform$>._viewInverse[1].xyz, mr0), dot(<$cameraTransform$>._viewInverse[1].xyz, mr1), dot(<$cameraTransform$>._viewInverse[1].xyz, mr2));
vec3 mvc2 = vec3(dot(<$cameraTransform$>._viewInverse[2].xyz, mr0), dot(<$cameraTransform$>._viewInverse[2].xyz, mr1), dot(<$cameraTransform$>._viewInverse[2].xyz, mr2));
<$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>));
}
<@endfunc@>
<@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@>
{ // transformEyeToWorldDir
<$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0));

View file

@ -43,7 +43,6 @@ static const int VERTICES_PER_TRIANGLE = 3;
static const gpu::Element POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
static const gpu::Element NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
static const gpu::Element COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA };
static const gpu::Element TRANSFORM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW };
static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT;
static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;
@ -491,7 +490,6 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::INSTANCE_XFM, gpu::Stream::INSTANCE_XFM, TRANSFORM_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
}
return INSTANCED_SOLID_STREAM_FORMAT;
}
@ -511,11 +509,9 @@ GeometryCache::~GeometryCache() {
#endif //def WANT_DEBUG
}
void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) {
gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
batch.setInputBuffer(gpu::Stream::COLOR, colorView);
gpu::BufferView instanceXfmView(transformBuffer, 0, transformBuffer->getSize(), TRANSFORM_ELEMENT);
batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView);
}
void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) {
@ -528,24 +524,24 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) {
_shapes[shape].drawWire(batch);
}
void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer) {
void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) {
batch.setInputFormat(getInstancedSolidStreamFormat());
setupBatchInstance(batch, transformBuffer, colorBuffer);
setupBatchInstance(batch, colorBuffer);
_shapes[shape].drawInstances(batch, count);
}
void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer) {
void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) {
batch.setInputFormat(getInstancedSolidStreamFormat());
setupBatchInstance(batch, transformBuffer, colorBuffer);
setupBatchInstance(batch, colorBuffer);
_shapes[shape].drawWireInstances(batch, count);
}
void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
renderShapeInstances(batch, Cube, count, transformBuffer, colorBuffer);
void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
renderShapeInstances(batch, Cube, count, colorBuffer);
}
void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
renderWireShapeInstances(batch, Cube, count, transformBuffer, colorBuffer);
void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
renderWireShapeInstances(batch, Cube, count, colorBuffer);
}
void GeometryCache::renderCube(gpu::Batch& batch) {
@ -556,8 +552,8 @@ void GeometryCache::renderWireCube(gpu::Batch& batch) {
renderWireShape(batch, Cube);
}
void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
renderShapeInstances(batch, Sphere, count, transformBuffer, colorBuffer);
void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
renderShapeInstances(batch, Sphere, count, colorBuffer);
}
void GeometryCache::renderSphere(gpu::Batch& batch) {
@ -1854,45 +1850,34 @@ uint32_t toCompactColor(const glm::vec4& color) {
return compactColor;
}
static const size_t INSTANCE_TRANSFORM_BUFFER = 0;
static const size_t INSTANCE_COLOR_BUFFER = 1;
static const size_t INSTANCE_COLOR_BUFFER = 0;
template <typename F>
void renderInstances(const std::string& name, gpu::Batch& batch, const Transform& transform, const glm::vec4& color, F f) {
void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4& color, F f) {
{
gpu::BufferPointer instanceTransformBuffer = batch.getNamedBuffer(name, INSTANCE_TRANSFORM_BUFFER);
glm::mat4 glmTransform;
instanceTransformBuffer->append(transform.getMatrix(glmTransform));
gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(name, INSTANCE_COLOR_BUFFER);
auto compactColor = toCompactColor(color);
instanceColorBuffer->append(compactColor);
}
batch.setupNamedCalls(name, [f](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
auto pipeline = DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
auto location = pipeline->getProgram()->getUniforms().findLocation("Instanced");
batch._glUniform1i(location, 1);
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
f(batch, data);
batch._glUniform1i(location, 0);
});
}
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) {
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color) {
static const std::string INSTANCE_NAME = __FUNCTION__;
renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, GeometryCache::Sphere, data.count,
data.buffers[INSTANCE_TRANSFORM_BUFFER],
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, GeometryCache::Sphere, data.count(),
data.buffers[INSTANCE_COLOR_BUFFER]);
});
}
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) {
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color) {
static const std::string INSTANCE_NAME = __FUNCTION__;
renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count,
data.buffers[INSTANCE_TRANSFORM_BUFFER],
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count(),
data.buffers[INSTANCE_COLOR_BUFFER]);
});
}
@ -1901,12 +1886,12 @@ void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const Transform&
// available shape types, both solid and wireframes
//#define DEBUG_SHAPES
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) {
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color) {
static const std::string INSTANCE_NAME = __FUNCTION__;
#ifdef DEBUG_SHAPES
static auto startTime = usecTimestampNow();
renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
auto usecs = usecTimestampNow();
usecs -= startTime;
@ -1931,29 +1916,25 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const Transform&
// For the first half second for a given shape, show the wireframe, for the second half, show the solid.
if (fractionalSeconds > 0.5f) {
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count,
data.buffers[INSTANCE_TRANSFORM_BUFFER],
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count(),
data.buffers[INSTANCE_COLOR_BUFFER]);
} else {
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count,
data.buffers[INSTANCE_TRANSFORM_BUFFER],
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(),
data.buffers[INSTANCE_COLOR_BUFFER]);
}
});
#else
renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderCubeInstances(batch, data.count,
data.buffers[INSTANCE_TRANSFORM_BUFFER],
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderCubeInstances(batch, data.count(),
data.buffers[INSTANCE_COLOR_BUFFER]);
});
#endif
}
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) {
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color) {
static const std::string INSTANCE_NAME = __FUNCTION__;
renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderWireCubeInstances(batch, data.count,
data.buffers[INSTANCE_TRANSFORM_BUFFER],
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
DependencyManager::get<GeometryCache>()->renderWireCubeInstances(batch, data.count(),
data.buffers[INSTANCE_COLOR_BUFFER]);
});
}

View file

@ -154,41 +154,41 @@ public:
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
bool emissive = false, bool depthBias = false);
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) {
renderSolidSphereInstance(batch, xfm, glm::vec4(color, 1.0));
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color);
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
renderSolidSphereInstance(batch, glm::vec4(color, 1.0));
}
void renderWireSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
void renderWireSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) {
renderWireSphereInstance(batch, xfm, glm::vec4(color, 1.0));
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color);
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
renderWireSphereInstance(batch, glm::vec4(color, 1.0));
}
void renderSolidCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
void renderSolidCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) {
renderSolidCubeInstance(batch, xfm, glm::vec4(color, 1.0));
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color);
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
renderSolidCubeInstance(batch, glm::vec4(color, 1.0));
}
void renderWireCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
void renderWireCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) {
renderWireCubeInstance(batch, xfm, glm::vec4(color, 1.0));
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color);
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
renderWireCubeInstance(batch, glm::vec4(color, 1.0));
}
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer);
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer);
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
void renderShape(gpu::Batch& batch, Shape shape);
void renderWireShape(gpu::Batch& batch, Shape shape);
size_t getShapeTriangleCount(Shape shape);
void renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
void renderCube(gpu::Batch& batch);
void renderWireCube(gpu::Batch& batch);
size_t getCubeTriangleCount();
void renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
void renderSphere(gpu::Batch& batch);
void renderWireSphere(gpu::Batch& batch);
size_t getSphereTriangleCount();

View file

@ -17,7 +17,7 @@
<@include DeferredLighting.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<$declareStandardCameraTransform()$>
// Everything about light

View file

@ -17,9 +17,7 @@
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
uniform bool Instanced = false;
// the interpolated normal
out vec3 _normal;
out vec3 _modelNormal;
out vec3 _color;
@ -35,11 +33,6 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
if (Instanced) {
<$transformInstancedModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformInstancedModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
} else {
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
}
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
}

View file

@ -124,7 +124,6 @@ class QTestWindow : public QWindow {
glm::mat4 _projectionMatrix;
RateCounter fps;
QTime _time;
int _instanceLocation{ -1 };
protected:
void renderText();
@ -164,7 +163,6 @@ public:
state->setMultisampleEnable(true);
state->setDepthTest(gpu::State::DepthTest { true });
_pipeline = gpu::Pipeline::create(shader, state);
_instanceLocation = _pipeline->getProgram()->getUniforms().findLocation("Instanced");
// Clear screen
gpu::Batch batch;
@ -218,16 +216,16 @@ public:
static const std::string GRID_INSTANCE = "Grid";
static auto compactColor1 = toCompactColor(vec4{ 0.35f, 0.25f, 0.15f, 1.0f });
static auto compactColor2 = toCompactColor(vec4{ 0.15f, 0.25f, 0.35f, 1.0f });
static gpu::BufferPointer transformBuffer;
static std::vector<glm::mat4> transforms;
static gpu::BufferPointer colorBuffer;
if (!transformBuffer) {
transformBuffer = std::make_shared<gpu::Buffer>();
if (!transforms.empty()) {
transforms.reserve(200);
colorBuffer = std::make_shared<gpu::Buffer>();
for (int i = 0; i < 100; ++i) {
{
glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i));
transform = glm::scale(transform, vec3(100, 1, 1));
transformBuffer->append(transform);
transforms.push_back(transform);
colorBuffer->append(compactColor1);
}
@ -235,20 +233,20 @@ public:
glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0)));
transform = glm::translate(transform, vec3(0, -1, -50 + i));
transform = glm::scale(transform, vec3(100, 1, 1));
transformBuffer->append(transform);
transforms.push_back(transform);
colorBuffer->append(compactColor2);
}
}
}
batch.setupNamedCalls(GRID_INSTANCE, 200, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
batch.setViewTransform(camera);
batch.setModelTransform(Transform());
batch.setPipeline(_pipeline);
batch._glUniform1i(_instanceLocation, 1);
geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count, transformBuffer, colorBuffer);
batch._glUniform1i(_instanceLocation, 0);
});
for (auto& transform : transforms) {
batch.setModelTransform(transform);
batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
batch.setViewTransform(camera);
batch.setPipeline(_pipeline);
geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count(), colorBuffer);
});
}
}
{
@ -316,14 +314,11 @@ public:
batch.setViewTransform(camera);
batch.setModelTransform(Transform());
batch.setPipeline(_pipeline);
batch._glUniform1i(_instanceLocation, 1);
batch.setInputFormat(getInstancedSolidStreamFormat());
batch.setInputBuffer(gpu::Stream::COLOR, colorView);
batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView);
batch.setIndirectBuffer(indirectBuffer);
shapeData.setupBatch(batch);
batch.multiDrawIndexedIndirect(TYPE_COUNT, gpu::TRIANGLES);
batch._glUniform1i(_instanceLocation, 0);
}
#else
batch.setViewTransform(camera);

View file

@ -19,8 +19,6 @@
<$declareStandardTransform()$>
// the interpolated normal
uniform bool Instanced = false;
out vec3 _normal;
out vec3 _color;
out vec2 _texCoord0;
@ -32,12 +30,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
if (Instanced) {
<$transformInstancedModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformInstancedModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
} else {
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
}
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
_normal = vec3(0.0, 0.0, 1.0);
}