Exposing the viewport to the shader and have a first draft of the draw status pipeline

This commit is contained in:
Sam Gateau 2015-06-30 14:43:57 -07:00
parent 20cb519c14
commit 8bd5e15f73
13 changed files with 198 additions and 5 deletions

View file

@ -159,6 +159,12 @@ void Batch::setProjectionTransform(const Mat4& proj) {
_params.push_back(cacheData(sizeof(Mat4), &proj));
}
void Batch::setViewportTransform(const Vec4i& viewport) {
ADD_COMMAND(setViewportTransform);
_params.push_back(cacheData(sizeof(Vec4i), &viewport));
}
void Batch::setPipeline(const PipelinePointer& pipeline) {
ADD_COMMAND(setPipeline);

View file

@ -105,6 +105,7 @@ public:
void setModelTransform(const Transform& model);
void setViewTransform(const Transform& view);
void setProjectionTransform(const Mat4& proj);
void setViewportTransform(const Vec4i& viewport); // Viewport is xy = low left corner in the framebuffer, zw = width height of the viewport
// Pipeline Stage
void setPipeline(const PipelinePointer& pipeline);
@ -177,6 +178,7 @@ public:
COMMAND_setModelTransform,
COMMAND_setViewTransform,
COMMAND_setProjectionTransform,
COMMAND_setViewportTransform,
COMMAND_setPipeline,
COMMAND_setStateBlendFactor,

View file

@ -38,6 +38,7 @@ typedef uint32 Offset;
typedef glm::mat4 Mat4;
typedef glm::mat3 Mat3;
typedef glm::vec4 Vec4;
typedef glm::ivec4 Vec4i;
typedef glm::vec3 Vec3;
typedef glm::vec2 Vec2;
typedef glm::ivec2 Vec2i;

View file

@ -29,6 +29,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_setModelTransform),
(&::gpu::GLBackend::do_setViewTransform),
(&::gpu::GLBackend::do_setProjectionTransform),
(&::gpu::GLBackend::do_setViewportTransform),
(&::gpu::GLBackend::do_setPipeline),
(&::gpu::GLBackend::do_setStateBlendFactor),

View file

@ -96,7 +96,9 @@ public:
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
GLuint _transformObject_model = -1;
GLuint _transformCamera_viewInverse = -1;
GLuint _transformCamera_viewport = -1;
#endif
GLShader();
@ -267,7 +269,8 @@ protected:
void do_setModelTransform(Batch& batch, uint32 paramOffset);
void do_setViewTransform(Batch& batch, uint32 paramOffset);
void do_setProjectionTransform(Batch& batch, uint32 paramOffset);
void do_setViewportTransform(Batch& batch, uint32 paramOffset);
void initTransform();
void killTransform();
// Synchronize the state cache of this Backend with the actual real state of the GL Context
@ -281,9 +284,11 @@ protected:
Transform _model;
Transform _view;
Mat4 _projection;
Vec4i _viewport;
bool _invalidModel;
bool _invalidView;
bool _invalidProj;
bool _invalidViewport;
GLenum _lastMode;
@ -296,6 +301,7 @@ protected:
_invalidModel(true),
_invalidView(true),
_invalidProj(false),
_invalidViewport(false),
_lastMode(GL_TEXTURE) {}
} _transform;
@ -329,7 +335,9 @@ protected:
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
GLint _program_transformObject_model = -1;
GLint _program_transformCamera_viewInverse = -1;
GLint _program_transformCamera_viewport = -1;
#endif
State::Data _stateCache;

View file

