Merge branch 'team-teaching' of https://github.com/highfidelity/hifi into team-teaching

This commit is contained in:
Atlante45 2015-06-08 19:20:33 +02:00
commit 36dfec7827
23 changed files with 401 additions and 94 deletions

View file

@ -66,19 +66,19 @@ panel.newCheckbox("Enable Render Transparent",
function(value) { return (value); }
);
panel.newSlider("Num Feed Transparents", 0, 1000,
panel.newSlider("Num Feed Transparents", 0, 100,
function(value) { },
function() { return Scene.getEngineNumFeedTransparentItems(); },
function(value) { return (value); }
);
panel.newSlider("Num Drawn Transparents", 0, 1000,
panel.newSlider("Num Drawn Transparents", 0, 100,
function(value) { },
function() { return Scene.getEngineNumDrawnTransparentItems(); },
function(value) { return (value); }
);
panel.newSlider("Max Drawn Transparents", -1, 1000,
panel.newSlider("Max Drawn Transparents", -1, 100,
function(value) { Scene.setEngineMaxDrawnTransparentItems(value); },
function() { return Scene.getEngineMaxDrawnTransparentItems(); },
function(value) { return (value); }

View file

@ -3191,6 +3191,7 @@ namespace render {
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
if (args->_renderMode != RenderArgs::MIRROR_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
PerformanceTimer perfTimer("worldBox");
auto& batch = *args->_batch;
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch);
renderWorldBox(batch);

View file

@ -13,6 +13,8 @@
#include <assert.h>
#include "Batch.h"
#include "Resource.h"
#include "Texture.h"
#include "Pipeline.h"
@ -20,14 +22,6 @@
namespace gpu {
class GPUObject {
public:
GPUObject() {}
virtual ~GPUObject() {}
};
class Batch;
class Backend {
public:

View file

@ -16,7 +16,11 @@
namespace gpu {
class GPUObject;
class GPUObject {
public:
GPUObject() {}
virtual ~GPUObject() {}
};
typedef int Stamp;

View file

@ -84,8 +84,13 @@ public:
GLuint _shader;
GLuint _program;
GLuint _transformCameraSlot = -1;
GLuint _transformObjectSlot = -1;
GLint _transformCameraSlot = -1;
GLint _transformObjectSlot = -1;
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
GLuint _transformCamera_viewInverse = -1;
#endif
GLShader();
~GLShader();
@ -287,14 +292,18 @@ protected:
_lastMode(GL_TEXTURE) {}
} _transform;
// Pipeline Stage
void do_setPipeline(Batch& batch, uint32 paramOffset);
void do_setStateBlendFactor(Batch& batch, uint32 paramOffset);
// Uniform Stage
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
void do_setUniformTexture(Batch& batch, uint32 paramOffset);
struct UniformStageState {
};
// Pipeline Stage
void do_setPipeline(Batch& batch, uint32 paramOffset);
void do_setStateBlendFactor(Batch& batch, uint32 paramOffset);
// Standard update pipeline check that the current Program and current State or good to go for a
void updatePipeline();
// Force to reset all the state fields indicated by the 'toBeReset" signature
@ -311,6 +320,11 @@ protected:
GLuint _program;
bool _invalidProgram;
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
GLint _program_transformCamera_viewInverse = -1;
#endif
State::Data _stateCache;
State::Signature _stateSignatureCache;

View file

@ -71,6 +71,11 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
_pipeline._program = 0;
_pipeline._invalidProgram = true;
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
_pipeline._program_transformCamera_viewInverse = -1;
#endif
_pipeline._state = nullptr;
_pipeline._invalidState = true;
} else {
@ -83,6 +88,11 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
if (_pipeline._program != pipelineObject->_program->_program) {
_pipeline._program = pipelineObject->_program->_program;
_pipeline._invalidProgram = true;
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
_pipeline._program_transformCamera_viewInverse = pipelineObject->_program->_transformCamera_viewInverse;
#endif
}
// Now for the state
@ -130,6 +140,14 @@ void GLBackend::updatePipeline() {
}
_pipeline._invalidState = false;
}
#if (GPU_TRANSFORM_PROFILE == GPU_CORE)
#else
// 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);
}
#endif
}
void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {

View file

@ -106,6 +106,11 @@ void makeBindings(GLBackend::GLShader* shader) {
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
}
#else
loc = glGetUniformLocation(glprogram, "transformCamera_viewInverse");
if (loc >= 0) {
shader->_transformCamera_viewInverse = loc;
}
#endif
}

View file

@ -8,8 +8,6 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Context.h"
#include "Resource.h"
#include <QDebug>

View file

@ -86,6 +86,8 @@ TransformCamera getTransformCamera() {
return camera;
}
uniform mat4 transformCamera_viewInverse;
<@endif@>
<@endfunc@>
@ -103,6 +105,23 @@ TransformCamera getTransformCamera() {
<@endif@>
<@endfunc@>
<@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
<@if GPU_TRANSFORM_PROFILE == GPU_CORE@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // transformModelToClipPos
vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>);
<$eyePos$> = (<$cameraTransform$>._view * _worldpos);
vec4 _eyepos =(<$objectTransform$>._model * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0);
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos;
// <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>);
}
<@else@>
<$eyePos$> = gl_ModelViewMatrix * <$modelPos$>;
<$clipPos$> = gl_ModelViewProjectionMatrix * <$modelPos$>;
<@endif@>
<@endfunc@>
<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
<@if GPU_TRANSFORM_PROFILE == GPU_CORE@>
{ // transformModelToEyeDir
@ -127,7 +146,7 @@ TransformCamera getTransformCamera() {
<$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0));
}
<@else@>
<$worldDir$> = vec3(gl_ModelViewMatrixInverse * vec4(<$eyeDir$>.xyz, 0.0));
<$worldDir$> = vec3(transformCamera_viewInverse * vec4(<$eyeDir$>.xyz, 0.0));
<@endif@>
<@endfunc@>

View file

@ -219,6 +219,7 @@ void DeferredLightingEffect::render() {
QSize framebufferSize = textureCache->getFrameBufferSize();
// binding the first framebuffer
auto freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFBO));
@ -489,11 +490,20 @@ void DeferredLightingEffect::render() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
// glDisable(GL_FRAMEBUFFER_SRGB);
// End of the Lighting pass
}
void DeferredLightingEffect::copyBack(RenderArgs* args) {
auto textureCache = DependencyManager::get<TextureCache>();
QSize framebufferSize = textureCache->getFrameBufferSize();
auto freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebuffer();
//freeFBO->release();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// glDisable(GL_FRAMEBUFFER_SRGB);
glDisable(GL_CULL_FACE);
@ -516,6 +526,18 @@ void DeferredLightingEffect::render() {
glPushMatrix();
glLoadIdentity();
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
const int VIEWPORT_X_INDEX = 0;
const int VIEWPORT_Y_INDEX = 1;
const int VIEWPORT_WIDTH_INDEX = 2;
const int VIEWPORT_HEIGHT_INDEX = 3;
float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width();
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width();
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height();
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)framebufferSize.height();
renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight);
glBindTexture(GL_TEXTURE_2D, 0);
@ -531,12 +553,11 @@ void DeferredLightingEffect::render() {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
// now render the objects we held back until after deferred lighting
foreach (PostLightingRenderable* renderable, _postLightingRenderables) {
renderable->renderPostLighting();
}
_postLightingRenderables.clear();
}
void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) {
auto globalLight = _allocatedLights[_globalLights.front()];
args->_batch->setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
}
void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations) {

View file

@ -23,7 +23,7 @@
#include "model/Stage.h"
class AbstractViewStateInterface;
class PostLightingRenderable;
class RenderArgs;
/// Handles deferred lighting for the bits that require it (voxels...)
class DeferredLightingEffect : public Dependency {
@ -66,11 +66,11 @@ public:
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f),
float intensity = 0.5f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI);
/// Adds an object to render after performing the deferred lighting for the current frame (e.g., a translucent object).
void addPostLightingRenderable(PostLightingRenderable* renderable) { _postLightingRenderables.append(renderable); }
void prepare();
void render();
void copyBack(RenderArgs* args);
void setupTransparent(RenderArgs* args, int lightBufferUnit);
// update global lighting
void setAmbientLightMode(int preset);
@ -153,7 +153,6 @@ private:
std::vector<int> _globalLights;
std::vector<int> _pointLights;
std::vector<int> _spotLights;
QVector<PostLightingRenderable*> _postLightingRenderables;
AbstractViewStateInterface* _viewState;
@ -162,10 +161,4 @@ private:
model::SkyboxPointer _skybox;
};
/// Simple interface for objects that require something to be rendered after deferred lighting.
class PostLightingRenderable {
public:
virtual void renderPostLighting() = 0;
};
#endif // hifi_DeferredLightingEffect_h

