Merging with Brad's branch and trying to get the rendering working

This commit is contained in:
Sam Gateau 2015-05-31 14:02:20 -07:00
parent 34fd1bd470
commit 4c817547b7
9 changed files with 267 additions and 165 deletions

View file

@ -842,7 +842,7 @@ void Application::paintGL() {
_glWidget->makeCurrent();
auto lodManager = DependencyManager::get<LODManager>();
gpu::Context context;
gpu::Context context(new gpu::GLBackend());
RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);

View file

@ -524,7 +524,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) {
_tree->unlock();
glPushMatrix();
renderArgs->_context->enqueueBatch(batch);
renderArgs->_context->render(batch);
glPopMatrix();
renderArgs->_batch = nullptr;

View file

@ -15,7 +15,8 @@
using namespace gpu;
Context::Context() {
Context::Context(Backend* backend) :
_backend(backend) {
}
Context::Context(const Context& context) {
@ -31,6 +32,7 @@ bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) {
return false;
}
void Context::enqueueBatch(Batch& batch) {
GLBackend::renderBatch(batch, true);
void Context::render(Batch& batch) {
_backend->render(batch);
// GLBackend::renderBatch(batch, true);
}

View file

@ -31,6 +31,9 @@ class Batch;
class Backend {
public:
virtual~ Backend() {};
virtual void render(Batch& batch) = 0;
class TransformObject {
public:
Mat4 _model;
@ -107,15 +110,14 @@ protected:
class Context {
public:
Context();
Context(const Context& context);
Context(Backend* backend);
~Context();
void enqueueBatch(Batch& batch);
void render(Batch& batch);
protected:
Context(const Context& context);
// This function can only be called by "static Shader::makeProgram()"
// makeProgramShader(...) make a program shader ready to be used in a Batch.
@ -123,6 +125,8 @@ protected:
// If the shader passed is not a program, nothing happens.
static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet());
std::unique_ptr<Backend> _backend;
friend class Shader;
};

View file

@ -442,6 +442,8 @@ void Batch::_glUniform1f(GLint location, GLfloat v0) {
}
void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) {
if (_pipeline._program == 0) {
// We should call updatePipeline() to bind the program but we are not doing that
// because these uniform setters are deprecated and we don;t want to create side effect
return;
}
glUniform1f(
@ -460,6 +462,11 @@ void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) {
DO_IT_NOW(_glUniform2f, 1);
}
void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) {
if (_pipeline._program == 0) {
// We should call updatePipeline() to bind the program but we are not doing that
// because these uniform setters are deprecated and we don;t want to create side effect
return;
}
glUniform2f(
batch._params[paramOffset + 2]._int,
batch._params[paramOffset + 1]._float,
@ -478,6 +485,11 @@ void Batch::_glUniform4fv(GLint location, GLsizei count, const GLfloat* value) {
DO_IT_NOW(_glUniform4fv, 3);
}
void GLBackend::do_glUniform4fv(Batch& batch, uint32 paramOffset) {
if (_pipeline._program == 0) {
// We should call updatePipeline() to bind the program but we are not doing that
// because these uniform setters are deprecated and we don;t want to create side effect
return;
}
glUniform4fv(
batch._params[paramOffset + 2]._int,
batch._params[paramOffset + 1]._uint,
@ -498,6 +510,11 @@ void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpo
DO_IT_NOW(_glUniformMatrix4fv, 4);
}
void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) {
if (_pipeline._program == 0) {
// We should call updatePipeline() to bind the program but we are not doing that
// because these uniform setters are deprecated and we don;t want to create side effect
return;
}
glUniformMatrix4fv(
batch._params[paramOffset + 3]._int,
batch._params[paramOffset + 2]._uint,

View file

@ -26,9 +26,9 @@ public:
explicit GLBackend(bool syncCache);
GLBackend();
~GLBackend();
virtual ~GLBackend();
void render(Batch& batch);
virtual void render(Batch& batch);
// Render Batch create a local Context and execute the batch with it
// WARNING:

View file

@ -107,7 +107,7 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
}
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured) {
DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(batch, true, true, true);
// DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(batch, true, true, true);
if (textured) {
batch.setPipeline(_simpleProgramTextured);
@ -117,7 +117,7 @@ void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured)
}
void DeferredLightingEffect::releaseSimpleProgram(gpu::Batch& batch) {
DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(batch, true, false, false);
// DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(batch, true, false, false);
}
void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {

View file

@ -783,7 +783,7 @@ namespace render {
}
template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) {
qDebug() << "payloadGetBound(TransparentMeshPart) url:" << payload->model->getURL();
//qDebug() << "payloadGetBound(TransparentMeshPart) url:" << payload->model->getURL();
if (payload) {
//return payload->model->getPartBounds(payload->meshIndex, payload->partIndex);
}
@ -791,7 +791,7 @@ namespace render {
}
template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) {
if (args) {
qDebug() << "payloadRender(TransparentMeshPart) url:" << payload->model->getURL();
// qDebug() << "payloadRender(TransparentMeshPart) url:" << payload->model->getURL();
args->_elementsTouched++;
return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true);
}
@ -815,7 +815,7 @@ namespace render {
}
template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) {
qDebug() << "payloadGetBound(OpaqueMeshPart) url:" << payload->model->getURL();
// qDebug() << "payloadGetBound(OpaqueMeshPart) url:" << payload->model->getURL();
if (payload) {
//return payload->model->getPartBounds(payload->meshIndex, payload->partIndex);
}
@ -823,7 +823,7 @@ namespace render {
}
template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) {
if (args) {
qDebug() << "payloadRender(OpaqueMeshPart) url:" << payload->model->getURL();
// qDebug() << "payloadRender(OpaqueMeshPart) url:" << payload->model->getURL();
args->_elementsTouched++;
return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false);
}
@ -1957,9 +1957,12 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
}
void Model::endScene(RenderArgs* args) {
// Now that we migrated everything to the new RENDER/SCENE no more work to do!
return;
PROFILE_RANGE(__FUNCTION__);
#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY)
// with legacy transform profile, we still to protect that transform stack...
glPushMatrix();
@ -1972,6 +1975,7 @@ void Model::endScene(RenderArgs* args) {
renderSide = args->_renderSide;
}
gpu::GLBackend backend;
backend.syncCache(); // force sync with gl state here
@ -2191,7 +2195,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) {
//renderCore(args, 1.0f);
//return;
qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url;
//qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url;
renderSetup(args);
auto textureCache = DependencyManager::get<TextureCache>();
@ -2229,7 +2233,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
// FIXME: Do I need this? it doesn't seem to do anything.
{
/* {
GLenum buffers[3];
int bufferCount = 0;
@ -2243,7 +2247,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
}
GLBATCH(glDrawBuffers)(bufferCount, buffers);
}
}*/
const float DEFAULT_ALPHA_THRESHOLD = 0.5f; //
auto alphaThreshold = DEFAULT_ALPHA_THRESHOLD; // FIX ME
@ -2285,7 +2289,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {
_meshGroupsKnown = false; // regenerate these lists next time around.
qDebug() << "if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {.... BAIL!!!";
// qDebug() << "if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {.... BAIL!!!";
return; // FIXME!
}
@ -2297,7 +2301,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
int vertexCount = mesh.vertices.size();
if (vertexCount == 0) {
// sanity check
qDebug() << "if (vertexCount == 0) {.... BAIL!!!";
// qDebug() << "if (vertexCount == 0) {.... BAIL!!!";
return; // FIXME!
}
@ -2321,10 +2325,10 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
}
if (mesh.colors.isEmpty()) {
qDebug() << " colors empty ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url;
// qDebug() << " colors empty ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url;
GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f);
} else {
qDebug() << " colors size:" << mesh.colors.size() << " ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url;
// qDebug() << " colors size:" << mesh.colors.size() << " ... meshIndex:" << meshIndex << "partIndex:" << partIndex << "url:" << _url;
}
qint64 offset = 0;
@ -2333,6 +2337,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
const FBXMeshPart& part = mesh.parts.at(j);
model::MaterialPointer material = part._material;
if (material != nullptr) {
/*
if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) {
offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int);
@ -2340,86 +2345,88 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
}
*/
// apply material properties
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
/// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
// apply material properties
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
/// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
} else {
if (true) { //lastMaterialID != part.materialID) {
const bool wantDebug = true;
if (wantDebug) {
qCDebug(renderutils) << "Material Changed ---------------------------------------------";
qCDebug(renderutils) << "part INDEX:" << j;
qCDebug(renderutils) << "NEW part.materialID:" << part.materialID;
}
} else {
if (true) { //lastMaterialID != part.materialID) {
const bool wantDebug = false;
if (wantDebug) {
qCDebug(renderutils) << "Material Changed ---------------------------------------------";
qCDebug(renderutils) << "part INDEX:" << j;
qCDebug(renderutils) << "NEW part.materialID:" << part.materialID;
}
if (locations->materialBufferUnit >= 0) {
batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer());
}
if (locations->materialBufferUnit >= 0) {
batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer());
}
Texture* diffuseMap = networkPart.diffuseTexture.data();
if (mesh.isEye && diffuseMap) {
diffuseMap = (_dilatedTextures[i][j] =
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
}
static bool showDiffuse = true;
if (showDiffuse && diffuseMap) {
qCDebug(renderutils) << " batch.setUniformTexture(0, diffuseMap->getGPUTexture());";
batch.setUniformTexture(0, diffuseMap->getGPUTexture());
Texture* diffuseMap = networkPart.diffuseTexture.data();
if (mesh.isEye && diffuseMap) {
diffuseMap = (_dilatedTextures[i][j] =
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
}
static bool showDiffuse = true;
if (showDiffuse && diffuseMap) {
// qCDebug(renderutils) << " batch.setUniformTexture(0, diffuseMap->getGPUTexture());";
batch.setUniformTexture(0, diffuseMap->getGPUTexture());
} else {
qCDebug(renderutils) << " batch.setUniformTexture(0, textureCache->getWhiteTexture());";
batch.setUniformTexture(0, textureCache->getWhiteTexture());
}
if (locations->texcoordMatrices >= 0) {
glm::mat4 texcoordTransform[2];
if (!part.diffuseTexture.transform.isIdentity()) {
qCDebug(renderutils) << " part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);";
part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);
} else {
// qCDebug(renderutils) << " batch.setUniformTexture(0, textureCache->getWhiteTexture());";
batch.setUniformTexture(0, textureCache->getWhiteTexture());
}
if (!part.emissiveTexture.transform.isIdentity()) {
qCDebug(renderutils) << " part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);";
part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);
if (locations->texcoordMatrices >= 0) {
glm::mat4 texcoordTransform[2];
if (!part.diffuseTexture.transform.isIdentity()) {
// qCDebug(renderutils) << " part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);";
part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);
}
if (!part.emissiveTexture.transform.isIdentity()) {
// qCDebug(renderutils) << " part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);";
part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);
}
// qCDebug(renderutils) << " GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);";
GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);
}
qCDebug(renderutils) << " GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);";
GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);
}
if (!mesh.tangents.isEmpty()) {
Texture* normalMap = networkPart.normalTexture.data();
qCDebug(renderutils) << " batch.setUniformTexture(1, !normalMap ? textureCache->getBlueTexture() : normalMap->getGPUTexture());";
batch.setUniformTexture(1, !normalMap ?
textureCache->getBlueTexture() : normalMap->getGPUTexture());
if (!mesh.tangents.isEmpty()) {
Texture* normalMap = networkPart.normalTexture.data();
// qCDebug(renderutils) << " batch.setUniformTexture(1, !normalMap ? textureCache->getBlueTexture() : normalMap->getGPUTexture());";
batch.setUniformTexture(1, !normalMap ?
textureCache->getBlueTexture() : normalMap->getGPUTexture());
}
}
if (locations->specularTextureUnit >= 0) {
Texture* specularMap = networkPart.specularTexture.data();
qCDebug(renderutils) << " batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture());";
batch.setUniformTexture(locations->specularTextureUnit, !specularMap ?
textureCache->getWhiteTexture() : specularMap->getGPUTexture());
if (locations->specularTextureUnit >= 0) {
Texture* specularMap = networkPart.specularTexture.data();
// qCDebug(renderutils) << " batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture());";
batch.setUniformTexture(locations->specularTextureUnit, !specularMap ?
textureCache->getWhiteTexture() : specularMap->getGPUTexture());
}
if (args) {
args->_materialSwitches++;
}
}
if (args) {
args->_materialSwitches++;
// HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every
// drawcall with an emissive, so let's do it for now.
if (locations->emissiveTextureUnit >= 0) {
// assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader
float emissiveOffset = part.emissiveParams.x;
float emissiveScale = part.emissiveParams.y;
GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale);
Texture* emissiveMap = networkPart.emissiveTexture.data();
// qCDebug(renderutils) << " batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());";
batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ?
textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());
}
}
// HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every
// drawcall with an emissive, so let's do it for now.
if (locations->emissiveTextureUnit >= 0) {
// assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader
float emissiveOffset = part.emissiveParams.x;
float emissiveScale = part.emissiveParams.y;
GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale);
Texture* emissiveMap = networkPart.emissiveTexture.data();
qCDebug(renderutils) << " batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());";
batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ?
textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());
}
lastMaterialID = part.materialID;
}
@ -2427,13 +2434,13 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
meshPartsRendered++;
if (part.quadIndices.size() > 0) {
qDebug() << "batch.drawIndexed(gpu::QUADS) size:" << part.quadIndices.size();
// qDebug() << "batch.drawIndexed(gpu::QUADS) size:" << part.quadIndices.size();
batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset);
offset += part.quadIndices.size() * sizeof(int);
}
if (part.triangleIndices.size() > 0) {
qDebug() << "batch.drawIndexed(gpu::TRIANGLES) size:" << part.triangleIndices.size();
// qDebug() << "batch.drawIndexed(gpu::TRIANGLES) size:" << part.triangleIndices.size();
batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset);
offset += part.triangleIndices.size() * sizeof(int);
}
@ -2483,7 +2490,7 @@ qDebug() << "Model::renderPart()... meshIndex:" << meshIndex << "partIndex:" <<
*/
// Back to no program
GLBATCH(glUseProgram)(0); // NOTE: We need this or else the avatar will end up with the texture of the last entity
// GLBATCH(glUseProgram)(0); // NOTE: We need this or else the avatar will end up with the texture of the last entity
}
void Model::segregateMeshGroups() {

View file

@ -55,73 +55,6 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon
Job::~Job() {
}
template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render opaques
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape());
ItemIDs inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems);
ItemIDs sortedItems;
depthSortItems(sceneContext, renderContext, true, culledItems, sortedItems); // Sort Front to back opaque items!
renderItems(sceneContext, renderContext, sortedItems);
}
template <> void render::jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render transparents
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape());
ItemIDs inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems);
ItemIDs sortedItems;
depthSortItems(sceneContext, renderContext, false, culledItems, sortedItems); // Sort Back to front transparent items!
renderItems(sceneContext, renderContext, sortedItems);
}
template <> void render::jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render lights
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light());
ItemIDs inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems);
renderItems(sceneContext, renderContext, culledItems);
}
/*
bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) {
const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
@ -263,16 +196,155 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems) {
auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args;
gpu::Batch theBatch;
args->_batch = &theBatch;
// render
for (auto id : inItems) {
auto item = scene->getItem(id);
item.render(args);
}
}
args->_context->enqueueBatch((*args->_batch));
void addClearStateCommands(gpu::Batch& batch) {
batch._glDepthMask(true);
batch._glDepthFunc(GL_LESS);
batch._glDisable(GL_CULL_FACE);
batch._glActiveTexture(GL_TEXTURE0 + 1);
batch._glBindTexture(GL_TEXTURE_2D, 0);
batch._glActiveTexture(GL_TEXTURE0 + 2);
batch._glBindTexture(GL_TEXTURE_2D, 0);
batch._glActiveTexture(GL_TEXTURE0 + 3);
batch._glBindTexture(GL_TEXTURE_2D, 0);
batch._glActiveTexture(GL_TEXTURE0);
batch._glBindTexture(GL_TEXTURE_2D, 0);
// deactivate vertex arrays after drawing
batch._glDisableClientState(GL_NORMAL_ARRAY);
batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_TEXTURE_COORD_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
batch._glDisableVertexAttribArray(gpu::Stream::TANGENT);
batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_INDEX);
batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_WEIGHT);
// bind with 0 to switch back to normal operation
batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
batch._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
batch._glBindTexture(GL_TEXTURE_2D, 0);
// Back to no program
batch._glUseProgram(0);
}
template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render opaques
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape());
ItemIDs inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems);
ItemIDs sortedItems;
depthSortItems(sceneContext, renderContext, true, culledItems, sortedItems); // Sort Front to back opaque items!
RenderArgs* args = renderContext->args;
gpu::Batch theBatch;
args->_batch = &theBatch;
glm::mat4 proj;
args->_viewFrustum->evalProjectionMatrix(proj);
theBatch.setProjectionTransform(proj);
renderContext->args->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
{
GLenum buffers[3];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
theBatch._glDrawBuffers(bufferCount, buffers);
}
renderItems(sceneContext, renderContext, sortedItems);
addClearStateCommands((*args->_batch));
args->_context->render((*args->_batch));
args->_batch = nullptr;
}
}
template <> void render::jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render transparents
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape());
ItemIDs inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems);
ItemIDs sortedItems;
depthSortItems(sceneContext, renderContext, false, culledItems, sortedItems); // Sort Back to front transparent items!
RenderArgs* args = renderContext->args;
gpu::Batch theBatch;
args->_batch = &theBatch;
renderContext->args->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
{
GLenum buffers[3];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
theBatch._glDrawBuffers(bufferCount, buffers);
}
renderItems(sceneContext, renderContext, sortedItems);
addClearStateCommands((*args->_batch));
args->_context->render((*args->_batch));
args->_batch = nullptr;
}
template <> void render::jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render lights
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light());
ItemIDs inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems);
RenderArgs* args = renderContext->args;
gpu::Batch theBatch;
args->_batch = &theBatch;
renderItems(sceneContext, renderContext, culledItems);
args->_context->render((*args->_batch));
args->_batch = nullptr;
}