@ -73,7 +73,9 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
_pipeline._program_transformObject_model = -1;
_pipeline._program_transformCamera_viewInverse = -1;
_pipeline._program_transformCamera_viewport = -1;
#endif
_pipeline._state = nullptr;
@ -91,7 +93,9 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
_pipeline._program_transformObject_model = pipelineObject->_program->_transformObject_model;
_pipeline._program_transformCamera_viewInverse = pipelineObject->_program->_transformCamera_viewInverse;
_pipeline._program_transformCamera_viewport = pipelineObject->_program->_transformCamera_viewport;
#endif
}
@ -143,10 +147,20 @@ void GLBackend::updatePipeline() {
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
// If shader program needs the model we need to provide it
if (_pipeline._program_transformObject_model >= 0) {
glUniformMatrix4fv(_pipeline._program_transformObject_model, 1, false, (const GLfloat*) &_transform._transformObject._model);
}
// If shader program needs the inverseView we need to provide it
if (_pipeline._program_transformCamera_viewInverse >= 0) {
glUniformMatrix4fv(_pipeline._program_transformCamera_viewInverse, 1, false, (const GLfloat*) &_transform._transformCamera._viewInverse);
}
// If shader program needs the viewport we need to provide it
if (_pipeline._program_transformCamera_viewport >= 0) {
glUniform4fv(_pipeline._program_transformCamera_viewport, 1, (const GLfloat*) &_transform._transformCamera._viewport);
}
#endif
}

View file

@ -111,10 +111,20 @@ void makeBindings(GLBackend::GLShader* shader) {
shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
}
#else
loc = glGetUniformLocation(glprogram, "transformObject_model");
if (loc >= 0) {
shader->_transformObject_model = loc;
}
loc = glGetUniformLocation(glprogram, "transformCamera_viewInverse");
if (loc >= 0) {
shader->_transformCamera_viewInverse = loc;
}
loc = glGetUniformLocation(glprogram, "transformCamera_viewport");
if (loc >= 0) {
shader->_transformCamera_viewport = loc;
}
#endif
}

View file

@ -31,6 +31,12 @@ void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) {
_transform._invalidProj = true;
}
void GLBackend::do_setViewportTransform(Batch& batch, uint32 paramOffset) {
memcpy(&_transform._viewport, batch.editData(batch._params[paramOffset]._uint), sizeof(Vec4i));
_transform._invalidViewport = true;
}
void GLBackend::initTransform() {
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
glGenBuffers(1, &_transform._transformObjectBuffer);
@ -57,10 +63,13 @@ void GLBackend::killTransform() {
}
void GLBackend::syncTransformStateCache() {
_transform._invalidViewport = true;
_transform._invalidProj = true;
_transform._invalidView = true;
_transform._invalidModel = true;
glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport);
GLint currentMode;
glGetIntegerv(GL_MATRIX_MODE, &currentMode);
_transform._lastMode = currentMode;
@ -78,6 +87,13 @@ void GLBackend::updateTransform() {
GLint originalMatrixMode;
glGetIntegerv(GL_MATRIX_MODE, &originalMatrixMode);
// Check all the dirty flags and update the state accordingly
if (_transform._invalidViewport) {
_transform._transformCamera._viewport = glm::vec4(_transform._viewport);
// Where we assign the GL viewport
glViewport(_transform._viewport.x, _transform._viewport.y, _transform._viewport.z, _transform._viewport.w);
}
if (_transform._invalidProj) {
_transform._transformCamera._projection = _transform._projection;
_transform._transformCamera._projectionInverse = glm::inverse(_transform._projection);
@ -100,7 +116,7 @@ void GLBackend::updateTransform() {
}
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
if (_transform._invalidView || _transform._invalidProj) {
if (_transform._invalidView || _transform._invalidProj || _transform._invalidViewport) {
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0);
glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW);
@ -162,7 +178,8 @@ void GLBackend::updateTransform() {
#endif
// Flags are clean
_transform._invalidView = _transform._invalidProj = _transform._invalidModel = false;
_transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false;
glMatrixMode(originalMatrixMode);
}

View file

@ -87,10 +87,18 @@ TransformCamera getTransformCamera() {
}
uniform mat4 transformCamera_viewInverse;
uniform vec4 transformCamera_viewport;
<@endif@>
<@endfunc@>
<@func transformCameraViewport(cameraTransform, viewport)@>
<@if GPU_TRANSFORM_PROFILE == GPU_CORE@>
<$viewport$> = <$cameraTransform$>._viewport;
<@else@>
<$viewport$> = transformCamera_viewport;
<@endif@>
<@endfunc@>
<@func transformModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@>
<@if GPU_TRANSFORM_PROFILE == GPU_CORE@>

View file

@ -26,6 +26,8 @@
#include "drawItemBounds_vert.h"
#include "drawItemBounds_frag.h"
#include "drawItemStatus_vert.h"
#include "drawItemStatus_frag.h"
using namespace render;
@ -55,6 +57,30 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() {
return _drawItemBoundsPipeline;
}
const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() {
if (!_drawItemStatusPipeline) {
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemStatus_vert)));
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemStatus_frag)));
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(false, false, gpu::LESS_EQUAL);
// Blend on transparent
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);
// Good to go add the brand new pipeline
_drawItemStatusPipeline.reset(gpu::Pipeline::create(program, state));
}
return _drawItemStatusPipeline;
}
void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
@ -92,6 +118,21 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
}
}
batch.setPipeline(getDrawItemStatusPipeline());
for (auto& item : inItems) {
if (!item.bounds.isInvalid()) {
Transform model;
model.setTranslation(item.bounds.getCorner());
if (!item.bounds.isNull()) {
model.setScale(item.bounds.getDimensions());
}
batch.setModelTransform(model);
batch.draw(gpu::TRIANGLE_STRIP, 4, 0);
}
}
// Before rendering the batch make sure we re in sync with gl state
args->_context->syncCache();
renderContext->args->_context->syncCache();