View file

@ -114,6 +114,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1));
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4));
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));
gpu::Shader::makeProgram(*program, slotBindings);
@ -139,7 +140,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
// Blend on transparent
state->setBlendFunction(key.isTranslucent(),
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, // For transparent only, this keep the highlight intensity
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
// Good to go add the brand new pipeline
@ -196,13 +197,17 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model:
#if (GPU_FEATURE_PROFILE == GPU_CORE)
locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer");
locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
#else
locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer");
locations.lightBufferUnit = program->getUniforms().findLocation("lightBuffer");
#endif
locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices");
locations.clusterIndices = program->getInputs().findLocation("clusterIndices");;
locations.clusterWeights = program->getInputs().findLocation("clusterWeights");;
}
@ -2067,7 +2072,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
gpu::Batch& batch = *(args->_batch);
auto mode = args->_renderMode;
// render the part bounding box
#ifdef DEBUG_BOUNDING_PARTS
{
@ -2089,6 +2093,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
}
auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
@ -2134,6 +2139,11 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
// sanity check
return; // FIXME!
}
// Transform stage
if (_transforms.empty()) {
_transforms.push_back(Transform());
}
if (isSkinned) {
GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false,
@ -2245,6 +2255,10 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ?
textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());
}
if (translucent && locations->lightBufferUnit >= 0) {
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit);
}
}
}

View file

@ -374,6 +374,7 @@ private:
int clusterMatrices;
int clusterIndices;
int clusterWeights;
int lightBufferUnit;
};
QHash<QPair<int,int>, AABox> _calculatedMeshPartBoxes; // world coordinate AABoxes for all sub mesh part boxes

View file

@ -10,7 +10,11 @@
//
#include "RenderDeferredTask.h"
#include "gpu/Batch.h"
#include "gpu/Context.h"
#include "DeferredLightingEffect.h"
#include "ViewFrustum.h"
#include "RenderArgs.h"
#include <PerfStat.h>
@ -22,9 +26,17 @@ template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPo
DependencyManager::get<DeferredLightingEffect>()->prepare();
}
template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("RenderDeferred");
DependencyManager::get<DeferredLightingEffect>()->render();
// renderContext->args->_context->syncCache();
}
template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("ResolveDeferred");
DependencyManager::get<DeferredLightingEffect>()->render();
DependencyManager::get<DeferredLightingEffect>()->copyBack(renderContext->args);
renderContext->args->_context->syncCache();
}
@ -34,10 +46,11 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
_jobs.push_back(Job(DrawBackground()));
_jobs.push_back(Job(DrawOpaque()));
_jobs.push_back(Job(DrawLight()));
_jobs.push_back(Job(DrawTransparent()));
_jobs.push_back(Job(ResetGLState()));
_jobs.push_back(Job(RenderDeferred()));
_jobs.push_back(Job(ResolveDeferred()));
_jobs.push_back(Job(DrawTransparentDeferred()));
_jobs.push_back(Job(ResetGLState()));
}
RenderDeferredTask::~RenderDeferredTask() {
@ -62,3 +75,76 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
job.run(sceneContext, renderContext);
}
};
template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawTransparentDeferred");
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& renderedItems = inItems;
renderContext->_numFeedTransparentItems = renderedItems.size();
ItemIDs culledItems;
if (renderContext->_cullTransparent) {
cullItems(sceneContext, renderContext, inItems, culledItems);
renderedItems = culledItems;
}
renderContext->_numDrawnTransparentItems = renderedItems.size();
ItemIDs sortedItems;
if (renderContext->_sortTransparent) {
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
renderedItems = sortedItems;
}
if (renderContext->_renderTransparent) {
RenderArgs* args = renderContext->args;
gpu::Batch batch;
args->_batch = &batch;
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
args->_renderMode = RenderArgs::NORMAL_RENDER_MODE;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
{
GLenum buffers[3];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
batch._glDrawBuffers(bufferCount, buffers);
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
}
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
args->_context->render((*args->_batch));
args->_batch = nullptr;
// reset blend function to standard...
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
}
}

View file