View file

@ -14,12 +14,11 @@
#include "DrawTask.h"
#include "gpu/Batch.h"
#include <PerfStat.h>
namespace render {
class DrawStatus {
gpu::PipelinePointer _drawItemBoundsPipeline;
gpu::PipelinePointer _drawItemStatusPipeline;
public:
@ -28,6 +27,7 @@ namespace render {
typedef Job::ModelI<DrawStatus, ItemIDsBounds> JobModel;
const gpu::PipelinePointer& getDrawItemBoundsPipeline();
const gpu::PipelinePointer& getDrawItemStatusPipeline();
};
}

View file

@ -0,0 +1,19 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// drawItemStatus.frag
// fragment shader
//
// Created by Sam Gateau on 6/30/15.
// Copyright 2015 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
//
varying vec4 varColor;
void main(void) {
gl_FragColor = varColor;
}

View file

@ -0,0 +1,66 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// drawItemStatus.slv
// vertex shader
//
// Created by Sam Gateau on 6/30/2015.
// Copyright 2015 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 gpu/Transform.slh@>
<$declareStandardTransform()$>
varying vec4 varColor;
attribute vec4 inStatus;
vec3 paintRainbow(float nv) {
float v = nv * 5.f;
if ( v < 0.f )
return vec3(1.f, 0.f, 0.f);
else if ( v < 1.f)
return vec3(1.f, v, 0.f);
else if ( v < 2.f)
return vec3(1.f - (v-1.f), 1.f, 0.f);
else if ( v < 3.f)
return vec3(0.f, 1.f, (v-2.f));
else if ( v < 4.f)
return vec3(0.f, 1.f - (v-3.f), 1.f );
else if ( v < 5.f)
return vec3((v-4.f), 0.f, 1.f );
else
return vec3(1.f, 0.f, 1.f);
}
void main(void) {
const vec2 ICON_PIXEL_SIZE = vec2(10, 10);
const vec4 UNIT_QUAD[4] = vec4[4](
vec4(-1.0, -1.0, 0.0, 1.0),
vec4(1.0, -1.0, 0.0, 1.0),
vec4(-1.0, 1.0, 0.0, 1.0),
vec4(1.0, 1.0, 0.0, 1.0)
);
// Use the status for showing a color ?
varColor = vec4(paintRainbow(inStatus.x), 1.0);
vec4 anchorPoint = vec4(0.5, 0.5, 0.5, 1.0);
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$>
vec4 pos = UNIT_QUAD[gl_VertexID];
vec4 viewport;
<$transformCameraViewport(cam, viewport)$>;
vec2 clipIconSize = vec2(ICON_PIXEL_SIZE.x / viewport.z, ICON_PIXEL_SIZE.y / viewport.w);
gl_Position = anchorPoint + anchorPoint.w * vec4(pos.xy * clipIconSize, 0.0, 0.0);
}