@ -14,8 +14,6 @@
#include "render/DrawTask.h"
#include "DeferredLightingEffect.h"
class PrepareDeferred {
public:
};
@ -23,6 +21,13 @@ namespace render {
template <> void jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class RenderDeferred {
public:
};
namespace render {
template <> void jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class ResolveDeferred {
public:
};
@ -30,6 +35,13 @@ namespace render {
template <> void jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class DrawTransparentDeferred {
public:
};
namespace render {
template <> void jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class RenderDeferredTask : public render::Task {
public:

View file

@ -19,6 +19,9 @@ const int MAX_TEXCOORDS = 2;
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
// interpolated eye position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
@ -35,7 +38,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, gl_Vertex, interpolatedPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$>
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);

View file

@ -23,6 +23,9 @@ uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
// the tangent vector
attribute vec3 tangent;
// interpolated eye position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
@ -45,7 +48,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, gl_Vertex, interpolatedPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$>
<$transformModelToEyeDir(cam, obj, tangent, interpolatedTangent.xyz)$>

View file

@ -11,8 +11,7 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DeferredBufferWrite.slh@>
<!/*<@include DeferredBufferWrite.slh@>
<@include model/Material.slh@>
@ -39,4 +38,95 @@ void main(void) {
// set the diffuse data
// gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].st);
}*/!>
<@include model/Material.slh@>
// Everything about global lighting
<@include DeferredLighting.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
// Everything about light
<@include model/Light.slh@>
// The view Matrix
//uniform mat4 invViewMat;
vec4 evalNormalColor(vec3 dir, float opacity) {
bool isX = (abs(dir.x) > 0.99);
bool isY = (abs(dir.y) > 0.99);
bool isZ = (abs(dir.z) > 0.99);
if (isX || isY || isZ) {
bool negX = (dir.x < -0.995);
bool negY = (dir.y < -0.995);
bool negZ = (dir.z < -0.995);
if (negX || negY || negZ) {
return vec4(float(isX), float(isY), float(isZ), 0.2);
} else {
return vec4(float(isX), float(isY), float(isZ), 1.0);
}
}
return vec4(0.5 * dir + vec3(0.5), opacity);
}
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) {
// Need the light now
Light light = getLight();
TransformCamera cam = getTransformCamera();
vec3 fragNormal;
<$transformEyeToWorldDir(cam, normal, fragNormal)$>
vec3 fragEyeVectorView = normalize(-position);
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
color += vec3(opacity * diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
//return vec4(color, opacity);
return vec4(color, opacity);
//return vec4(diffuse.rgb, opacity);
//return evalNormalColor(fragEyeDir, opacity);
}
// the diffuse texture
uniform sampler2D diffuseMap;
// the interpolated view position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
varying vec3 color;
void main(void) {
vec3 fragPosition = interpolatedPosition.xyz;
// Fetch diffuse map
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
Material mat = getMaterial();
vec3 fragNormal = normalize(interpolatedNormal.xyz);
float fragOpacity = getMaterialOpacity(mat) * diffuse.a;
vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * color;
vec3 fragSpecular = getMaterialSpecular(mat);
float fragGloss = getMaterialShininess(mat);
vec4 fragColor = evalGlobalColor(1.0,
fragPosition,
fragNormal,
fragDiffuse,
fragSpecular,
fragGloss,
fragOpacity);
gl_FragColor = fragColor;
}

View file

@ -25,6 +25,9 @@ uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
attribute vec4 clusterIndices;
attribute vec4 clusterWeights;
// interpolated eye position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
@ -49,7 +52,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, position, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, gl_Vertex, interpolatedPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$>
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);

View file

@ -28,6 +28,9 @@ attribute vec3 tangent;
attribute vec4 clusterIndices;
attribute vec4 clusterWeights;
// interpolated eye position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
@ -37,13 +40,13 @@ varying vec4 interpolatedTangent;
varying vec3 color;
void main(void) {
vec4 interpolatedPosition = vec4(0.0, 0.0, 0.0, 0.0);
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);
interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])];
float clusterWeight = clusterWeights[i];
interpolatedPosition += clusterMatrix * gl_Vertex * clusterWeight;
position += clusterMatrix * gl_Vertex * clusterWeight;
interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight;
interpolatedTangent += clusterMatrix * vec4(tangent, 0.0) * clusterWeight;
}
@ -60,7 +63,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, interpolatedPosition, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, position, interpolatedPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$>
<$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$>

View file

@ -9,6 +9,9 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <algorithm>
#include <assert.h>
#include "DrawTask.h"
#include <PerfStat.h>
@ -19,9 +22,6 @@
#include "ViewFrustum.h"
#include "RenderArgs.h"
#include <algorithm>
#include <assert.h>
using namespace render;
DrawSceneTask::DrawSceneTask() : Task() {
@ -56,7 +56,7 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon
Job::~Job() {
}
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemIDs& outItems) {
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
PerformanceTimer perfTimer("cullItems");
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
@ -68,22 +68,35 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
renderDetails->_considered += inItems.size();
// Culling / LOD
for (auto id : inItems) {
auto item = scene->getItem(id);
auto bound = item.getBound();
for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id);
AABox bound;
{
PerformanceTimer perfTimer("getBound");
bound = item.getBound();
}
if (bound.isNull()) {
outItems.push_back(id); // One more Item to render
outItems.push_back(ItemIDAndBounds(itemDetails.id)); // One more Item to render
continue;
}
// TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum...
bool outOfView = args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE;
bool outOfView;
{
PerformanceTimer perfTimer("boxInFrustum");
outOfView = args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE;
}
if (!outOfView) {
bool bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true;
bool bigEnoughToRender;
{
PerformanceTimer perfTimer("shouldRender");
bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true;
}
if (bigEnoughToRender) {
outItems.push_back(id); // One more Item to render
outItems.push_back(ItemIDAndBounds(itemDetails.id, bound)); // One more Item to render
} else {
renderDetails->_tooSmall++;
}
@ -116,28 +129,29 @@ struct BackToFrontSort {
}
};
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDs& inItems, ItemIDs& outItems) {
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
PerformanceTimer perfTimer("depthSortItems");
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args;
// Allocate and simply copy
outItems.reserve(inItems.size());
// Make a local dataset of the center distance and closest point distance
std::vector<ItemBound> itemBounds;
itemBounds.reserve(outItems.size());
for (auto id : inItems) {
auto item = scene->getItem(id);
auto bound = item.getBound();
for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id);
auto bound = itemDetails.bounds; // item.getBound();
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter());
itemBounds.emplace_back(ItemBound(distance, distance, distance, id));
itemBounds.emplace_back(ItemBound(distance, distance, distance, itemDetails.id));
}
// sort against Z
@ -155,20 +169,20 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
}
}
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, int maxDrawnItems) {
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems) {
PerformanceTimer perfTimer("renderItems");
auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args;
// render
if ((maxDrawnItems < 0) || (maxDrawnItems > inItems.size())) {
for (auto id : inItems) {
auto item = scene->getItem(id);
for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id);
item.render(args);
}
} else {
int numItems = 0;
for (auto id : inItems) {
auto item = scene->getItem(id);
for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id);
item.render(args);
numItems++;
if (numItems >= maxDrawnItems) {
@ -230,16 +244,16 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape());
auto& renderDetails = renderContext->args->_details;
ItemIDs inItems;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
inItems.push_back(ItemIDAndBounds(id));
}
ItemIDs& renderedItems = inItems;
ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedOpaqueItems = renderedItems.size();
ItemIDs culledItems;
ItemIDsBounds culledItems;
if (renderContext->_cullOpaque) {
renderDetails.pointTo(RenderDetails::OPAQUE_ITEM);
cullItems(sceneContext, renderContext, renderedItems, culledItems);
@ -250,7 +264,7 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer
renderContext->_numDrawnOpaqueItems = renderedItems.size();
ItemIDs sortedItems;
ItemIDsBounds sortedItems;
if (renderContext->_sortOpaque) {
depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items!
renderedItems = sortedItems;
@ -296,16 +310,16 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape());
auto& renderDetails = renderContext->args->_details;
ItemIDs inItems;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs& renderedItems = inItems;
ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedTransparentItems = renderedItems.size();
ItemIDs culledItems;
ItemIDsBounds culledItems;
if (renderContext->_cullTransparent) {
renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM);
cullItems(sceneContext, renderContext, inItems, culledItems);
@ -315,7 +329,7 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo
renderContext->_numDrawnTransparentItems = renderedItems.size();
ItemIDs sortedItems;
ItemIDsBounds sortedItems;
if (renderContext->_sortTransparent) {
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
renderedItems = sortedItems;
@ -376,13 +390,13 @@ template <> void render::jobRun(const DrawLight& job, const SceneContextPointer&
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light());
ItemIDs inItems;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDs culledItems;
ItemIDsBounds culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems);
RenderArgs* args = renderContext->args;
@ -403,7 +417,7 @@ template <> void render::jobRun(const DrawBackground& job, const SceneContextPoi
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background());
ItemIDs inItems;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);

View file

@ -57,9 +57,9 @@ protected:
typedef std::vector<Job> Jobs;
void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemIDs& outITems);
void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDs& inItems, ItemIDs& outITems);
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, int maxDrawnItems = -1);
void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1);
class DrawOpaque {

View file

@ -333,6 +333,17 @@ typedef Item::ID ItemID;
typedef std::vector<ItemID> ItemIDs;
typedef std::set<ItemID> ItemIDSet;
class ItemIDAndBounds {
public:
ItemIDAndBounds(ItemID id) : id(id) { }
ItemIDAndBounds(ItemID id, const AABox& bounds) : id(id), bounds(bounds) { }
ItemID id;
AABox bounds;
};
typedef std::vector< ItemIDAndBounds > ItemIDsBounds;
// A map of ItemIDSets allowing to create bucket lists of items which are filtering correctly
class ItemBucketMap : public std::map<ItemFilter, ItemIDSet, ItemFilter::Less> {
public: