mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 15:38:00 +02:00
Merge pull request #4601 from samcake/temp1
Introducing gpu::State and using it in the Model rendering path and more...
This commit is contained in:
commit
a47170b02c
37 changed files with 1978 additions and 764 deletions
|
@ -2750,7 +2750,7 @@ void Application::updateShadowMap() {
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("avatarManager");
|
PerformanceTimer perfTimer("avatarManager");
|
||||||
DependencyManager::get<AvatarManager>()->renderAvatars(Avatar::SHADOW_RENDER_MODE);
|
DependencyManager::get<AvatarManager>()->renderAvatars(RenderArgs::SHADOW_RENDER_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -2997,6 +2997,8 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
||||||
"Application::displaySide() ... entities...");
|
"Application::displaySide() ... entities...");
|
||||||
if (renderCollisionHulls) {
|
if (renderCollisionHulls) {
|
||||||
_entities.render(RenderArgs::DEBUG_RENDER_MODE, renderSide);
|
_entities.render(RenderArgs::DEBUG_RENDER_MODE, renderSide);
|
||||||
|
} else if (theCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||||
|
_entities.render(RenderArgs::MIRROR_RENDER_MODE, renderSide);
|
||||||
} else {
|
} else {
|
||||||
_entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderSide);
|
_entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderSide);
|
||||||
}
|
}
|
||||||
|
@ -3021,8 +3023,8 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("avatars");
|
PerformanceTimer perfTimer("avatars");
|
||||||
DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,
|
DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE,
|
||||||
false, selfAvatarOnly);
|
false, selfAvatarOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -3038,7 +3040,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("avatarsPostLighting");
|
PerformanceTimer perfTimer("avatarsPostLighting");
|
||||||
DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,
|
DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE,
|
||||||
true, selfAvatarOnly);
|
true, selfAvatarOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -261,9 +261,11 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data)
|
||||||
(1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f);
|
(1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f);
|
||||||
program->setUniformValue(locations[G_LOCATION], -0.990f);
|
program->setUniformValue(locations[G_LOCATION], -0.990f);
|
||||||
program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f);
|
program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f);
|
||||||
|
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
DependencyManager::get<GeometryCache>()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere
|
DependencyManager::get<GeometryCache>()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
|
|
||||||
|
|
|
@ -268,7 +268,7 @@ static TextRenderer* textRenderer(TextRendererType type) {
|
||||||
return displayNameRenderer;
|
return displayNameRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool postLighting) {
|
void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode, bool postLighting) {
|
||||||
if (_referential) {
|
if (_referential) {
|
||||||
_referential->update();
|
_referential->update();
|
||||||
}
|
}
|
||||||
|
@ -338,13 +338,13 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool
|
||||||
|
|
||||||
// simple frustum check
|
// simple frustum check
|
||||||
float boundingRadius = getBillboardSize();
|
float boundingRadius = getBillboardSize();
|
||||||
|
|
||||||
ViewFrustum* frustum = nullptr;
|
ViewFrustum* frustum = nullptr;
|
||||||
if (renderMode == Avatar::SHADOW_RENDER_MODE) {
|
if (renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
frustum = Application::getInstance()->getShadowViewFrustum();
|
frustum = Application::getInstance()->getShadowViewFrustum();
|
||||||
} else {
|
} else {
|
||||||
frustum = Application::getInstance()->getDisplayViewFrustum();
|
frustum = Application::getInstance()->getDisplayViewFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -365,14 +365,14 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool
|
||||||
GLOW_FROM_AVERAGE_LOUDNESS = 0.0f;
|
GLOW_FROM_AVERAGE_LOUDNESS = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE
|
float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == RenderArgs::NORMAL_RENDER_MODE
|
||||||
? 1.0f
|
? 1.0f
|
||||||
: GLOW_FROM_AVERAGE_LOUDNESS;
|
: GLOW_FROM_AVERAGE_LOUDNESS;
|
||||||
|
|
||||||
// render body
|
// render body
|
||||||
renderBody(frustum, renderMode, postLighting, glowLevel);
|
renderBody(frustum, renderMode, postLighting, glowLevel);
|
||||||
|
|
||||||
if (!postLighting && renderMode != SHADOW_RENDER_MODE) {
|
if (!postLighting && renderMode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
// add local lights
|
// add local lights
|
||||||
const float BASE_LIGHT_DISTANCE = 2.0f;
|
const float BASE_LIGHT_DISTANCE = 2.0f;
|
||||||
const float LIGHT_EXPONENT = 1.0f;
|
const float LIGHT_EXPONENT = 1.0f;
|
||||||
|
@ -436,7 +436,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool
|
||||||
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
|
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
|
||||||
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
|
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
|
||||||
|
|
||||||
if (renderMode == NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) &&
|
if (renderMode == RenderArgs::NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) &&
|
||||||
(angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
|
(angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_position.x, _position.y, _position.z);
|
glTranslatef(_position.x, _position.y, _position.z);
|
||||||
|
@ -455,8 +455,8 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const float DISPLAYNAME_DISTANCE = 20.0f;
|
const float DISPLAYNAME_DISTANCE = 20.0f;
|
||||||
setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE);
|
setShowDisplayName(renderMode == RenderArgs::NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE);
|
||||||
if (!postLighting || renderMode != NORMAL_RENDER_MODE || (isMyAvatar() &&
|
if (!postLighting || renderMode != RenderArgs::NORMAL_RENDER_MODE || (isMyAvatar() &&
|
||||||
Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) {
|
Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -479,14 +479,13 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||||
return glm::angleAxis(angle * proportion, axis);
|
return glm::angleAxis(angle * proportion, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel) {
|
void Avatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel) {
|
||||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
Model::RenderMode modelRenderMode = renderMode;
|
||||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
|
||||||
{
|
{
|
||||||
Glower glower(glowLevel);
|
Glower glower(glowLevel);
|
||||||
|
|
||||||
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||||
if (postLighting || renderMode == SHADOW_RENDER_MODE) {
|
if (postLighting || renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
// render the billboard until both models are loaded
|
// render the billboard until both models are loaded
|
||||||
renderBillboard();
|
renderBillboard();
|
||||||
}
|
}
|
||||||
|
@ -505,7 +504,7 @@ void Avatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool
|
||||||
getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting);
|
getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
|
bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,11 +528,11 @@ void Avatar::simulateAttachments(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::renderAttachments(RenderMode renderMode, RenderArgs* args) {
|
void Avatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args) {
|
||||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
// RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
|
||||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
// RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE;
|
||||||
foreach (Model* model, _attachmentModels) {
|
foreach (Model* model, _attachmentModels) {
|
||||||
model->render(1.0f, modelRenderMode, args);
|
model->render(1.0f, renderMode, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,10 +67,8 @@ public:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
|
|
||||||
enum RenderMode { NORMAL_RENDER_MODE, SHADOW_RENDER_MODE, MIRROR_RENDER_MODE };
|
virtual void render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode = RenderArgs::NORMAL_RENDER_MODE,
|
||||||
|
|
||||||
virtual void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE,
|
|
||||||
bool postLighting = false);
|
bool postLighting = false);
|
||||||
|
|
||||||
//setters
|
//setters
|
||||||
|
@ -208,11 +206,11 @@ protected:
|
||||||
|
|
||||||
float calculateDisplayNameScaleFactor(const glm::vec3& textPosition, bool inHMD);
|
float calculateDisplayNameScaleFactor(const glm::vec3& textPosition, bool inHMD);
|
||||||
void renderDisplayName();
|
void renderDisplayName();
|
||||||
virtual void renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
virtual void renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
||||||
virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const;
|
virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const;
|
||||||
|
|
||||||
void simulateAttachments(float deltaTime);
|
void simulateAttachments(float deltaTime);
|
||||||
virtual void renderAttachments(RenderMode renderMode, RenderArgs* args);
|
virtual void renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args);
|
||||||
|
|
||||||
virtual void updateJointMappings();
|
virtual void updateJointMappings();
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
simulateAvatarFades(deltaTime);
|
simulateAvatarFades(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::renderAvatars(Avatar::RenderMode renderMode, bool postLighting, bool selfAvatarOnly) {
|
void AvatarManager::renderAvatars(RenderArgs::RenderMode renderMode, bool postLighting, bool selfAvatarOnly) {
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::renderAvatars()");
|
"Application::renderAvatars()");
|
||||||
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderLookAtVectors);
|
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderLookAtVectors);
|
||||||
|
@ -159,9 +159,9 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode) {
|
void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) {
|
||||||
// render avatar fades
|
// render avatar fades
|
||||||
Glower glower(renderMode == Avatar::NORMAL_RENDER_MODE ? 1.0f : 0.0f);
|
Glower glower(renderMode == RenderArgs::NORMAL_RENDER_MODE ? 1.0f : 0.0f);
|
||||||
|
|
||||||
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
|
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
|
||||||
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
|
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
|
|
||||||
void updateMyAvatar(float deltaTime);
|
void updateMyAvatar(float deltaTime);
|
||||||
void updateOtherAvatars(float deltaTime);
|
void updateOtherAvatars(float deltaTime);
|
||||||
void renderAvatars(Avatar::RenderMode renderMode, bool postLighting = false, bool selfAvatarOnly = false);
|
void renderAvatars(RenderArgs::RenderMode renderMode, bool postLighting = false, bool selfAvatarOnly = false);
|
||||||
|
|
||||||
void clearOtherAvatars();
|
void clearOtherAvatars();
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ private:
|
||||||
AvatarManager(const AvatarManager& other);
|
AvatarManager(const AvatarManager& other);
|
||||||
|
|
||||||
void simulateAvatarFades(float deltaTime);
|
void simulateAvatarFades(float deltaTime);
|
||||||
void renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode);
|
void renderAvatarFades(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode);
|
||||||
|
|
||||||
AvatarSharedPointer newSharedAvatar();
|
AvatarSharedPointer newSharedAvatar();
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ void Hand::resolvePenetrations() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::render(bool isMine, Model::RenderMode renderMode) {
|
void Hand::render(bool isMine, Model::RenderMode renderMode) {
|
||||||
if (renderMode != Model::SHADOW_RENDER_MODE &&
|
if (renderMode != RenderArgs::SHADOW_RENDER_MODE &&
|
||||||
Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes)) {
|
Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes)) {
|
||||||
// draw a green sphere at hand joint location, which is actually near the wrist)
|
// draw a green sphere at hand joint location, which is actually near the wrist)
|
||||||
for (size_t i = 0; i < getNumPalms(); i++) {
|
for (size_t i = 0; i < getNumPalms(); i++) {
|
||||||
|
@ -119,7 +119,7 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderMode != Model::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHands)) {
|
if (renderMode != RenderArgs::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHands)) {
|
||||||
renderHandTargets(isMine);
|
renderHandTargets(isMine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void simulate(float deltaTime, bool isMine);
|
void simulate(float deltaTime, bool isMine);
|
||||||
void render(bool isMine, Model::RenderMode renderMode = Model::DEFAULT_RENDER_MODE);
|
void render(bool isMine, Model::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE);
|
||||||
|
|
||||||
void collideAgainstAvatar(Avatar* avatar, bool isMyHand);
|
void collideAgainstAvatar(Avatar* avatar, bool isMyHand);
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,7 @@ void MyAvatar::renderDebugBodyPoints() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool postLighting) {
|
void MyAvatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode, bool postLighting) {
|
||||||
// don't render if we've been asked to disable local rendering
|
// don't render if we've been asked to disable local rendering
|
||||||
if (!_shouldRender) {
|
if (!_shouldRender) {
|
||||||
return; // exit early
|
return; // exit early
|
||||||
|
@ -998,7 +998,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g
|
||||||
Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved);
|
Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel) {
|
void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel) {
|
||||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||||
return; // wait until both models are loaded
|
return; // wait until both models are loaded
|
||||||
}
|
}
|
||||||
|
@ -1007,7 +1007,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo
|
||||||
const glm::vec3 cameraPos = camera->getPosition();
|
const glm::vec3 cameraPos = camera->getPosition();
|
||||||
|
|
||||||
// Only tweak the frustum near far if it's not shadow
|
// Only tweak the frustum near far if it's not shadow
|
||||||
if (renderMode != SHADOW_RENDER_MODE) {
|
if (renderMode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
// Set near clip distance according to skeleton model dimensions if first person and there is no separate head model.
|
// Set near clip distance according to skeleton model dimensions if first person and there is no separate head model.
|
||||||
if (shouldRenderHead(cameraPos, renderMode) || !getHead()->getFaceModel().getURL().isEmpty()) {
|
if (shouldRenderHead(cameraPos, renderMode) || !getHead()->getFaceModel().getURL().isEmpty()) {
|
||||||
renderFrustum->setNearClip(DEFAULT_NEAR_CLIP);
|
renderFrustum->setNearClip(DEFAULT_NEAR_CLIP);
|
||||||
|
@ -1028,8 +1028,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the body's voxels and head
|
// Render the body's voxels and head
|
||||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
RenderArgs::RenderMode modelRenderMode = renderMode;
|
||||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
|
||||||
if (!postLighting) {
|
if (!postLighting) {
|
||||||
RenderArgs args;
|
RenderArgs args;
|
||||||
args._viewFrustum = renderFrustum;
|
args._viewFrustum = renderFrustum;
|
||||||
|
@ -1048,9 +1047,9 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo
|
||||||
|
|
||||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||||
|
|
||||||
bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
|
bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const {
|
||||||
const Head* head = getHead();
|
const Head* head = getHead();
|
||||||
return (renderMode != NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
return (renderMode != RenderArgs::NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||||
(glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
(glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1396,19 +1395,19 @@ void MyAvatar::updateMotionBehavior() {
|
||||||
_feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations);
|
_feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::renderAttachments(RenderMode renderMode, RenderArgs* args) {
|
void MyAvatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args) {
|
||||||
if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || renderMode == MIRROR_RENDER_MODE) {
|
if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||||
Avatar::renderAttachments(renderMode, args);
|
Avatar::renderAttachments(renderMode, args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const FBXGeometry& geometry = _skeletonModel.getGeometry()->getFBXGeometry();
|
const FBXGeometry& geometry = _skeletonModel.getGeometry()->getFBXGeometry();
|
||||||
QString headJointName = (geometry.headJointIndex == -1) ? QString() : geometry.joints.at(geometry.headJointIndex).name;
|
QString headJointName = (geometry.headJointIndex == -1) ? QString() : geometry.joints.at(geometry.headJointIndex).name;
|
||||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
// RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
|
||||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
// RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE;
|
||||||
for (int i = 0; i < _attachmentData.size(); i++) {
|
for (int i = 0; i < _attachmentData.size(); i++) {
|
||||||
const QString& jointName = _attachmentData.at(i).jointName;
|
const QString& jointName = _attachmentData.at(i).jointName;
|
||||||
if (jointName != headJointName && jointName != "Head") {
|
if (jointName != headJointName && jointName != "Head") {
|
||||||
_attachmentModels.at(i)->render(1.0f, modelRenderMode, args);
|
_attachmentModels.at(i)->render(1.0f, renderMode, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,9 @@ public:
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
void updateFromTrackers(float deltaTime);
|
void updateFromTrackers(float deltaTime);
|
||||||
|
|
||||||
void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE, bool postLighting = false);
|
void render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode = RenderArgs::NORMAL_RENDER_MODE, bool postLighting = false);
|
||||||
void renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
void renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
||||||
bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const;
|
bool shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const;
|
||||||
void renderDebugBodyPoints();
|
void renderDebugBodyPoints();
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
|
@ -182,7 +182,7 @@ signals:
|
||||||
void transformChanged();
|
void transformChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void renderAttachments(RenderMode renderMode, RenderArgs* args);
|
virtual void renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float _turningKeyPressTime;
|
float _turningKeyPressTime;
|
||||||
|
|
|
@ -68,7 +68,7 @@ void ModelOverlay::render(RenderArgs* args) {
|
||||||
if (glowLevel > 0.0f) {
|
if (glowLevel > 0.0f) {
|
||||||
glower = new Glower(glowLevel);
|
glower = new Glower(glowLevel);
|
||||||
}
|
}
|
||||||
_model.render(getAlpha(), Model::DEFAULT_RENDER_MODE, args);
|
_model.render(getAlpha(), RenderArgs::DEFAULT_RENDER_MODE, args);
|
||||||
if (glower) {
|
if (glower) {
|
||||||
delete glower;
|
delete glower;
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,12 +395,12 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R
|
||||||
_tree->lockForRead();
|
_tree->lockForRead();
|
||||||
_tree->recurseTreeWithOperation(renderOperation, &args);
|
_tree->recurseTreeWithOperation(renderOperation, &args);
|
||||||
|
|
||||||
Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE
|
// Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE
|
||||||
? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
// ? RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE;
|
||||||
|
|
||||||
// we must call endScene while we still have the tree locked so that no one deletes a model
|
// we must call endScene while we still have the tree locked so that no one deletes a model
|
||||||
// on us while rendering the scene
|
// on us while rendering the scene
|
||||||
Model::endScene(modelRenderMode, &args);
|
Model::endScene(renderMode, &args);
|
||||||
_tree->unlock();
|
_tree->unlock();
|
||||||
|
|
||||||
// stats...
|
// stats...
|
||||||
|
|
|
@ -20,7 +20,6 @@ Batch::Batch() :
|
||||||
_commands(),
|
_commands(),
|
||||||
_commandOffsets(),
|
_commandOffsets(),
|
||||||
_params(),
|
_params(),
|
||||||
_resources(),
|
|
||||||
_data(),
|
_data(),
|
||||||
_buffers(),
|
_buffers(),
|
||||||
_textures(),
|
_textures(),
|
||||||
|
@ -37,7 +36,6 @@ void Batch::clear() {
|
||||||
_commands.clear();
|
_commands.clear();
|
||||||
_commandOffsets.clear();
|
_commandOffsets.clear();
|
||||||
_params.clear();
|
_params.clear();
|
||||||
_resources.clear();
|
|
||||||
_data.clear();
|
_data.clear();
|
||||||
_buffers.clear();
|
_buffers.clear();
|
||||||
_textures.clear();
|
_textures.clear();
|
||||||
|
@ -46,20 +44,6 @@ void Batch::clear() {
|
||||||
_pipelines.clear();
|
_pipelines.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Batch::cacheResource(Resource* res) {
|
|
||||||
uint32 offset = _resources.size();
|
|
||||||
_resources.push_back(ResourceCache(res));
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 Batch::cacheResource(const void* pointer) {
|
|
||||||
uint32 offset = _resources.size();
|
|
||||||
_resources.push_back(ResourceCache(pointer));
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 Batch::cacheData(uint32 size, const void* data) {
|
uint32 Batch::cacheData(uint32 size, const void* data) {
|
||||||
uint32 offset = _data.size();
|
uint32 offset = _data.size();
|
||||||
uint32 nbBytes = size;
|
uint32 nbBytes = size;
|
||||||
|
@ -167,6 +151,16 @@ void Batch::setPipeline(const PipelinePointer& pipeline) {
|
||||||
_params.push_back(_pipelines.cache(pipeline));
|
_params.push_back(_pipelines.cache(pipeline));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::setStateBlendFactor(const Vec4& factor) {
|
||||||
|
ADD_COMMAND(setStateBlendFactor);
|
||||||
|
|
||||||
|
_params.push_back(factor.x);
|
||||||
|
_params.push_back(factor.y);
|
||||||
|
_params.push_back(factor.z);
|
||||||
|
_params.push_back(factor.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) {
|
void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) {
|
||||||
ADD_COMMAND(setUniformBuffer);
|
ADD_COMMAND(setUniformBuffer);
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,8 @@ public:
|
||||||
// Pipeline Stage
|
// Pipeline Stage
|
||||||
void setPipeline(const PipelinePointer& pipeline);
|
void setPipeline(const PipelinePointer& pipeline);
|
||||||
|
|
||||||
|
void setStateBlendFactor(const Vec4& factor);
|
||||||
|
|
||||||
void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size);
|
void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size);
|
||||||
void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
|
void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
|
||||||
|
|
||||||
|
@ -128,7 +130,7 @@ public:
|
||||||
|
|
||||||
void _glDepthFunc(GLenum func);
|
void _glDepthFunc(GLenum func);
|
||||||
void _glDepthMask(GLboolean flag);
|
void _glDepthMask(GLboolean flag);
|
||||||
void _glDepthRange(GLclampd zNear, GLclampd zFar);
|
void _glDepthRange(GLfloat zNear, GLfloat zFar);
|
||||||
|
|
||||||
void _glBindBuffer(GLenum target, GLuint buffer);
|
void _glBindBuffer(GLenum target, GLuint buffer);
|
||||||
|
|
||||||
|
@ -143,15 +145,6 @@ public:
|
||||||
void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value);
|
void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value);
|
||||||
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
|
||||||
void _glDrawArrays(GLenum mode, GLint first, GLsizei count);
|
|
||||||
void _glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
|
|
||||||
|
|
||||||
void _glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
|
||||||
void _glNormalPointer(GLenum type, GLsizei stride, const void *pointer);
|
|
||||||
void _glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
|
||||||
void _glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
|
||||||
|
|
||||||
void _glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
|
||||||
void _glEnableVertexAttribArray(GLint location);
|
void _glEnableVertexAttribArray(GLint location);
|
||||||
void _glDisableVertexAttribArray(GLint location);
|
void _glDisableVertexAttribArray(GLint location);
|
||||||
|
|
||||||
|
@ -172,6 +165,8 @@ public:
|
||||||
COMMAND_setProjectionTransform,
|
COMMAND_setProjectionTransform,
|
||||||
|
|
||||||
COMMAND_setPipeline,
|
COMMAND_setPipeline,
|
||||||
|
COMMAND_setStateBlendFactor,
|
||||||
|
|
||||||
COMMAND_setUniformBuffer,
|
COMMAND_setUniformBuffer,
|
||||||
COMMAND_setUniformTexture,
|
COMMAND_setUniformTexture,
|
||||||
|
|
||||||
|
@ -204,15 +199,6 @@ public:
|
||||||
COMMAND_glUniform4fv,
|
COMMAND_glUniform4fv,
|
||||||
COMMAND_glUniformMatrix4fv,
|
COMMAND_glUniformMatrix4fv,
|
||||||
|
|
||||||
COMMAND_glDrawArrays,
|
|
||||||
COMMAND_glDrawRangeElements,
|
|
||||||
|
|
||||||
COMMAND_glColorPointer,
|
|
||||||
COMMAND_glNormalPointer,
|
|
||||||
COMMAND_glTexCoordPointer,
|
|
||||||
COMMAND_glVertexPointer,
|
|
||||||
|
|
||||||
COMMAND_glVertexAttribPointer,
|
|
||||||
COMMAND_glEnableVertexAttribArray,
|
COMMAND_glEnableVertexAttribArray,
|
||||||
COMMAND_glDisableVertexAttribArray,
|
COMMAND_glDisableVertexAttribArray,
|
||||||
|
|
||||||
|
@ -233,28 +219,18 @@ public:
|
||||||
uint32 _uint;
|
uint32 _uint;
|
||||||
float _float;
|
float _float;
|
||||||
char _chars[4];
|
char _chars[4];
|
||||||
double _double;
|
|
||||||
};
|
};
|
||||||
Param(int32 val) : _int(val) {}
|
Param(int32 val) : _int(val) {}
|
||||||
Param(uint32 val) : _uint(val) {}
|
Param(uint32 val) : _uint(val) {}
|
||||||
Param(float val) : _float(val) {}
|
Param(float val) : _float(val) {}
|
||||||
Param(double val) : _double(val) {}
|
|
||||||
};
|
};
|
||||||
typedef std::vector<Param> Params;
|
typedef std::vector<Param> Params;
|
||||||
|
|
||||||
const Params& getParams() const { return _params; }
|
const Params& getParams() const { return _params; }
|
||||||
|
|
||||||
class ResourceCache {
|
// The template cache mechanism for the gpu::Object passed to the gpu::Batch
|
||||||
public:
|
// this allow us to have one cache container for each different types and eventually
|
||||||
union {
|
// be smarter how we manage them
|
||||||
Resource* _resource;
|
|
||||||
const void* _pointer;
|
|
||||||
};
|
|
||||||
ResourceCache(Resource* res) : _resource(res) {}
|
|
||||||
ResourceCache(const void* pointer) : _pointer(pointer) {}
|
|
||||||
};
|
|
||||||
typedef std::vector<ResourceCache> Resources;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Cache {
|
class Cache {
|
||||||
public:
|
public:
|
||||||
|
@ -291,26 +267,10 @@ public:
|
||||||
typedef Cache<Transform>::Vector TransformCaches;
|
typedef Cache<Transform>::Vector TransformCaches;
|
||||||
typedef Cache<PipelinePointer>::Vector PipelineCaches;
|
typedef Cache<PipelinePointer>::Vector PipelineCaches;
|
||||||
|
|
||||||
|
// Cache Data in a byte array if too big to fit in Param
|
||||||
|
// FOr example Mat4s are going there
|
||||||
typedef unsigned char Byte;
|
typedef unsigned char Byte;
|
||||||
typedef std::vector<Byte> Bytes;
|
typedef std::vector<Byte> Bytes;
|
||||||
|
|
||||||
uint32 cacheResource(Resource* res);
|
|
||||||
uint32 cacheResource(const void* pointer);
|
|
||||||
ResourceCache* editResource(uint32 offset) {
|
|
||||||
if (offset >= _resources.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (_resources.data() + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T* editResourcePointer(uint32 offset) {
|
|
||||||
if (offset >= _resources.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return reinterpret_cast<T*>((_resources.data() + offset)->_pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 cacheData(uint32 size, const void* data);
|
uint32 cacheData(uint32 size, const void* data);
|
||||||
Byte* editData(uint32 offset) {
|
Byte* editData(uint32 offset) {
|
||||||
if (offset >= _data.size()) {
|
if (offset >= _data.size()) {
|
||||||
|
@ -322,7 +282,6 @@ public:
|
||||||
Commands _commands;
|
Commands _commands;
|
||||||
CommandOffsets _commandOffsets;
|
CommandOffsets _commandOffsets;
|
||||||
Params _params;
|
Params _params;
|
||||||
Resources _resources;
|
|
||||||
Bytes _data;
|
Bytes _data;
|
||||||
|
|
||||||
BufferCaches _buffers;
|
BufferCaches _buffers;
|
||||||
|
|
|
@ -82,6 +82,15 @@ public:
|
||||||
return reinterpret_cast<T*>(pipeline.getGPUObject());
|
return reinterpret_cast<T*>(pipeline.getGPUObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
static void setGPUObject(const State& state, T* so) {
|
||||||
|
state.setGPUObject(so);
|
||||||
|
}
|
||||||
|
template< typename T >
|
||||||
|
static T* getGPUObject(const State& state) {
|
||||||
|
return reinterpret_cast<T*>(state.getGPUObject());
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
class GPUObject;
|
||||||
|
|
||||||
|
typedef int Stamp;
|
||||||
|
|
||||||
typedef unsigned int uint32;
|
typedef unsigned int uint32;
|
||||||
typedef int int32;
|
typedef int int32;
|
||||||
typedef unsigned short uint16;
|
typedef unsigned short uint16;
|
||||||
|
|
|
@ -27,6 +27,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
(&::gpu::GLBackend::do_setProjectionTransform),
|
(&::gpu::GLBackend::do_setProjectionTransform),
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_setPipeline),
|
(&::gpu::GLBackend::do_setPipeline),
|
||||||
|
(&::gpu::GLBackend::do_setStateBlendFactor),
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_setUniformBuffer),
|
(&::gpu::GLBackend::do_setUniformBuffer),
|
||||||
(&::gpu::GLBackend::do_setUniformTexture),
|
(&::gpu::GLBackend::do_setUniformTexture),
|
||||||
|
|
||||||
|
@ -56,15 +58,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
(&::gpu::GLBackend::do_glUniform4fv),
|
(&::gpu::GLBackend::do_glUniform4fv),
|
||||||
(&::gpu::GLBackend::do_glUniformMatrix4fv),
|
(&::gpu::GLBackend::do_glUniformMatrix4fv),
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_glDrawArrays),
|
|
||||||
(&::gpu::GLBackend::do_glDrawRangeElements),
|
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_glColorPointer),
|
|
||||||
(&::gpu::GLBackend::do_glNormalPointer),
|
|
||||||
(&::gpu::GLBackend::do_glTexCoordPointer),
|
|
||||||
(&::gpu::GLBackend::do_glVertexPointer),
|
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_glVertexAttribPointer),
|
|
||||||
(&::gpu::GLBackend::do_glEnableVertexAttribArray),
|
(&::gpu::GLBackend::do_glEnableVertexAttribArray),
|
||||||
(&::gpu::GLBackend::do_glDisableVertexAttribArray),
|
(&::gpu::GLBackend::do_glDisableVertexAttribArray),
|
||||||
|
|
||||||
|
@ -281,7 +274,7 @@ void GLBackend::do_glDepthMask(Batch& batch, uint32 paramOffset) {
|
||||||
CHECK_GL_ERROR();
|
CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) {
|
void Batch::_glDepthRange(GLfloat zNear, GLfloat zFar) {
|
||||||
ADD_COMMAND_GL(glDepthRange);
|
ADD_COMMAND_GL(glDepthRange);
|
||||||
|
|
||||||
_params.push_back(zFar);
|
_params.push_back(zFar);
|
||||||
|
@ -291,8 +284,8 @@ void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) {
|
||||||
}
|
}
|
||||||
void GLBackend::do_glDepthRange(Batch& batch, uint32 paramOffset) {
|
void GLBackend::do_glDepthRange(Batch& batch, uint32 paramOffset) {
|
||||||
glDepthRange(
|
glDepthRange(
|
||||||
batch._params[paramOffset + 1]._double,
|
batch._params[paramOffset + 1]._float,
|
||||||
batch._params[paramOffset + 0]._double);
|
batch._params[paramOffset + 0]._float);
|
||||||
CHECK_GL_ERROR();
|
CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,14 +364,19 @@ void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::_glUniform1f(GLint location, GLfloat v0) {
|
void Batch::_glUniform1f(GLint location, GLfloat v0) {
|
||||||
|
if (location < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ADD_COMMAND_GL(glUniform1f);
|
ADD_COMMAND_GL(glUniform1f);
|
||||||
|
|
||||||
_params.push_back(v0);
|
_params.push_back(v0);
|
||||||
_params.push_back(location);
|
_params.push_back(location);
|
||||||
|
|
||||||
DO_IT_NOW(_glUniform1f, 1);
|
DO_IT_NOW(_glUniform1f, 1);
|
||||||
}
|
}
|
||||||
void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) {
|
void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) {
|
||||||
|
if (_pipeline._program == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
glUniform1f(
|
glUniform1f(
|
||||||
batch._params[paramOffset + 1]._int,
|
batch._params[paramOffset + 1]._int,
|
||||||
batch._params[paramOffset + 0]._float);
|
batch._params[paramOffset + 0]._float);
|
||||||
|
@ -441,144 +439,6 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) {
|
||||||
CHECK_GL_ERROR();
|
CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
|
||||||
ADD_COMMAND_GL(glDrawArrays);
|
|
||||||
|
|
||||||
_params.push_back(count);
|
|
||||||
_params.push_back(first);
|
|
||||||
_params.push_back(mode);
|
|
||||||
|
|
||||||
DO_IT_NOW(_glDrawArrays, 3);
|
|
||||||
}
|
|
||||||
void GLBackend::do_glDrawArrays(Batch& batch, uint32 paramOffset) {
|
|
||||||
glDrawArrays(
|
|
||||||
batch._params[paramOffset + 2]._uint,
|
|
||||||
batch._params[paramOffset + 1]._int,
|
|
||||||
batch._params[paramOffset + 0]._int);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) {
|
|
||||||
ADD_COMMAND_GL(glDrawRangeElements);
|
|
||||||
|
|
||||||
_params.push_back(cacheResource(indices));
|
|
||||||
_params.push_back(type);
|
|
||||||
_params.push_back(count);
|
|
||||||
_params.push_back(end);
|
|
||||||
_params.push_back(start);
|
|
||||||
_params.push_back(mode);
|
|
||||||
|
|
||||||
DO_IT_NOW(_glDrawRangeElements, 6);
|
|
||||||
}
|
|
||||||
void GLBackend::do_glDrawRangeElements(Batch& batch, uint32 paramOffset) {
|
|
||||||
glDrawRangeElements(
|
|
||||||
batch._params[paramOffset + 5]._uint,
|
|
||||||
batch._params[paramOffset + 4]._uint,
|
|
||||||
batch._params[paramOffset + 3]._uint,
|
|
||||||
batch._params[paramOffset + 2]._int,
|
|
||||||
batch._params[paramOffset + 1]._uint,
|
|
||||||
batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
|
||||||
ADD_COMMAND_GL(glColorPointer);
|
|
||||||
|
|
||||||
_params.push_back(cacheResource(pointer));
|
|
||||||
_params.push_back(stride);
|
|
||||||
_params.push_back(type);
|
|
||||||
_params.push_back(size);
|
|
||||||
|
|
||||||
DO_IT_NOW(_glColorPointer, 4);
|
|
||||||
}
|
|
||||||
void GLBackend::do_glColorPointer(Batch& batch, uint32 paramOffset) {
|
|
||||||
glColorPointer(
|
|
||||||
batch._params[paramOffset + 3]._int,
|
|
||||||
batch._params[paramOffset + 2]._uint,
|
|
||||||
batch._params[paramOffset + 1]._int,
|
|
||||||
batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) {
|
|
||||||
ADD_COMMAND_GL(glNormalPointer);
|
|
||||||
|
|
||||||
_params.push_back(cacheResource(pointer));
|
|
||||||
_params.push_back(stride);
|
|
||||||
_params.push_back(type);
|
|
||||||
|
|
||||||
DO_IT_NOW(_glNormalPointer, 3);
|
|
||||||
}
|
|
||||||
void GLBackend::do_glNormalPointer(Batch& batch, uint32 paramOffset) {
|
|
||||||
glNormalPointer(
|
|
||||||
batch._params[paramOffset + 2]._uint,
|
|
||||||
batch._params[paramOffset + 1]._int,
|
|
||||||
batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
|
||||||
ADD_COMMAND_GL(glTexCoordPointer);
|
|
||||||
|
|
||||||
_params.push_back(cacheResource(pointer));
|
|
||||||
_params.push_back(stride);
|
|
||||||
_params.push_back(type);
|
|
||||||
_params.push_back(size);
|
|
||||||
|
|
||||||
DO_IT_NOW(_glTexCoordPointer, 4);
|
|
||||||
}
|
|
||||||
void GLBackend::do_glTexCoordPointer(Batch& batch, uint32 paramOffset) {
|
|
||||||
glTexCoordPointer(
|
|
||||||
batch._params[paramOffset + 3]._int,
|
|
||||||
batch._params[paramOffset + 2]._uint,
|
|
||||||
batch._params[paramOffset + 1]._int,
|
|
||||||
batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
|
||||||
ADD_COMMAND_GL(glVertexPointer);
|
|
||||||
|
|
||||||
_params.push_back(cacheResource(pointer));
|
|
||||||
_params.push_back(stride);
|
|
||||||
_params.push_back(type);
|
|
||||||
_params.push_back(size);
|
|
||||||
|
|
||||||
DO_IT_NOW(_glVertexPointer, 4);
|
|
||||||
}
|
|
||||||
void GLBackend::do_glVertexPointer(Batch& batch, uint32 paramOffset) {
|
|
||||||
glVertexPointer(
|
|
||||||
batch._params[paramOffset + 3]._int,
|
|
||||||
batch._params[paramOffset + 2]._uint,
|
|
||||||
batch._params[paramOffset + 1]._int,
|
|
||||||
batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) {
|
|
||||||
ADD_COMMAND_GL(glVertexAttribPointer);
|
|
||||||
|
|
||||||
_params.push_back(cacheResource(pointer));
|
|
||||||
_params.push_back(stride);
|
|
||||||
_params.push_back(normalized);
|
|
||||||
_params.push_back(type);
|
|
||||||
_params.push_back(size);
|
|
||||||
_params.push_back(index);
|
|
||||||
|
|
||||||
DO_IT_NOW(_glVertexAttribPointer, 6);
|
|
||||||
}
|
|
||||||
void GLBackend::do_glVertexAttribPointer(Batch& batch, uint32 paramOffset) {
|
|
||||||
glVertexAttribPointer(
|
|
||||||
batch._params[paramOffset + 5]._uint,
|
|
||||||
batch._params[paramOffset + 4]._int,
|
|
||||||
batch._params[paramOffset + 3]._uint,
|
|
||||||
batch._params[paramOffset + 2]._uint,
|
|
||||||
batch._params[paramOffset + 1]._int,
|
|
||||||
batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Batch::_glEnableVertexAttribArray(GLint location) {
|
void Batch::_glEnableVertexAttribArray(GLint location) {
|
||||||
ADD_COMMAND_GL(glEnableVertexAttribArray);
|
ADD_COMMAND_GL(glEnableVertexAttribArray);
|
||||||
|
|
||||||
|
|
|
@ -75,10 +75,66 @@ public:
|
||||||
static GLShader* syncGPUObject(const Shader& shader);
|
static GLShader* syncGPUObject(const Shader& shader);
|
||||||
static GLuint getShaderID(const ShaderPointer& shader);
|
static GLuint getShaderID(const ShaderPointer& shader);
|
||||||
|
|
||||||
|
class GLState : public GPUObject {
|
||||||
|
public:
|
||||||
|
class Command {
|
||||||
|
public:
|
||||||
|
virtual void run(GLBackend* backend) = 0;
|
||||||
|
Command() {}
|
||||||
|
virtual ~Command() {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> class Command1 : public Command {
|
||||||
|
public:
|
||||||
|
typedef void (GLBackend::*GLFunction)(T);
|
||||||
|
void run(GLBackend* backend) { (backend->*(_func))(_param); }
|
||||||
|
Command1(GLFunction func, T param) : _func(func), _param(param) {};
|
||||||
|
GLFunction _func;
|
||||||
|
T _param;
|
||||||
|
};
|
||||||
|
template <class T, class U> class Command2 : public Command {
|
||||||
|
public:
|
||||||
|
typedef void (GLBackend::*GLFunction)(T, U);
|
||||||
|
void run(GLBackend* backend) { (backend->*(_func))(_param0, _param1); }
|
||||||
|
Command2(GLFunction func, T param0, U param1) : _func(func), _param0(param0), _param1(param1) {};
|
||||||
|
GLFunction _func;
|
||||||
|
T _param0;
|
||||||
|
U _param1;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class V> class Command3 : public Command {
|
||||||
|
public:
|
||||||
|
typedef void (GLBackend::*GLFunction)(T, U, V);
|
||||||
|
void run(GLBackend* backend) { (backend->*(_func))(_param0, _param1, _param2); }
|
||||||
|
Command3(GLFunction func, T param0, U param1, V param2) : _func(func), _param0(param0), _param1(param1), _param2(param2) {};
|
||||||
|
GLFunction _func;
|
||||||
|
T _param0;
|
||||||
|
U _param1;
|
||||||
|
V _param2;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr< Command > CommandPointer;
|
||||||
|
typedef std::vector< CommandPointer > Commands;
|
||||||
|
|
||||||
|
Commands _commands;
|
||||||
|
Stamp _stamp;
|
||||||
|
State::Signature _signature;
|
||||||
|
|
||||||
|
GLState();
|
||||||
|
~GLState();
|
||||||
|
|
||||||
|
// The state commands to reset to default,
|
||||||
|
// WARNING depending on the order of the State::Field enum
|
||||||
|
static const Commands _resetStateCommands;
|
||||||
|
|
||||||
|
friend class GLBackend;
|
||||||
|
};
|
||||||
|
static GLState* syncGPUObject(const State& state);
|
||||||
|
|
||||||
class GLPipeline : public GPUObject {
|
class GLPipeline : public GPUObject {
|
||||||
public:
|
public:
|
||||||
GLShader* _program;
|
GLShader* _program;
|
||||||
|
GLState* _state;
|
||||||
|
|
||||||
GLPipeline();
|
GLPipeline();
|
||||||
~GLPipeline();
|
~GLPipeline();
|
||||||
|
@ -90,21 +146,43 @@ public:
|
||||||
|
|
||||||
uint32 getNumInputBuffers() const { return _input._buffersState.size(); }
|
uint32 getNumInputBuffers() const { return _input._buffersState.size(); }
|
||||||
|
|
||||||
|
|
||||||
|
// The State setters called by the GLState::Commands when a new state is assigned
|
||||||
|
void do_setStateFillMode(int32 mode);
|
||||||
|
void do_setStateCullMode(int32 mode);
|
||||||
|
void do_setStateFrontFaceClockwise(bool isClockwise);
|
||||||
|
void do_setStateDepthClipEnable(bool enable);
|
||||||
|
void do_setStateScissorEnable(bool enable);
|
||||||
|
void do_setStateMultisampleEnable(bool enable);
|
||||||
|
void do_setStateAntialiasedLineEnable(bool enable);
|
||||||
|
|
||||||
|
void do_setStateDepthBias(Vec2 bias);
|
||||||
|
void do_setStateDepthTest(State::DepthTest test);
|
||||||
|
|
||||||
|
void do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest);
|
||||||
|
|
||||||
|
void do_setStateAlphaToCoverageEnable(bool enable);
|
||||||
|
void do_setStateSampleMask(uint32 mask);
|
||||||
|
|
||||||
|
void do_setStateBlend(State::BlendFunction blendFunction);
|
||||||
|
|
||||||
|
void do_setStateColorWriteMask(uint32 mask);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Draw Stage
|
// Draw Stage
|
||||||
void do_draw(Batch& batch, uint32 paramOffset);
|
void do_draw(Batch& batch, uint32 paramOffset);
|
||||||
void do_drawIndexed(Batch& batch, uint32 paramOffset);
|
void do_drawIndexed(Batch& batch, uint32 paramOffset);
|
||||||
void do_drawInstanced(Batch& batch, uint32 paramOffset);
|
void do_drawInstanced(Batch& batch, uint32 paramOffset);
|
||||||
void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset);
|
void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
// Input Stage
|
// Input Stage
|
||||||
void do_setInputFormat(Batch& batch, uint32 paramOffset);
|
void do_setInputFormat(Batch& batch, uint32 paramOffset);
|
||||||
void do_setInputBuffer(Batch& batch, uint32 paramOffset);
|
void do_setInputBuffer(Batch& batch, uint32 paramOffset);
|
||||||
void do_setIndexBuffer(Batch& batch, uint32 paramOffset);
|
void do_setIndexBuffer(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void updateInput();
|
void updateInput();
|
||||||
struct InputStageState {
|
struct InputStageState {
|
||||||
bool _invalidFormat;
|
bool _invalidFormat;
|
||||||
Stream::FormatPointer _format;
|
Stream::FormatPointer _format;
|
||||||
|
|
||||||
|
@ -137,18 +215,18 @@ protected:
|
||||||
} _input;
|
} _input;
|
||||||
|
|
||||||
// Transform Stage
|
// Transform Stage
|
||||||
void do_setModelTransform(Batch& batch, uint32 paramOffset);
|
void do_setModelTransform(Batch& batch, uint32 paramOffset);
|
||||||
void do_setViewTransform(Batch& batch, uint32 paramOffset);
|
void do_setViewTransform(Batch& batch, uint32 paramOffset);
|
||||||
void do_setProjectionTransform(Batch& batch, uint32 paramOffset);
|
void do_setProjectionTransform(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void initTransform();
|
void initTransform();
|
||||||
void killTransform();
|
void killTransform();
|
||||||
void updateTransform();
|
void updateTransform();
|
||||||
struct TransformStageState {
|
struct TransformStageState {
|
||||||
TransformObject _transformObject;
|
TransformObject _transformObject;
|
||||||
TransformCamera _transformCamera;
|
TransformCamera _transformCamera;
|
||||||
GLuint _transformObjectBuffer;
|
GLuint _transformObjectBuffer;
|
||||||
GLuint _transformCameraBuffer;
|
GLuint _transformCameraBuffer;
|
||||||
Transform _model;
|
Transform _model;
|
||||||
Transform _view;
|
Transform _view;
|
||||||
Mat4 _projection;
|
Mat4 _projection;
|
||||||
|
@ -172,38 +250,61 @@ protected:
|
||||||
|
|
||||||
// Pipeline Stage
|
// Pipeline Stage
|
||||||
void do_setPipeline(Batch& batch, uint32 paramOffset);
|
void do_setPipeline(Batch& batch, uint32 paramOffset);
|
||||||
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
|
|
||||||
void do_setUniformTexture(Batch& batch, uint32 paramOffset);
|
void do_setStateBlendFactor(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
|
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
|
||||||
|
void do_setUniformTexture(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void updatePipeline();
|
// 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
|
||||||
|
void resetPipelineState(State::Signature toBeReset);
|
||||||
|
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||||
|
void syncPipelineStateCache();
|
||||||
|
// Grab the actual gl state into it's gpu::State equivalent. THis is used by the above call syncPipleineStateCache()
|
||||||
|
void getCurrentGLState(State::Data& state);
|
||||||
|
|
||||||
struct PipelineStageState {
|
struct PipelineStageState {
|
||||||
|
|
||||||
PipelinePointer _pipeline;
|
PipelinePointer _pipeline;
|
||||||
|
|
||||||
GLuint _program;
|
GLuint _program;
|
||||||
bool _invalidProgram;
|
bool _invalidProgram;
|
||||||
|
|
||||||
|
State::Data _stateCache;
|
||||||
|
State::Signature _stateSignatureCache;
|
||||||
|
|
||||||
|
GLState* _state;
|
||||||
|
bool _invalidState;
|
||||||
|
bool _needStateSync;
|
||||||
|
|
||||||
PipelineStageState() :
|
PipelineStageState() :
|
||||||
_pipeline(),
|
_pipeline(),
|
||||||
_program(0),
|
_program(0),
|
||||||
_invalidProgram(false)
|
_invalidProgram(false),
|
||||||
|
_stateCache(State::DEFAULT),
|
||||||
|
_stateSignatureCache(0),
|
||||||
|
_state(nullptr),
|
||||||
|
_invalidState(false),
|
||||||
|
_needStateSync(true)
|
||||||
{}
|
{}
|
||||||
} _pipeline;
|
} _pipeline;
|
||||||
|
|
||||||
|
|
||||||
// TODO: As long as we have gl calls explicitely issued from interface
|
// 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
|
// 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
|
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||||
void do_glEnable(Batch& batch, uint32 paramOffset);
|
void do_glEnable(Batch& batch, uint32 paramOffset);
|
||||||
void do_glDisable(Batch& batch, uint32 paramOffset);
|
void do_glDisable(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void do_glEnableClientState(Batch& batch, uint32 paramOffset);
|
void do_glEnableClientState(Batch& batch, uint32 paramOffset);
|
||||||
void do_glDisableClientState(Batch& batch, uint32 paramOffset);
|
void do_glDisableClientState(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void do_glCullFace(Batch& batch, uint32 paramOffset);
|
void do_glCullFace(Batch& batch, uint32 paramOffset);
|
||||||
void do_glAlphaFunc(Batch& batch, uint32 paramOffset);
|
void do_glAlphaFunc(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void do_glDepthFunc(Batch& batch, uint32 paramOffset);
|
void do_glDepthFunc(Batch& batch, uint32 paramOffset);
|
||||||
void do_glDepthMask(Batch& batch, uint32 paramOffset);
|
void do_glDepthMask(Batch& batch, uint32 paramOffset);
|
||||||
void do_glDepthRange(Batch& batch, uint32 paramOffset);
|
void do_glDepthRange(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void do_glBindBuffer(Batch& batch, uint32 paramOffset);
|
void do_glBindBuffer(Batch& batch, uint32 paramOffset);
|
||||||
|
@ -217,17 +318,8 @@ protected:
|
||||||
void do_glUniform1f(Batch& batch, uint32 paramOffset);
|
void do_glUniform1f(Batch& batch, uint32 paramOffset);
|
||||||
void do_glUniform2f(Batch& batch, uint32 paramOffset);
|
void do_glUniform2f(Batch& batch, uint32 paramOffset);
|
||||||
void do_glUniform4fv(Batch& batch, uint32 paramOffset);
|
void do_glUniform4fv(Batch& batch, uint32 paramOffset);
|
||||||
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
|
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void do_glDrawArrays(Batch& batch, uint32 paramOffset);
|
|
||||||
void do_glDrawRangeElements(Batch& batch, uint32 paramOffset);
|
|
||||||
|
|
||||||
void do_glColorPointer(Batch& batch, uint32 paramOffset);
|
|
||||||
void do_glNormalPointer(Batch& batch, uint32 paramOffset);
|
|
||||||
void do_glTexCoordPointer(Batch& batch, uint32 paramOffset);
|
|
||||||
void do_glVertexPointer(Batch& batch, uint32 paramOffset);
|
|
||||||
|
|
||||||
void do_glVertexAttribPointer(Batch& batch, uint32 paramOffset);
|
|
||||||
void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset);
|
void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset);
|
||||||
void do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset);
|
void do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
|
||||||
GLBackend::GLPipeline::GLPipeline() :
|
GLBackend::GLPipeline::GLPipeline() :
|
||||||
_program(nullptr)
|
_program(nullptr),
|
||||||
|
_state(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
GLBackend::GLPipeline::~GLPipeline() {
|
GLBackend::GLPipeline::~GLPipeline() {
|
||||||
_program = nullptr;
|
_program = nullptr;
|
||||||
|
_state = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) {
|
GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) {
|
||||||
|
@ -30,24 +32,118 @@ GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
// No object allocated yet, let's see if it's worth it...
|
||||||
|
ShaderPointer shader = pipeline.getProgram();
|
||||||
|
GLShader* programObject = GLBackend::syncGPUObject((*shader));
|
||||||
|
if (programObject == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatePointer state = pipeline.getState();
|
||||||
|
GLState* stateObject = GLBackend::syncGPUObject((*state));
|
||||||
|
if (stateObject == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Program and state are valid, we can create the pipeline object
|
||||||
|
if (!object) {
|
||||||
|
object = new GLPipeline();
|
||||||
|
Backend::setGPUObject(pipeline, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
object->_program = programObject;
|
||||||
|
object->_state = stateObject;
|
||||||
|
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
|
void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
|
||||||
PipelinePointer pipeline = batch._pipelines.get(batch._params[paramOffset + 0]._uint);
|
PipelinePointer pipeline = batch._pipelines.get(batch._params[paramOffset + 0]._uint);
|
||||||
|
|
||||||
if (pipeline == _pipeline._pipeline) {
|
if (_pipeline._pipeline == pipeline) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pipelineObject = syncGPUObject((*pipeline));
|
if (_pipeline._needStateSync) {
|
||||||
if (!pipelineObject) {
|
syncPipelineStateCache();
|
||||||
return;
|
_pipeline._needStateSync = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// null pipeline == reset
|
||||||
|
if (!pipeline) {
|
||||||
|
_pipeline._pipeline.reset();
|
||||||
|
|
||||||
|
_pipeline._program = 0;
|
||||||
|
_pipeline._invalidProgram = true;
|
||||||
|
|
||||||
|
_pipeline._state = nullptr;
|
||||||
|
_pipeline._invalidState = true;
|
||||||
|
} else {
|
||||||
|
auto pipelineObject = syncGPUObject((*pipeline));
|
||||||
|
if (!pipelineObject) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the program cache
|
||||||
|
if (_pipeline._program != pipelineObject->_program->_program) {
|
||||||
|
_pipeline._program = pipelineObject->_program->_program;
|
||||||
|
_pipeline._invalidProgram = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now for the state
|
||||||
|
if (_pipeline._state != pipelineObject->_state) {
|
||||||
|
_pipeline._state = pipelineObject->_state;
|
||||||
|
_pipeline._invalidState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember the new pipeline
|
||||||
|
_pipeline._pipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
// THis should be done on Pipeline::update...
|
||||||
|
if (_pipeline._invalidProgram) {
|
||||||
|
glUseProgram(_pipeline._program);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
_pipeline._invalidProgram = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEBUG_GLSTATE
|
||||||
|
void GLBackend::updatePipeline() {
|
||||||
|
#ifdef DEBUG_GLSTATE
|
||||||
|
if (_pipeline._needStateSync) {
|
||||||
|
State::Data state;
|
||||||
|
getCurrentGLState(state);
|
||||||
|
State::Signature signature = State::evalSignature(state);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_pipeline._invalidProgram) {
|
||||||
|
// doing it here is aproblem for calls to glUniform.... so will do it on assing...
|
||||||
|
glUseProgram(_pipeline._program);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
_pipeline._invalidProgram = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pipeline._invalidState) {
|
||||||
|
if (_pipeline._state) {
|
||||||
|
// first reset to default what should be
|
||||||
|
// the fields which were not to default and are default now
|
||||||
|
resetPipelineState(_pipeline._state->_signature);
|
||||||
|
|
||||||
|
// Update the signature cache with what's going to be touched
|
||||||
|
_pipeline._stateSignatureCache |= _pipeline._state->_signature;
|
||||||
|
|
||||||
|
// And perform
|
||||||
|
for (auto command: _pipeline._state->_commands) {
|
||||||
|
command->run(this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No state ? anyway just reset everything
|
||||||
|
resetPipelineState(0);
|
||||||
|
}
|
||||||
|
_pipeline._invalidState = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_pipeline._pipeline = pipeline;
|
|
||||||
_pipeline._program = pipelineObject->_program->_program;
|
|
||||||
_pipeline._invalidProgram = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
|
void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
|
||||||
|
@ -81,13 +177,3 @@ void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) {
|
||||||
CHECK_GL_ERROR();
|
CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLBackend::updatePipeline() {
|
|
||||||
if (_pipeline._invalidProgram) {
|
|
||||||
glUseProgram(_pipeline._program);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
|
|
||||||
_pipeline._invalidProgram = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
735
libraries/gpu/src/gpu/GLBackendState.cpp
Normal file
735
libraries/gpu/src/gpu/GLBackendState.cpp
Normal file
|
@ -0,0 +1,735 @@
|
||||||
|
//
|
||||||
|
// GLBackendState.cpp
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 3/22/2015.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GLBackendShared.h"
|
||||||
|
|
||||||
|
#include "Format.h"
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
|
||||||
|
GLBackend::GLState::GLState()
|
||||||
|
{}
|
||||||
|
|
||||||
|
GLBackend::GLState::~GLState() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef GLBackend::GLState::Command Command;
|
||||||
|
typedef GLBackend::GLState::CommandPointer CommandPointer;
|
||||||
|
typedef GLBackend::GLState::Command1<uint32> Command1U;
|
||||||
|
typedef GLBackend::GLState::Command1<int32> Command1I;
|
||||||
|
typedef GLBackend::GLState::Command1<bool> Command1B;
|
||||||
|
typedef GLBackend::GLState::Command1<Vec2> CommandDepthBias;
|
||||||
|
typedef GLBackend::GLState::Command1<State::DepthTest> CommandDepthTest;
|
||||||
|
typedef GLBackend::GLState::Command3<State::StencilActivation, State::StencilTest, State::StencilTest> CommandStencil;
|
||||||
|
typedef GLBackend::GLState::Command1<State::BlendFunction> CommandBlend;
|
||||||
|
|
||||||
|
// The state commands to reset to default,
|
||||||
|
// WARNING depending on the order of the State::Field enum
|
||||||
|
const GLBackend::GLState::Commands GLBackend::GLState::_resetStateCommands = {
|
||||||
|
CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, State::DEFAULT.fillMode)),
|
||||||
|
CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, State::DEFAULT.cullMode)),
|
||||||
|
CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, State::DEFAULT.frontFaceClockwise)),
|
||||||
|
CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, State::DEFAULT.depthClipEnable)),
|
||||||
|
CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, State::DEFAULT.scissorEnable)),
|
||||||
|
CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, State::DEFAULT.multisampleEnable)),
|
||||||
|
CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, State::DEFAULT.antialisedLineEnable)),
|
||||||
|
|
||||||
|
// Depth bias has 2 fields in State but really one call in GLBackend
|
||||||
|
CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))),
|
||||||
|
CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))),
|
||||||
|
|
||||||
|
CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, State::DEFAULT.depthTest)),
|
||||||
|
|
||||||
|
// Depth bias has 3 fields in State but really one call in GLBackend
|
||||||
|
CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)),
|
||||||
|
CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)),
|
||||||
|
CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)),
|
||||||
|
|
||||||
|
CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, State::DEFAULT.alphaToCoverageEnable)),
|
||||||
|
|
||||||
|
CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, State::DEFAULT.sampleMask)),
|
||||||
|
|
||||||
|
CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, State::DEFAULT.blendFunction)),
|
||||||
|
|
||||||
|
CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, State::DEFAULT.colorWriteMask))
|
||||||
|
};
|
||||||
|
|
||||||
|
void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) {
|
||||||
|
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(fillMode))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateCullMode(GLBackend::GLState::Commands& commands, State::CullMode cullMode) {
|
||||||
|
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, int32(cullMode))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateFrontFaceClockwise(GLBackend::GLState::Commands& commands, bool isClockwise) {
|
||||||
|
commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, isClockwise)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateDepthClipEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||||
|
commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, enable)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateScissorEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||||
|
commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, enable)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateMultisampleEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||||
|
commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, enable)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||||
|
commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, enable)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateDepthBias(GLBackend::GLState::Commands& commands, const State& state) {
|
||||||
|
commands.push_back(CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(state.getDepthBias(), state.getDepthBiasSlopeScale()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateDepthTest(GLBackend::GLState::Commands& commands, const State::DepthTest& test) {
|
||||||
|
commands.push_back(CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, int32(test.getRaw()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateStencil(GLBackend::GLState::Commands& commands, const State& state) {
|
||||||
|
commands.push_back(CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, state.getStencilActivation(), state.getStencilTestFront(), state.getStencilTestBack())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||||
|
commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, enable)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateSampleMask(GLBackend::GLState::Commands& commands, uint32 mask) {
|
||||||
|
commands.push_back(CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, mask)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateBlend(GLBackend::GLState::Commands& commands, const State& state) {
|
||||||
|
commands.push_back(CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, state.getBlendFunction())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateColorWriteMask(GLBackend::GLState::Commands& commands, uint32 mask) {
|
||||||
|
commands.push_back(CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, mask)));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
|
||||||
|
GLState* object = Backend::getGPUObject<GLBackend::GLState>(state);
|
||||||
|
|
||||||
|
// If GPU object already created then good
|
||||||
|
if (object) {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else allocate and create the GLState
|
||||||
|
if (!object) {
|
||||||
|
object = new GLState();
|
||||||
|
Backend::setGPUObject(state, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
// here, we need to regenerate something so let's do it all
|
||||||
|
object->_commands.clear();
|
||||||
|
object->_stamp = state.getStamp();
|
||||||
|
object->_signature = state.getSignature();
|
||||||
|
|
||||||
|
bool depthBias = false;
|
||||||
|
bool stencilState = false;
|
||||||
|
bool blendState = false;
|
||||||
|
|
||||||
|
// go thorugh the list of state fields in the State and record the corresponding gl command
|
||||||
|
for (int i = 0; i < State::NUM_FIELDS; i++) {
|
||||||
|
if (state.getSignature()[i]) {
|
||||||
|
switch(i) {
|
||||||
|
case State::FILL_MODE: {
|
||||||
|
generateFillMode(object->_commands, state.getFillMode());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::CULL_MODE: {
|
||||||
|
generateCullMode(object->_commands, state.getCullMode());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::DEPTH_BIAS:
|
||||||
|
case State::DEPTH_BIAS_SLOPE_SCALE: {
|
||||||
|
depthBias = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::FRONT_FACE_CLOCKWISE: {
|
||||||
|
generateFrontFaceClockwise(object->_commands, state.isFrontFaceClockwise());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::DEPTH_CLIP_ENABLE: {
|
||||||
|
generateDepthClipEnable(object->_commands, state.isDepthClipEnable());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SCISSOR_ENABLE: {
|
||||||
|
generateScissorEnable(object->_commands, state.isScissorEnable());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::MULTISAMPLE_ENABLE: {
|
||||||
|
generateMultisampleEnable(object->_commands, state.isMultisampleEnable());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::ANTIALISED_LINE_ENABLE: {
|
||||||
|
generateAntialiasedLineEnable(object->_commands, state.isAntialiasedLineEnable());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::DEPTH_TEST: {
|
||||||
|
generateDepthTest(object->_commands, state.getDepthTest());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::STENCIL_ACTIVATION:
|
||||||
|
case State::STENCIL_TEST_FRONT:
|
||||||
|
case State::STENCIL_TEST_BACK: {
|
||||||
|
stencilState = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::SAMPLE_MASK: {
|
||||||
|
generateSampleMask(object->_commands, state.getSampleMask());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::ALPHA_TO_COVERAGE_ENABLE: {
|
||||||
|
generateAlphaToCoverageEnable(object->_commands, state.isAlphaToCoverageEnabled());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::BLEND_FUNCTION: {
|
||||||
|
generateBlend(object->_commands, state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::COLOR_WRITE_MASK: {
|
||||||
|
generateColorWriteMask(object->_commands, state.getColorWriteMask());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depthBias) {
|
||||||
|
generateDepthBias(object->_commands, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencilState) {
|
||||||
|
generateStencil(object->_commands, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLBackend::resetPipelineState(State::Signature nextSignature) {
|
||||||
|
auto currentNotSignature = ~_pipeline._stateSignatureCache;
|
||||||
|
auto nextNotSignature = ~nextSignature;
|
||||||
|
auto fieldsToBeReset = currentNotSignature ^ (currentNotSignature | nextNotSignature);
|
||||||
|
if (fieldsToBeReset.any()) {
|
||||||
|
for (auto i = 0; i < State::NUM_FIELDS; i++) {
|
||||||
|
if (fieldsToBeReset[i]) {
|
||||||
|
GLState::_resetStateCommands[i]->run(this);
|
||||||
|
_pipeline._stateSignatureCache.reset(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
State::ComparisonFunction comparisonFuncFromGL(GLenum func) {
|
||||||
|
if (func == GL_NEVER) {
|
||||||
|
return State::NEVER;
|
||||||
|
} else if (func == GL_LESS) {
|
||||||
|
return State::LESS;
|
||||||
|
} else if (func == GL_EQUAL) {
|
||||||
|
return State::EQUAL;
|
||||||
|
} else if (func == GL_LEQUAL) {
|
||||||
|
return State::LESS_EQUAL;
|
||||||
|
} else if (func == GL_GREATER) {
|
||||||
|
return State::GREATER;
|
||||||
|
} else if (func == GL_NOTEQUAL) {
|
||||||
|
return State::NOT_EQUAL;
|
||||||
|
} else if (func == GL_GEQUAL) {
|
||||||
|
return State::GREATER_EQUAL;
|
||||||
|
} else if (func == GL_ALWAYS) {
|
||||||
|
return State::ALWAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return State::ALWAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
State::StencilOp stencilOpFromGL(GLenum stencilOp) {
|
||||||
|
if (stencilOp == GL_KEEP) {
|
||||||
|
return State::STENCIL_OP_KEEP;
|
||||||
|
} else if (stencilOp == GL_ZERO) {
|
||||||
|
return State::STENCIL_OP_ZERO;
|
||||||
|
} else if (stencilOp == GL_REPLACE) {
|
||||||
|
return State::STENCIL_OP_REPLACE;
|
||||||
|
} else if (stencilOp == GL_INCR_WRAP) {
|
||||||
|
return State::STENCIL_OP_INCR_SAT;
|
||||||
|
} else if (stencilOp == GL_DECR_WRAP) {
|
||||||
|
return State::STENCIL_OP_DECR_SAT;
|
||||||
|
} else if (stencilOp == GL_INVERT) {
|
||||||
|
return State::STENCIL_OP_INVERT;
|
||||||
|
} else if (stencilOp == GL_INCR) {
|
||||||
|
return State::STENCIL_OP_INCR;
|
||||||
|
} else if (stencilOp == GL_DECR) {
|
||||||
|
return State::STENCIL_OP_DECR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return State::STENCIL_OP_KEEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
State::BlendOp blendOpFromGL(GLenum blendOp) {
|
||||||
|
if (blendOp == GL_FUNC_ADD) {
|
||||||
|
return State::BLEND_OP_ADD;
|
||||||
|
} else if (blendOp == GL_FUNC_SUBTRACT) {
|
||||||
|
return State::BLEND_OP_SUBTRACT;
|
||||||
|
} else if (blendOp == GL_FUNC_REVERSE_SUBTRACT) {
|
||||||
|
return State::BLEND_OP_REV_SUBTRACT;
|
||||||
|
} else if (blendOp == GL_MIN) {
|
||||||
|
return State::BLEND_OP_MIN;
|
||||||
|
} else if (blendOp == GL_MAX) {
|
||||||
|
return State::BLEND_OP_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return State::BLEND_OP_ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
State::BlendArg blendArgFromGL(GLenum blendArg) {
|
||||||
|
if (blendArg == GL_ZERO) {
|
||||||
|
return State::ZERO;
|
||||||
|
} else if (blendArg == GL_ONE) {
|
||||||
|
return State::ONE;
|
||||||
|
} else if (blendArg == GL_SRC_COLOR) {
|
||||||
|
return State::SRC_COLOR;
|
||||||
|
} else if (blendArg == GL_ONE_MINUS_SRC_COLOR) {
|
||||||
|
return State::INV_SRC_COLOR;
|
||||||
|
} else if (blendArg == GL_DST_COLOR) {
|
||||||
|
return State::DEST_COLOR;
|
||||||
|
} else if (blendArg == GL_ONE_MINUS_DST_COLOR) {
|
||||||
|
return State::INV_DEST_COLOR;
|
||||||
|
} else if (blendArg == GL_SRC_ALPHA) {
|
||||||
|
return State::SRC_ALPHA;
|
||||||
|
} else if (blendArg == GL_ONE_MINUS_SRC_ALPHA) {
|
||||||
|
return State::INV_SRC_ALPHA;
|
||||||
|
} else if (blendArg == GL_DST_ALPHA) {
|
||||||
|
return State::DEST_ALPHA;
|
||||||
|
} else if (blendArg == GL_ONE_MINUS_DST_ALPHA) {
|
||||||
|
return State::INV_DEST_ALPHA;
|
||||||
|
} else if (blendArg == GL_CONSTANT_COLOR) {
|
||||||
|
return State::FACTOR_COLOR;
|
||||||
|
} else if (blendArg == GL_ONE_MINUS_CONSTANT_COLOR) {
|
||||||
|
return State::INV_FACTOR_COLOR;
|
||||||
|
} else if (blendArg == GL_CONSTANT_ALPHA) {
|
||||||
|
return State::FACTOR_ALPHA;
|
||||||
|
} else if (blendArg == GL_ONE_MINUS_CONSTANT_ALPHA) {
|
||||||
|
return State::INV_FACTOR_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return State::ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::getCurrentGLState(State::Data& state) {
|
||||||
|
{
|
||||||
|
GLint modes[2];
|
||||||
|
glGetIntegerv(GL_POLYGON_MODE, modes);
|
||||||
|
if (modes[0] == GL_FILL) {
|
||||||
|
state.fillMode = State::FILL_FACE;
|
||||||
|
} else {
|
||||||
|
if (modes[0] == GL_LINE) {
|
||||||
|
state.fillMode = State::FILL_LINE;
|
||||||
|
} else {
|
||||||
|
state.fillMode = State::FILL_POINT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if (glIsEnabled(GL_CULL_FACE)) {
|
||||||
|
GLint mode;
|
||||||
|
glGetIntegerv(GL_CULL_FACE_MODE, &mode);
|
||||||
|
state.cullMode = (mode == GL_FRONT ? State::CULL_FRONT : State::CULL_BACK);
|
||||||
|
} else {
|
||||||
|
state.cullMode = State::CULL_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GLint winding;
|
||||||
|
glGetIntegerv(GL_FRONT_FACE, &winding);
|
||||||
|
state.frontFaceClockwise = (winding == GL_CW);
|
||||||
|
state.depthClipEnable = glIsEnabled(GL_DEPTH_CLAMP);
|
||||||
|
state.scissorEnable = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
state.multisampleEnable = glIsEnabled(GL_MULTISAMPLE);
|
||||||
|
state.antialisedLineEnable = glIsEnabled(GL_LINE_SMOOTH);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if (glIsEnabled(GL_POLYGON_OFFSET_FILL)) {
|
||||||
|
glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &state.depthBiasSlopeScale);
|
||||||
|
glGetFloatv(GL_POLYGON_OFFSET_UNITS, &state.depthBias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GLboolean isEnabled = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
GLboolean writeMask;
|
||||||
|
glGetBooleanv(GL_DEPTH_WRITEMASK, &writeMask);
|
||||||
|
GLint func;
|
||||||
|
glGetIntegerv(GL_DEPTH_FUNC, &func);
|
||||||
|
|
||||||
|
state.depthTest = State::DepthTest(isEnabled, writeMask, comparisonFuncFromGL(func));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GLboolean isEnabled = glIsEnabled(GL_STENCIL_TEST);
|
||||||
|
|
||||||
|
GLint frontWriteMask;
|
||||||
|
GLint frontReadMask;
|
||||||
|
GLint frontRef;
|
||||||
|
GLint frontFail;
|
||||||
|
GLint frontDepthFail;
|
||||||
|
GLint frontPass;
|
||||||
|
GLint frontFunc;
|
||||||
|
glGetIntegerv(GL_STENCIL_WRITEMASK, &frontWriteMask);
|
||||||
|
glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontReadMask);
|
||||||
|
glGetIntegerv(GL_STENCIL_REF, &frontRef);
|
||||||
|
glGetIntegerv(GL_STENCIL_FAIL, &frontFail);
|
||||||
|
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &frontDepthFail);
|
||||||
|
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &frontPass);
|
||||||
|
glGetIntegerv(GL_STENCIL_FUNC, &frontFunc);
|
||||||
|
|
||||||
|
GLint backWriteMask;
|
||||||
|
GLint backReadMask;
|
||||||
|
GLint backRef;
|
||||||
|
GLint backFail;
|
||||||
|
GLint backDepthFail;
|
||||||
|
GLint backPass;
|
||||||
|
GLint backFunc;
|
||||||
|
glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &backWriteMask);
|
||||||
|
glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backReadMask);
|
||||||
|
glGetIntegerv(GL_STENCIL_BACK_REF, &backRef);
|
||||||
|
glGetIntegerv(GL_STENCIL_BACK_FAIL, &backFail);
|
||||||
|
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &backDepthFail);
|
||||||
|
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &backPass);
|
||||||
|
glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc);
|
||||||
|
|
||||||
|
state.stencilActivation = State::StencilActivation(isEnabled, frontWriteMask, backWriteMask);
|
||||||
|
state.stencilTestFront = State::StencilTest(frontRef, frontReadMask, comparisonFuncFromGL(frontFunc), stencilOpFromGL(frontFail), stencilOpFromGL(frontDepthFail), stencilOpFromGL(frontPass));
|
||||||
|
state.stencilTestBack = State::StencilTest(backRef, backReadMask, comparisonFuncFromGL(backFunc), stencilOpFromGL(backFail), stencilOpFromGL(backDepthFail), stencilOpFromGL(backPass));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GLint mask = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
#ifdef GPU_PROFILE_CORE
|
||||||
|
if (glIsEnabled(GL_SAMPLE_MASK)) {
|
||||||
|
glGetIntegerv(GL_SAMPLE_MASK, &mask);
|
||||||
|
state.sampleMask = mask;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
state.sampleMask = mask;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
state.alphaToCoverageEnable = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GLboolean isEnabled = glIsEnabled(GL_BLEND);
|
||||||
|
GLint srcRGB;
|
||||||
|
GLint srcA;
|
||||||
|
GLint dstRGB;
|
||||||
|
GLint dstA;
|
||||||
|
glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB);
|
||||||
|
glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcA);
|
||||||
|
glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB);
|
||||||
|
glGetIntegerv(GL_BLEND_DST_ALPHA, &dstA);
|
||||||
|
|
||||||
|
GLint opRGB;
|
||||||
|
GLint opA;
|
||||||
|
glGetIntegerv(GL_BLEND_EQUATION_RGB, &opRGB);
|
||||||
|
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &opA);
|
||||||
|
|
||||||
|
state.blendFunction = State::BlendFunction(isEnabled,
|
||||||
|
blendArgFromGL(srcRGB), blendOpFromGL(opRGB), blendArgFromGL(dstRGB),
|
||||||
|
blendArgFromGL(srcA), blendOpFromGL(opA), blendArgFromGL(dstA));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GLboolean mask[4];
|
||||||
|
glGetBooleanv(GL_COLOR_WRITEMASK, mask);
|
||||||
|
state.colorWriteMask = (mask[0] ? State::WRITE_RED : 0)
|
||||||
|
| (mask[1] ? State::WRITE_GREEN : 0)
|
||||||
|
| (mask[2] ? State::WRITE_BLUE : 0)
|
||||||
|
| (mask[3] ? State::WRITE_ALPHA : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::syncPipelineStateCache() {
|
||||||
|
State::Data state;
|
||||||
|
|
||||||
|
getCurrentGLState(state);
|
||||||
|
State::Signature signature = State::evalSignature(state);
|
||||||
|
|
||||||
|
_pipeline._stateCache = state;
|
||||||
|
_pipeline._stateSignatureCache = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLenum GL_COMPARISON_FUNCTIONS[] = {
|
||||||
|
GL_NEVER,
|
||||||
|
GL_LESS,
|
||||||
|
GL_EQUAL,
|
||||||
|
GL_LEQUAL,
|
||||||
|
GL_GREATER,
|
||||||
|
GL_NOTEQUAL,
|
||||||
|
GL_GEQUAL,
|
||||||
|
GL_ALWAYS };
|
||||||
|
|
||||||
|
void GLBackend::do_setStateFillMode(int32 mode) {
|
||||||
|
if (_pipeline._stateCache.fillMode != mode) {
|
||||||
|
static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL };
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.fillMode = State::FillMode(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateCullMode(int32 mode) {
|
||||||
|
if (_pipeline._stateCache.cullMode != mode) {
|
||||||
|
static GLenum GL_CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK };
|
||||||
|
if (mode == State::CULL_NONE) {
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_FRONT_AND_BACK);
|
||||||
|
} else {
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_CULL_MODES[mode]);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.cullMode = State::CullMode(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateFrontFaceClockwise(bool isClockwise) {
|
||||||
|
if (_pipeline._stateCache.frontFaceClockwise != isClockwise) {
|
||||||
|
static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW };
|
||||||
|
glFrontFace(GL_FRONT_FACES[isClockwise]);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.frontFaceClockwise = isClockwise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateDepthClipEnable(bool enable) {
|
||||||
|
if (_pipeline._stateCache.depthClipEnable != enable) {
|
||||||
|
if (enable) {
|
||||||
|
glEnable(GL_DEPTH_CLAMP);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_DEPTH_CLAMP);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.depthClipEnable = enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateScissorEnable(bool enable) {
|
||||||
|
if (_pipeline._stateCache.scissorEnable != enable) {
|
||||||
|
if (enable) {
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.scissorEnable = enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateMultisampleEnable(bool enable) {
|
||||||
|
if (_pipeline._stateCache.multisampleEnable != enable) {
|
||||||
|
if (enable) {
|
||||||
|
glEnable(GL_MULTISAMPLE);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_MULTISAMPLE);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.multisampleEnable = enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateAntialiasedLineEnable(bool enable) {
|
||||||
|
if (_pipeline._stateCache.antialisedLineEnable != enable) {
|
||||||
|
if (enable) {
|
||||||
|
glEnable(GL_POINT_SMOOTH);
|
||||||
|
glEnable(GL_LINE_SMOOTH);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_POINT_SMOOTH);
|
||||||
|
glDisable(GL_LINE_SMOOTH);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.antialisedLineEnable = enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateDepthBias(Vec2 bias) {
|
||||||
|
if ( (bias.x != _pipeline._stateCache.depthBias) || (bias.y != _pipeline._stateCache.depthBiasSlopeScale)) {
|
||||||
|
if ((bias.x != 0.f) || (bias.y != 0.f)) {
|
||||||
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glEnable(GL_POLYGON_OFFSET_LINE);
|
||||||
|
glEnable(GL_POLYGON_OFFSET_POINT);
|
||||||
|
glPolygonOffset(bias.x, bias.y);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glDisable(GL_POLYGON_OFFSET_LINE);
|
||||||
|
glDisable(GL_POLYGON_OFFSET_POINT);
|
||||||
|
}
|
||||||
|
_pipeline._stateCache.depthBias = bias.x;
|
||||||
|
_pipeline._stateCache.depthBiasSlopeScale = bias.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateDepthTest(State::DepthTest test) {
|
||||||
|
if (_pipeline._stateCache.depthTest != test) {
|
||||||
|
if (test.isEnabled()) {
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(test.getWriteMask());
|
||||||
|
glDepthFunc(GL_COMPARISON_FUNCTIONS[test.getFunction()]);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.depthTest = test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest) {
|
||||||
|
|
||||||
|
if ((_pipeline._stateCache.stencilActivation != activation)
|
||||||
|
|| (_pipeline._stateCache.stencilTestFront != frontTest)
|
||||||
|
|| (_pipeline._stateCache.stencilTestBack != backTest)) {
|
||||||
|
|
||||||
|
if (activation.isEnabled()) {
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront());
|
||||||
|
glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack());
|
||||||
|
|
||||||
|
static GLenum STENCIL_OPS[] = {
|
||||||
|
GL_KEEP,
|
||||||
|
GL_ZERO,
|
||||||
|
GL_REPLACE,
|
||||||
|
GL_INCR_WRAP,
|
||||||
|
GL_DECR_WRAP,
|
||||||
|
GL_INVERT,
|
||||||
|
GL_INCR,
|
||||||
|
GL_DECR };
|
||||||
|
|
||||||
|
glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]);
|
||||||
|
glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask());
|
||||||
|
|
||||||
|
glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest.getFailOp()], STENCIL_OPS[backTest.getPassOp()], STENCIL_OPS[backTest.getDepthFailOp()]);
|
||||||
|
glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest.getFunction()], backTest.getReference(), backTest.getReadMask());
|
||||||
|
} else {
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_pipeline._stateCache.stencilActivation = activation;
|
||||||
|
_pipeline._stateCache.stencilTestFront = frontTest;
|
||||||
|
_pipeline._stateCache.stencilTestBack = backTest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) {
|
||||||
|
if (_pipeline._stateCache.alphaToCoverageEnable != enable) {
|
||||||
|
if (enable) {
|
||||||
|
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
}
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
_pipeline._stateCache.alphaToCoverageEnable = enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateSampleMask(uint32 mask) {
|
||||||
|
if (_pipeline._stateCache.sampleMask != mask) {
|
||||||
|
#ifdef GPU_CORE_PROFILE
|
||||||
|
if (mask == 0xFFFFFFFF) {
|
||||||
|
glDisable(GL_SAMPLE_MASK);
|
||||||
|
} else {
|
||||||
|
glEnable(GL_SAMPLE_MASK);
|
||||||
|
glSampleMaski(0, mask);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_pipeline._stateCache.sampleMask = mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateBlend(State::BlendFunction function) {
|
||||||
|
if (_pipeline._stateCache.blendFunction != function) {
|
||||||
|
if (function.isEnabled()) {
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
static GLenum GL_BLEND_OPS[] = {
|
||||||
|
GL_FUNC_ADD,
|
||||||
|
GL_FUNC_SUBTRACT,
|
||||||
|
GL_FUNC_REVERSE_SUBTRACT,
|
||||||
|
GL_MIN,
|
||||||
|
GL_MAX };
|
||||||
|
|
||||||
|
glBlendEquationSeparate(GL_BLEND_OPS[function.getOperationColor()], GL_BLEND_OPS[function.getOperationAlpha()]);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
static GLenum BLEND_ARGS[] = {
|
||||||
|
GL_ZERO,
|
||||||
|
GL_ONE,
|
||||||
|
GL_SRC_COLOR,
|
||||||
|
GL_ONE_MINUS_SRC_COLOR,
|
||||||
|
GL_SRC_ALPHA,
|
||||||
|
GL_ONE_MINUS_SRC_ALPHA,
|
||||||
|
GL_DST_ALPHA,
|
||||||
|
GL_ONE_MINUS_DST_ALPHA,
|
||||||
|
GL_DST_COLOR,
|
||||||
|
GL_ONE_MINUS_DST_COLOR,
|
||||||
|
GL_SRC_ALPHA_SATURATE,
|
||||||
|
GL_CONSTANT_COLOR,
|
||||||
|
GL_ONE_MINUS_CONSTANT_COLOR,
|
||||||
|
GL_CONSTANT_ALPHA,
|
||||||
|
GL_ONE_MINUS_CONSTANT_ALPHA,
|
||||||
|
};
|
||||||
|
|
||||||
|
glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()],
|
||||||
|
BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
} else {
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pipeline._stateCache.blendFunction = function;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setStateColorWriteMask(uint32 mask) {
|
||||||
|
if (_pipeline._stateCache.colorWriteMask = mask) {
|
||||||
|
glColorMask(mask & State::ColorMask::WRITE_RED,
|
||||||
|
mask & State::ColorMask::WRITE_GREEN,
|
||||||
|
mask & State::ColorMask::WRITE_BLUE,
|
||||||
|
mask & State::ColorMask::WRITE_ALPHA );
|
||||||
|
|
||||||
|
_pipeline._stateCache.colorWriteMask = mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLBackend::do_setStateBlendFactor(Batch& batch, uint32 paramOffset) {
|
||||||
|
|
||||||
|
Vec4 factor(batch._params[paramOffset + 0]._float,
|
||||||
|
batch._params[paramOffset + 1]._float,
|
||||||
|
batch._params[paramOffset + 2]._float,
|
||||||
|
batch._params[paramOffset + 3]._float);
|
||||||
|
|
||||||
|
glBlendColor(factor.x, factor.y, factor.z, factor.w);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ using namespace gpu;
|
||||||
|
|
||||||
Pipeline::Pipeline():
|
Pipeline::Pipeline():
|
||||||
_program(),
|
_program(),
|
||||||
_states()
|
_state()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,10 +25,10 @@ Pipeline::~Pipeline()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Pipeline* Pipeline::create(const ShaderPointer& program, const States& states) {
|
Pipeline* Pipeline::create(const ShaderPointer& program, const StatePointer& state) {
|
||||||
Pipeline* pipeline = new Pipeline();
|
Pipeline* pipeline = new Pipeline();
|
||||||
pipeline->_program = program;
|
pipeline->_program = program;
|
||||||
pipeline->_states = states;
|
pipeline->_state = state;
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,23 +22,23 @@ namespace gpu {
|
||||||
|
|
||||||
class Pipeline {
|
class Pipeline {
|
||||||
public:
|
public:
|
||||||
static Pipeline* create(const ShaderPointer& program, const States& states);
|
static Pipeline* create(const ShaderPointer& program, const StatePointer& state);
|
||||||
~Pipeline();
|
~Pipeline();
|
||||||
|
|
||||||
const ShaderPointer& getProgram() const { return _program; }
|
const ShaderPointer& getProgram() const { return _program; }
|
||||||
|
|
||||||
const States& getStates() const { return _states; }
|
const StatePointer& getState() const { return _state; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ShaderPointer _program;
|
ShaderPointer _program;
|
||||||
States _states;
|
StatePointer _state;
|
||||||
|
|
||||||
Pipeline();
|
Pipeline();
|
||||||
Pipeline(const Pipeline& pipeline); // deep copy of the sysmem shader
|
Pipeline(const Pipeline& pipeline); // deep copy of the sysmem shader
|
||||||
Pipeline& operator=(const Pipeline& pipeline); // deep copy of the sysmem texture
|
Pipeline& operator=(const Pipeline& pipeline); // deep copy of the sysmem texture
|
||||||
|
|
||||||
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
||||||
mutable GPUObject* _gpuObject = NULL;
|
mutable GPUObject* _gpuObject = nullptr;
|
||||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||||
GPUObject* getGPUObject() const { return _gpuObject; }
|
GPUObject* getGPUObject() const { return _gpuObject; }
|
||||||
friend class Backend;
|
friend class Backend;
|
||||||
|
|
|
@ -24,10 +24,6 @@
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
class GPUObject;
|
|
||||||
|
|
||||||
typedef int Stamp;
|
|
||||||
|
|
||||||
class Resource {
|
class Resource {
|
||||||
public:
|
public:
|
||||||
typedef unsigned char Byte;
|
typedef unsigned char Byte;
|
||||||
|
|
|
@ -14,7 +14,73 @@
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
|
||||||
|
State::State() {
|
||||||
State::~State()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State::~State() {
|
||||||
|
}
|
||||||
|
|
||||||
|
const State::Data State::DEFAULT = State::Data();
|
||||||
|
|
||||||
|
State::Signature State::evalSignature(const Data& state) {
|
||||||
|
Signature signature(0);
|
||||||
|
|
||||||
|
if (state.fillMode != State::DEFAULT.fillMode) {
|
||||||
|
signature.set(State::FILL_MODE);
|
||||||
|
}
|
||||||
|
if (state.cullMode != State::DEFAULT.cullMode) {
|
||||||
|
signature.set(State::CULL_MODE);
|
||||||
|
}
|
||||||
|
if (state.frontFaceClockwise != State::DEFAULT.frontFaceClockwise) {
|
||||||
|
signature.set(State::FRONT_FACE_CLOCKWISE);
|
||||||
|
}
|
||||||
|
if (state.depthClipEnable != State::DEFAULT.depthClipEnable) {
|
||||||
|
signature.set(State::DEPTH_CLIP_ENABLE);
|
||||||
|
}
|
||||||
|
if (state.scissorEnable != State::DEFAULT.scissorEnable) {
|
||||||
|
signature.set(State::SCISSOR_ENABLE);
|
||||||
|
}
|
||||||
|
if (state.multisampleEnable != State::DEFAULT.multisampleEnable) {
|
||||||
|
signature.set(State::MULTISAMPLE_ENABLE);
|
||||||
|
}
|
||||||
|
if (state.antialisedLineEnable != State::DEFAULT.antialisedLineEnable) {
|
||||||
|
signature.set(State::ANTIALISED_LINE_ENABLE);
|
||||||
|
}
|
||||||
|
if (state.depthBias != State::DEFAULT.depthBias) {
|
||||||
|
signature.set(State::DEPTH_BIAS);
|
||||||
|
}
|
||||||
|
if (state.depthBiasSlopeScale != State::DEFAULT.depthBiasSlopeScale) {
|
||||||
|
signature.set(State::DEPTH_BIAS_SLOPE_SCALE);
|
||||||
|
}
|
||||||
|
if (state.depthTest != State::DEFAULT.depthTest) {
|
||||||
|
signature.set(State::DEPTH_TEST);
|
||||||
|
}
|
||||||
|
if (state.stencilActivation != State::DEFAULT.stencilActivation) {
|
||||||
|
signature.set(State::STENCIL_ACTIVATION);
|
||||||
|
}
|
||||||
|
if (state.stencilTestFront != State::DEFAULT.stencilTestFront) {
|
||||||
|
signature.set(State::STENCIL_TEST_FRONT);
|
||||||
|
}
|
||||||
|
if (state.stencilTestBack != State::DEFAULT.stencilTestBack) {
|
||||||
|
signature.set(State::STENCIL_TEST_BACK);
|
||||||
|
}
|
||||||
|
if (state.sampleMask != State::DEFAULT.sampleMask) {
|
||||||
|
signature.set(State::SAMPLE_MASK);
|
||||||
|
}
|
||||||
|
if (state.alphaToCoverageEnable != State::DEFAULT.alphaToCoverageEnable) {
|
||||||
|
signature.set(State::ALPHA_TO_COVERAGE_ENABLE);
|
||||||
|
}
|
||||||
|
if (state.blendFunction != State::DEFAULT.blendFunction) {
|
||||||
|
signature.set(State::BLEND_FUNCTION);
|
||||||
|
}
|
||||||
|
if (state.colorWriteMask != State::DEFAULT.colorWriteMask) {
|
||||||
|
signature.set(State::COLOR_WRITE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
State::State(const Data& values) :
|
||||||
|
_values(values) {
|
||||||
|
_signature = evalSignature(_values);
|
||||||
|
}
|
||||||
|
|
|
@ -1,88 +1,418 @@
|
||||||
//
|
//
|
||||||
// Pipeline.h
|
// State
|
||||||
// libraries/gpu/src/gpu
|
// libraries/gpu/src/gpu
|
||||||
//
|
//
|
||||||
// Created by Sam Gateau on 3/8/2015.
|
// Created by Sam Gateau on 3/8/2015.
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
#ifndef hifi_gpu_State_h
|
#ifndef hifi_gpu_State_h
|
||||||
#define hifi_gpu_State_h
|
#define hifi_gpu_State_h
|
||||||
|
|
||||||
#include "Format.h"
|
#include "Format.h"
|
||||||
#include <vector>
|
|
||||||
#include <QSharedPointer>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
namespace gpu {
|
#include <bitset>
|
||||||
|
|
||||||
class GPUObject;
|
// Why a macro and not a fancy template you will ask me ?
|
||||||
|
// Because some of the fields are bool packed tightly in the State::Cache class
|
||||||
class State {
|
// and it s just not good anymore for template T& variable manipulation...
|
||||||
public:
|
#define SET_FIELD(field, defaultValue, value, dest) {\
|
||||||
State() {}
|
dest = value;\
|
||||||
virtual ~State();
|
if (value == defaultValue) {\
|
||||||
|
_signature.reset(field);\
|
||||||
// Work in progress, not used
|
} else {\
|
||||||
/*
|
_signature.set(field);\
|
||||||
enum Field {
|
}\
|
||||||
FILL_MODE,
|
_stamp++;\
|
||||||
CULL_MODE,
|
}\
|
||||||
DEPTH_BIAS,
|
|
||||||
DEPTH_BIAS_CLAMP,
|
|
||||||
DEPTH_BIASSLOPE_SCALE,
|
namespace gpu {
|
||||||
|
|
||||||
FRONT_CLOCKWISE,
|
class GPUObject;
|
||||||
DEPTH_CLIP_ENABLE,
|
|
||||||
SCISSR_ENABLE,
|
class State {
|
||||||
MULTISAMPLE_ENABLE,
|
public:
|
||||||
ANTIALISED_LINE_ENABLE,
|
State();
|
||||||
|
virtual ~State();
|
||||||
DEPTH_ENABLE,
|
|
||||||
DEPTH_WRITE_MASK,
|
const Stamp getStamp() const { return _stamp; }
|
||||||
DEPTH_FUNCTION,
|
|
||||||
|
enum ComparisonFunction {
|
||||||
STENCIL_ENABLE,
|
NEVER = 0,
|
||||||
STENCIL_READ_MASK,
|
LESS,
|
||||||
STENCIL_WRITE_MASK,
|
EQUAL,
|
||||||
STENCIL_FUNCTION_FRONT,
|
LESS_EQUAL,
|
||||||
STENCIL_FUNCTION_BACK,
|
GREATER,
|
||||||
STENCIL_REFERENCE,
|
NOT_EQUAL,
|
||||||
|
GREATER_EQUAL,
|
||||||
BLEND_INDEPENDANT_ENABLE,
|
ALWAYS,
|
||||||
BLEND_ENABLE,
|
|
||||||
BLEND_SOURCE,
|
NUM_COMPARISON_FUNCS,
|
||||||
BLEND_DESTINATION,
|
};
|
||||||
BLEND_OPERATION,
|
|
||||||
BLEND_SOURCE_ALPHA,
|
enum FillMode {
|
||||||
BLEND_DESTINATION_ALPHA,
|
FILL_POINT = 0,
|
||||||
BLEND_OPERATION_ALPHA,
|
FILL_LINE,
|
||||||
BLEND_WRITE_MASK,
|
FILL_FACE,
|
||||||
BLEND_FACTOR,
|
|
||||||
|
NUM_FILL_MODES,
|
||||||
SAMPLE_MASK,
|
};
|
||||||
|
|
||||||
ALPHA_TO_COVERAGE_ENABLE,
|
enum CullMode {
|
||||||
};
|
CULL_NONE = 0,
|
||||||
*/
|
CULL_FRONT,
|
||||||
|
CULL_BACK,
|
||||||
protected:
|
|
||||||
State(const State& state);
|
NUM_CULL_MODES,
|
||||||
State& operator=(const State& state);
|
};
|
||||||
|
|
||||||
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
enum StencilOp {
|
||||||
mutable GPUObject* _gpuObject = NULL;
|
STENCIL_OP_KEEP = 0,
|
||||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
STENCIL_OP_ZERO,
|
||||||
GPUObject* getGPUObject() const { return _gpuObject; }
|
STENCIL_OP_REPLACE,
|
||||||
friend class Backend;
|
STENCIL_OP_INCR_SAT,
|
||||||
};
|
STENCIL_OP_DECR_SAT,
|
||||||
|
STENCIL_OP_INVERT,
|
||||||
typedef QSharedPointer< State > StatePointer;
|
STENCIL_OP_INCR,
|
||||||
typedef std::vector< StatePointer > States;
|
STENCIL_OP_DECR,
|
||||||
|
|
||||||
};
|
NUM_STENCIL_OPS,
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
enum BlendArg {
|
||||||
|
ZERO = 0,
|
||||||
|
ONE,
|
||||||
|
SRC_COLOR,
|
||||||
|
INV_SRC_COLOR,
|
||||||
|
SRC_ALPHA,
|
||||||
|
INV_SRC_ALPHA,
|
||||||
|
DEST_ALPHA,
|
||||||
|
INV_DEST_ALPHA,
|
||||||
|
DEST_COLOR,
|
||||||
|
INV_DEST_COLOR,
|
||||||
|
SRC_ALPHA_SAT,
|
||||||
|
FACTOR_COLOR,
|
||||||
|
INV_FACTOR_COLOR,
|
||||||
|
FACTOR_ALPHA,
|
||||||
|
INV_FACTOR_ALPHA,
|
||||||
|
|
||||||
|
NUM_BLEND_ARGS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BlendOp {
|
||||||
|
BLEND_OP_ADD = 0,
|
||||||
|
BLEND_OP_SUBTRACT,
|
||||||
|
BLEND_OP_REV_SUBTRACT,
|
||||||
|
BLEND_OP_MIN,
|
||||||
|
BLEND_OP_MAX,
|
||||||
|
|
||||||
|
NUM_BLEND_OPS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ColorMask
|
||||||
|
{
|
||||||
|
WRITE_NONE = 0,
|
||||||
|
WRITE_RED = 1,
|
||||||
|
WRITE_GREEN = 2,
|
||||||
|
WRITE_BLUE = 4,
|
||||||
|
WRITE_ALPHA = 8,
|
||||||
|
WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ),
|
||||||
|
};
|
||||||
|
|
||||||
|
class DepthTest {
|
||||||
|
uint8 _function = LESS;
|
||||||
|
bool _writeMask = true;
|
||||||
|
bool _enabled = false;
|
||||||
|
public:
|
||||||
|
DepthTest(bool enabled, bool writeMask, ComparisonFunction func) :
|
||||||
|
_function(func), _writeMask(writeMask), _enabled(enabled) {}
|
||||||
|
|
||||||
|
bool isEnabled() const { return _enabled; }
|
||||||
|
ComparisonFunction getFunction() const { return ComparisonFunction(_function); }
|
||||||
|
bool getWriteMask() const { return _writeMask; }
|
||||||
|
|
||||||
|
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
|
||||||
|
DepthTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
|
||||||
|
bool operator== (const DepthTest& right) const { return getRaw() == right.getRaw(); }
|
||||||
|
bool operator!= (const DepthTest& right) const { return getRaw() != right.getRaw(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class StencilTest {
|
||||||
|
static const int FUNC_MASK = 0x000f;
|
||||||
|
static const int FAIL_OP_MASK = 0x00f0;
|
||||||
|
static const int DEPTH_FAIL_OP_MASK = 0x0f00;
|
||||||
|
static const int PASS_OP_MASK = 0xf000;
|
||||||
|
static const int FAIL_OP_OFFSET = 4;
|
||||||
|
static const int DEPTH_FAIL_OP_OFFSET = 8;
|
||||||
|
static const int PASS_OP_OFFSET = 12;
|
||||||
|
|
||||||
|
uint16 _functionAndOperations;
|
||||||
|
uint8 _reference = 0;
|
||||||
|
uint8 _readMask = 0xff;
|
||||||
|
public:
|
||||||
|
|
||||||
|
StencilTest(uint8 reference = 0, uint8 readMask =0xFF, ComparisonFunction func = ALWAYS, StencilOp failOp = STENCIL_OP_KEEP, StencilOp depthFailOp = STENCIL_OP_KEEP, StencilOp passOp = STENCIL_OP_KEEP) :
|
||||||
|
_functionAndOperations(func | (failOp << FAIL_OP_OFFSET) | (depthFailOp << DEPTH_FAIL_OP_OFFSET) | (passOp << PASS_OP_OFFSET)),
|
||||||
|
_reference(reference), _readMask(readMask)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ComparisonFunction getFunction() const { return ComparisonFunction(_functionAndOperations & FUNC_MASK); }
|
||||||
|
StencilOp getFailOp() const { return StencilOp((_functionAndOperations & FAIL_OP_MASK) >> FAIL_OP_OFFSET); }
|
||||||
|
StencilOp getDepthFailOp() const { return StencilOp((_functionAndOperations & DEPTH_FAIL_OP_MASK) >> DEPTH_FAIL_OP_OFFSET); }
|
||||||
|
StencilOp getPassOp() const { return StencilOp((_functionAndOperations & PASS_OP_MASK) >> PASS_OP_OFFSET); }
|
||||||
|
|
||||||
|
uint8 getReference() const { return _reference; }
|
||||||
|
uint8 getReadMask() const { return _readMask; }
|
||||||
|
|
||||||
|
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
|
||||||
|
StencilTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
|
||||||
|
bool operator== (const StencilTest& right) const { return getRaw() == right.getRaw(); }
|
||||||
|
bool operator!= (const StencilTest& right) const { return getRaw() != right.getRaw(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class StencilActivation {
|
||||||
|
uint8 _frontWriteMask = 0xFF;
|
||||||
|
uint8 _backWriteMask = 0xFF;
|
||||||
|
uint16 _enabled = 0;
|
||||||
|
public:
|
||||||
|
|
||||||
|
StencilActivation(bool enabled, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) :
|
||||||
|
_frontWriteMask(frontWriteMask), _backWriteMask(backWriteMask), _enabled(enabled) {}
|
||||||
|
|
||||||
|
bool isEnabled() const { return (_enabled != 0); }
|
||||||
|
uint8 getWriteMaskFront() const { return _frontWriteMask; }
|
||||||
|
uint8 getWriteMaskBack() const { return _backWriteMask; }
|
||||||
|
|
||||||
|
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
|
||||||
|
StencilActivation(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
|
||||||
|
bool operator== (const StencilActivation& right) const { return getRaw() == right.getRaw(); }
|
||||||
|
bool operator!= (const StencilActivation& right) const { return getRaw() != right.getRaw(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class BlendFunction {
|
||||||
|
static const int COLOR_MASK = 0x0f;
|
||||||
|
static const int ALPHA_MASK = 0xf0;
|
||||||
|
static const int ALPHA_OFFSET = 4;
|
||||||
|
|
||||||
|
uint8 _enabled;
|
||||||
|
uint8 _source;
|
||||||
|
uint8 _destination;
|
||||||
|
uint8 _operation;
|
||||||
|
public:
|
||||||
|
|
||||||
|
BlendFunction(bool enabled,
|
||||||
|
BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor,
|
||||||
|
BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) :
|
||||||
|
_enabled(enabled),
|
||||||
|
_source(sourceColor | (sourceAlpha << ALPHA_OFFSET)),
|
||||||
|
_destination(destinationColor | (destinationAlpha << ALPHA_OFFSET)),
|
||||||
|
_operation(operationColor | (operationAlpha << ALPHA_OFFSET)) {}
|
||||||
|
|
||||||
|
BlendFunction(bool enabled, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) :
|
||||||
|
_enabled(enabled),
|
||||||
|
_source(source | (source << ALPHA_OFFSET)),
|
||||||
|
_destination(destination | (destination << ALPHA_OFFSET)),
|
||||||
|
_operation(operation | (operation << ALPHA_OFFSET)) {}
|
||||||
|
|
||||||
|
bool isEnabled() const { return (_enabled != 0); }
|
||||||
|
|
||||||
|
BlendArg getSourceColor() const { return BlendArg(_source & COLOR_MASK); }
|
||||||
|
BlendArg getDestinationColor() const { return BlendArg(_destination & COLOR_MASK); }
|
||||||
|
BlendOp getOperationColor() const { return BlendOp(_operation & COLOR_MASK); }
|
||||||
|
|
||||||
|
BlendArg getSourceAlpha() const { return BlendArg((_source & ALPHA_MASK) >> ALPHA_OFFSET); }
|
||||||
|
BlendArg getDestinationAlpha() const { return BlendArg((_destination & ALPHA_MASK) >> ALPHA_OFFSET); }
|
||||||
|
BlendOp getOperationAlpha() const { return BlendOp((_operation & ALPHA_MASK) >> ALPHA_OFFSET); }
|
||||||
|
|
||||||
|
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
|
||||||
|
BlendFunction(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
|
||||||
|
bool operator== (const BlendFunction& right) const { return getRaw() == right.getRaw(); }
|
||||||
|
bool operator!= (const BlendFunction& right) const { return getRaw() != right.getRaw(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// The Data class is the full explicit description of the State class fields value.
|
||||||
|
// Useful for having one const static called Default for reference or for the gpu::Backend to keep track of the current value
|
||||||
|
class Data {
|
||||||
|
public:
|
||||||
|
float depthBias = 0.0f;
|
||||||
|
float depthBiasSlopeScale = 0.0f;
|
||||||
|
|
||||||
|
DepthTest depthTest = DepthTest(false, true, LESS);
|
||||||
|
|
||||||
|
StencilActivation stencilActivation = StencilActivation(false);
|
||||||
|
StencilTest stencilTestFront = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP);
|
||||||
|
StencilTest stencilTestBack = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP);
|
||||||
|
|
||||||
|
uint32 sampleMask = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
BlendFunction blendFunction = BlendFunction(false);
|
||||||
|
|
||||||
|
uint8 fillMode = FILL_FACE;
|
||||||
|
uint8 cullMode = CULL_NONE;
|
||||||
|
|
||||||
|
uint8 colorWriteMask = WRITE_ALL;
|
||||||
|
|
||||||
|
bool frontFaceClockwise : 1;
|
||||||
|
bool depthClipEnable : 1;
|
||||||
|
bool scissorEnable : 1;
|
||||||
|
bool multisampleEnable : 1;
|
||||||
|
bool antialisedLineEnable : 1;
|
||||||
|
bool alphaToCoverageEnable : 1;
|
||||||
|
|
||||||
|
Data() :
|
||||||
|
frontFaceClockwise(false),
|
||||||
|
depthClipEnable(false),
|
||||||
|
scissorEnable(false),
|
||||||
|
multisampleEnable(false),
|
||||||
|
antialisedLineEnable(false),
|
||||||
|
alphaToCoverageEnable(false)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The unique default values for all the fields
|
||||||
|
static const Data DEFAULT;
|
||||||
|
void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, DEFAULT.fillMode, fill, _values.fillMode); }
|
||||||
|
FillMode getFillMode() const { return FillMode(_values.fillMode); }
|
||||||
|
|
||||||
|
void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, DEFAULT.cullMode, cull, _values.cullMode); }
|
||||||
|
CullMode getCullMode() const { return CullMode(_values.cullMode); }
|
||||||
|
|
||||||
|
void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise, _values.frontFaceClockwise); }
|
||||||
|
bool isFrontFaceClockwise() const { return _values.frontFaceClockwise; }
|
||||||
|
|
||||||
|
void setDepthClipEnable(bool enable) { SET_FIELD(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable, enable, _values.depthClipEnable); }
|
||||||
|
bool isDepthClipEnable() const { return _values.depthClipEnable; }
|
||||||
|
|
||||||
|
void setScissorEnable(bool enable) { SET_FIELD(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable, _values.scissorEnable); }
|
||||||
|
bool isScissorEnable() const { return _values.scissorEnable; }
|
||||||
|
|
||||||
|
void setMultisampleEnable(bool enable) { SET_FIELD(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable, _values.multisampleEnable); }
|
||||||
|
bool isMultisampleEnable() const { return _values.multisampleEnable; }
|
||||||
|
|
||||||
|
void setAntialiasedLineEnable(bool enable) { SET_FIELD(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable, _values.antialisedLineEnable); }
|
||||||
|
bool isAntialiasedLineEnable() const { return _values.antialisedLineEnable; }
|
||||||
|
|
||||||
|
// Depth Bias
|
||||||
|
void setDepthBias(float bias) { SET_FIELD(DEPTH_BIAS, DEFAULT.depthBias, bias, _values.depthBias); }
|
||||||
|
float getDepthBias() const { return _values.depthBias; }
|
||||||
|
|
||||||
|
void setDepthBiasSlopeScale(float scale) { SET_FIELD(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale, _values.depthBiasSlopeScale); }
|
||||||
|
float getDepthBiasSlopeScale() const { return _values.depthBiasSlopeScale; }
|
||||||
|
|
||||||
|
// Depth Test
|
||||||
|
void setDepthTest(DepthTest depthTest) { SET_FIELD(DEPTH_TEST, DEFAULT.depthTest, depthTest, _values.depthTest); }
|
||||||
|
void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); }
|
||||||
|
DepthTest getDepthTest() const { return _values.depthTest; }
|
||||||
|
|
||||||
|
bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); }
|
||||||
|
bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); }
|
||||||
|
ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); }
|
||||||
|
|
||||||
|
// Stencil test
|
||||||
|
void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) {
|
||||||
|
SET_FIELD(STENCIL_ACTIVATION, DEFAULT.stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask), _values.stencilActivation);
|
||||||
|
SET_FIELD(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest, _values.stencilTestFront);
|
||||||
|
SET_FIELD(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest, _values.stencilTestBack); }
|
||||||
|
void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) {
|
||||||
|
setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); }
|
||||||
|
|
||||||
|
StencilActivation getStencilActivation() const { return _values.stencilActivation; }
|
||||||
|
StencilTest getStencilTestFront() const { return _values.stencilTestFront; }
|
||||||
|
StencilTest getStencilTestBack() const { return _values.stencilTestBack; }
|
||||||
|
|
||||||
|
bool isStencilEnabled() const { return getStencilActivation().isEnabled(); }
|
||||||
|
uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); }
|
||||||
|
uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); }
|
||||||
|
|
||||||
|
// Alpha to coverage
|
||||||
|
void setAlphaToCoverageEnable(bool enable) { SET_FIELD(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable, _values.alphaToCoverageEnable); }
|
||||||
|
bool isAlphaToCoverageEnabled() const { return _values.alphaToCoverageEnable; }
|
||||||
|
|
||||||
|
// Sample mask
|
||||||
|
void setSampleMask(uint32 mask) { SET_FIELD(SAMPLE_MASK, DEFAULT.sampleMask, mask, _values.sampleMask); }
|
||||||
|
uint32 getSampleMask() const { return _values.sampleMask; }
|
||||||
|
|
||||||
|
// Blend Function
|
||||||
|
void setBlendFunction(BlendFunction function) { SET_FIELD(BLEND_FUNCTION, DEFAULT.blendFunction, function, _values.blendFunction); }
|
||||||
|
BlendFunction getBlendFunction() const { return _values.blendFunction; }
|
||||||
|
|
||||||
|
void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) {
|
||||||
|
setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); }
|
||||||
|
void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) {
|
||||||
|
setBlendFunction(BlendFunction(enabled, source, operation, destination)); }
|
||||||
|
|
||||||
|
bool isBlendEnabled() const { return getBlendFunction().isEnabled(); }
|
||||||
|
|
||||||
|
// Color write mask
|
||||||
|
void setColorWriteMask(uint8 mask) { SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask, _values.colorWriteMask); }
|
||||||
|
uint8 getColorWriteMask() const { return _values.colorWriteMask; }
|
||||||
|
|
||||||
|
// All the possible fields
|
||||||
|
enum Field {
|
||||||
|
FILL_MODE,
|
||||||
|
CULL_MODE,
|
||||||
|
FRONT_FACE_CLOCKWISE,
|
||||||
|
DEPTH_CLIP_ENABLE,
|
||||||
|
SCISSOR_ENABLE,
|
||||||
|
MULTISAMPLE_ENABLE,
|
||||||
|
ANTIALISED_LINE_ENABLE,
|
||||||
|
|
||||||
|
DEPTH_BIAS,
|
||||||
|
DEPTH_BIAS_SLOPE_SCALE,
|
||||||
|
|
||||||
|
DEPTH_TEST,
|
||||||
|
|
||||||
|
STENCIL_ACTIVATION,
|
||||||
|
STENCIL_TEST_FRONT,
|
||||||
|
STENCIL_TEST_BACK,
|
||||||
|
|
||||||
|
SAMPLE_MASK,
|
||||||
|
ALPHA_TO_COVERAGE_ENABLE,
|
||||||
|
|
||||||
|
BLEND_FUNCTION,
|
||||||
|
|
||||||
|
COLOR_WRITE_MASK,
|
||||||
|
|
||||||
|
NUM_FIELDS, // not a valid field, just the count
|
||||||
|
};
|
||||||
|
|
||||||
|
// The signature of the state tells which fields of the state are not default
|
||||||
|
// this way during rendering the Backend can compare it's current state and try to minimize the job to do
|
||||||
|
typedef std::bitset<NUM_FIELDS> Signature;
|
||||||
|
|
||||||
|
Signature getSignature() const { return _signature; }
|
||||||
|
|
||||||
|
static Signature evalSignature(const Data& state);
|
||||||
|
|
||||||
|
// For convenience, create a State from the values directly
|
||||||
|
State(const Data& values);
|
||||||
|
const Data& getValues() const { return _values; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
State(const State& state);
|
||||||
|
State& operator=(const State& state);
|
||||||
|
|
||||||
|
Data _values;
|
||||||
|
Signature _signature{0};
|
||||||
|
Stamp _stamp{0};
|
||||||
|
|
||||||
|
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
||||||
|
mutable GPUObject* _gpuObject = nullptr;
|
||||||
|
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||||
|
GPUObject* getGPUObject() const { return _gpuObject; }
|
||||||
|
friend class Backend;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr< State > StatePointer;
|
||||||
|
typedef std::vector< StatePointer > States;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -184,6 +184,14 @@ void Atmosphere::setInnerOuterRadiuses(float inner, float outer) {
|
||||||
data._scales.z = data._scales.x / data._scales.y;
|
data._scales.z = data._scales.x / data._scales.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Skybox::Skybox() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skybox::setCubemap(const gpu::TexturePointer& cubemap) {
|
||||||
|
_cubemap = cubemap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const int NUM_DAYS_PER_YEAR = 365;
|
const int NUM_DAYS_PER_YEAR = 365;
|
||||||
const float NUM_HOURS_PER_DAY = 24.0f;
|
const float NUM_HOURS_PER_DAY = 24.0f;
|
||||||
|
@ -207,7 +215,12 @@ SunSkyStage::SunSkyStage() :
|
||||||
auto skyFromAtmosphereVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert)));
|
auto skyFromAtmosphereVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert)));
|
||||||
auto skyFromAtmosphereFragment = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag)));
|
auto skyFromAtmosphereFragment = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag)));
|
||||||
auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment));
|
auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment));
|
||||||
_skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, gpu::States()));
|
|
||||||
|
auto skyState = gpu::StatePointer(new gpu::State());
|
||||||
|
// skyState->setStencilEnable(false);
|
||||||
|
// skyState->setBlendEnable(false);
|
||||||
|
|
||||||
|
_skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,3 +286,7 @@ void SunSkyStage::updateGraphicsObject() const {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SunSkyStage::setSkybox(const SkyboxPointer& skybox) {
|
||||||
|
_skybox = skybox;
|
||||||
|
invalidate();
|
||||||
|
}
|
|
@ -160,6 +160,21 @@ protected:
|
||||||
};
|
};
|
||||||
typedef QSharedPointer< Atmosphere > AtmospherePointer;
|
typedef QSharedPointer< Atmosphere > AtmospherePointer;
|
||||||
|
|
||||||
|
|
||||||
|
class Skybox {
|
||||||
|
public:
|
||||||
|
Skybox();
|
||||||
|
Skybox& operator= (const Atmosphere& Skybox);
|
||||||
|
virtual ~Skybox() {};
|
||||||
|
|
||||||
|
void setCubemap(const gpu::TexturePointer& cubemap);
|
||||||
|
const gpu::TexturePointer& getCubemap() const { return _cubemap; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
gpu::TexturePointer _cubemap;
|
||||||
|
};
|
||||||
|
typedef QSharedPointer< Skybox > SkyboxPointer;
|
||||||
|
|
||||||
// Sun sky stage generates the rendering primitives to display a scene realistically
|
// Sun sky stage generates the rendering primitives to display a scene realistically
|
||||||
// at the specified location and time around earth
|
// at the specified location and time around earth
|
||||||
class SunSkyStage {
|
class SunSkyStage {
|
||||||
|
@ -197,9 +212,14 @@ public:
|
||||||
LightPointer getSunLight() const { valid(); return _sunLight; }
|
LightPointer getSunLight() const { valid(); return _sunLight; }
|
||||||
AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; }
|
AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; }
|
||||||
|
|
||||||
|
// Skybox
|
||||||
|
void setSkybox(const SkyboxPointer& skybox);
|
||||||
|
const SkyboxPointer& getSkybox() const { valid(); return _skybox; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LightPointer _sunLight;
|
LightPointer _sunLight;
|
||||||
AtmospherePointer _atmosphere;
|
AtmospherePointer _atmosphere;
|
||||||
|
SkyboxPointer _skybox;
|
||||||
|
|
||||||
gpu::PipelinePointer _skyPipeline;
|
gpu::PipelinePointer _skyPipeline;
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,19 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
|
void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
|
||||||
|
if (alpha != glowIntensity) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
gl_FragData[0] = vec4(diffuse.rgb, alpha);
|
gl_FragData[0] = vec4(diffuse.rgb, alpha);
|
||||||
gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
gl_FragData[2] = vec4(specular, shininess / 128.0);
|
gl_FragData[2] = vec4(specular, shininess / 128.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) {
|
void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) {
|
||||||
|
if (alpha != glowIntensity) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
gl_FragData[0] = vec4(diffuse.rgb, alpha);
|
gl_FragData[0] = vec4(diffuse.rgb, alpha);
|
||||||
//gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
//gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);
|
gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);
|
||||||
|
@ -35,6 +42,10 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s
|
||||||
}
|
}
|
||||||
|
|
||||||
void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
|
void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
|
||||||
|
if (alpha <= alphaThreshold) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
gl_FragData[0] = vec4(diffuse.rgb, alpha);
|
gl_FragData[0] = vec4(diffuse.rgb, alpha);
|
||||||
// gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
// gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
// gl_FragData[2] = vec4(specular, shininess / 128.0);
|
// gl_FragData[2] = vec4(specular, shininess / 128.0);
|
||||||
|
|
|
@ -28,21 +28,23 @@ struct SphericalHarmonics {
|
||||||
|
|
||||||
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
|
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
|
||||||
|
|
||||||
|
vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis?
|
||||||
|
|
||||||
const float C1 = 0.429043;
|
const float C1 = 0.429043;
|
||||||
const float C2 = 0.511664;
|
const float C2 = 0.511664;
|
||||||
const float C3 = 0.743125;
|
const float C3 = 0.743125;
|
||||||
const float C4 = 0.886227;
|
const float C4 = 0.886227;
|
||||||
const float C5 = 0.247708;
|
const float C5 = 0.247708;
|
||||||
|
|
||||||
vec4 value = C1 * sh.L22 * (direction.x * direction.x - direction.y * direction.y) +
|
vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +
|
||||||
C3 * sh.L20 * direction.z * direction.z +
|
C3 * sh.L20 * dir.z * dir.z +
|
||||||
C4 * sh.L00 - C5 * sh.L20 +
|
C4 * sh.L00 - C5 * sh.L20 +
|
||||||
2.0 * C1 * ( sh.L2m2 * direction.x * direction.y +
|
2.0 * C1 * ( sh.L2m2 * dir.x * dir.y +
|
||||||
sh.L21 * direction.x * direction.z +
|
sh.L21 * dir.x * dir.z +
|
||||||
sh.L2m1 * direction.y * direction.z ) +
|
sh.L2m1 * dir.y * dir.z ) +
|
||||||
2.0 * C2 * ( sh.L11 * direction.x +
|
2.0 * C2 * ( sh.L11 * dir.x +
|
||||||
sh.L1m1 * direction.y +
|
sh.L1m1 * dir.y +
|
||||||
sh.L10 * direction.z ) ;
|
sh.L10 * dir.z ) ;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,15 +77,12 @@ vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal,
|
||||||
vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
||||||
// Need the light now
|
// Need the light now
|
||||||
Light light = getLight();
|
Light light = getLight();
|
||||||
|
|
||||||
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
|
vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0)));
|
||||||
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
||||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||||
|
|
||||||
// TODO: The world space normal doesn;t seem to work properly with the current SH definitions
|
vec3 ambientNormal = fragNormal.xyz;
|
||||||
// FoOr now, we use the normal in view space
|
|
||||||
vec3 ambientNormal = normal;
|
|
||||||
|
|
||||||
vec3 color = diffuse.rgb * 0.5 * evalSphericalLight(ambientSphere, ambientNormal).xyz;
|
vec3 color = diffuse.rgb * 0.5 * evalSphericalLight(ambientSphere, ambientNormal).xyz;
|
||||||
|
|
||||||
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||||
|
|
|
@ -551,3 +551,7 @@ void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const gl
|
||||||
light->setColor(diffuse);
|
light->setColor(diffuse);
|
||||||
light->setIntensity(intensity);
|
light->setIntensity(intensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) {
|
||||||
|
_skybox = skybox;
|
||||||
|
}
|
|
@ -76,6 +76,7 @@ public:
|
||||||
void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity);
|
void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity);
|
||||||
void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; }
|
void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; }
|
||||||
|
|
||||||
|
void setGlobalSkybox(const model::SkyboxPointer& skybox);
|
||||||
private:
|
private:
|
||||||
DeferredLightingEffect() {}
|
DeferredLightingEffect() {}
|
||||||
virtual ~DeferredLightingEffect() { }
|
virtual ~DeferredLightingEffect() { }
|
||||||
|
@ -150,6 +151,7 @@ private:
|
||||||
|
|
||||||
int _ambientLightMode = 0;
|
int _ambientLightMode = 0;
|
||||||
model::AtmospherePointer _atmosphere;
|
model::AtmospherePointer _atmosphere;
|
||||||
|
model::SkyboxPointer _skybox;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Simple interface for objects that require something to be rendered after deferred lighting.
|
/// Simple interface for objects that require something to be rendered after deferred lighting.
|
||||||
|
|
|
@ -96,50 +96,89 @@ Model::~Model() {
|
||||||
deleteGeometry();
|
deleteGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::ShaderPointer Model::_program;
|
Model::RenderPipelineLib Model::_renderPipelineLib;
|
||||||
gpu::ShaderPointer Model::_normalMapProgram;
|
const GLint MATERIAL_GPU_SLOT = 3;
|
||||||
gpu::ShaderPointer Model::_specularMapProgram;
|
|
||||||
gpu::ShaderPointer Model::_normalSpecularMapProgram;
|
|
||||||
gpu::ShaderPointer Model::_translucentProgram;
|
|
||||||
|
|
||||||
gpu::ShaderPointer Model::_lightmapProgram;
|
void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
|
||||||
gpu::ShaderPointer Model::_lightmapNormalMapProgram;
|
gpu::ShaderPointer& vertexShader,
|
||||||
gpu::ShaderPointer Model::_lightmapSpecularMapProgram;
|
gpu::ShaderPointer& pixelShader ) {
|
||||||
gpu::ShaderPointer Model::_lightmapNormalSpecularMapProgram;
|
|
||||||
|
|
||||||
gpu::ShaderPointer Model::_shadowProgram;
|
gpu::Shader::BindingSet slotBindings;
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0));
|
||||||
|
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));
|
||||||
|
|
||||||
gpu::ShaderPointer Model::_skinProgram;
|
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));
|
||||||
gpu::ShaderPointer Model::_skinNormalMapProgram;
|
bool makeResult = gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
gpu::ShaderPointer Model::_skinSpecularMapProgram;
|
|
||||||
gpu::ShaderPointer Model::_skinNormalSpecularMapProgram;
|
|
||||||
gpu::ShaderPointer Model::_skinTranslucentProgram;
|
auto locations = std::shared_ptr<Locations>(new Locations());
|
||||||
|
initLocations(program, *locations);
|
||||||
|
|
||||||
gpu::ShaderPointer Model::_skinShadowProgram;
|
|
||||||
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
|
|
||||||
Model::Locations Model::_locations;
|
// Backface on shadow
|
||||||
Model::Locations Model::_normalMapLocations;
|
if (key.isShadow()) {
|
||||||
Model::Locations Model::_specularMapLocations;
|
state->setCullMode(gpu::State::CULL_FRONT);
|
||||||
Model::Locations Model::_normalSpecularMapLocations;
|
state->setDepthBias(1.0f);
|
||||||
Model::Locations Model::_translucentLocations;
|
state->setDepthBiasSlopeScale(4.0f);
|
||||||
Model::Locations Model::_shadowLocations;
|
} else {
|
||||||
|
state->setCullMode(gpu::State::CULL_BACK);
|
||||||
|
}
|
||||||
|
|
||||||
Model::Locations Model::_lightmapLocations;
|
// Z test depends if transparent or not
|
||||||
Model::Locations Model::_lightmapNormalMapLocations;
|
state->setDepthTest(true, !key.isTranslucent(), gpu::State::LESS_EQUAL);
|
||||||
Model::Locations Model::_lightmapSpecularMapLocations;
|
|
||||||
Model::Locations Model::_lightmapNormalSpecularMapLocations;
|
// Blend on transparent
|
||||||
|
state->setBlendFunction(key.isTranslucent(),
|
||||||
|
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||||
|
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||||
|
|
||||||
|
// Good to go add the brand new pipeline
|
||||||
|
auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
|
||||||
|
auto it = insert(value_type(key.getRaw(), RenderPipeline(pipeline, locations)));
|
||||||
|
|
||||||
|
// If not a shadow pass, create the mirror version from the same state, just change the FrontFace
|
||||||
|
if (!key.isShadow()) {
|
||||||
|
|
||||||
|
RenderKey mirrorKey(key.getRaw() | RenderKey::IS_MIRROR);
|
||||||
|
gpu::StatePointer mirrorState = gpu::StatePointer(new gpu::State(state->getValues()));
|
||||||
|
|
||||||
|
mirrorState->setFrontFaceClockwise(true);
|
||||||
|
|
||||||
|
// create a new RenderPipeline with the same shader side and the mirrorState
|
||||||
|
auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState));
|
||||||
|
auto it = insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Model::SkinLocations Model::_skinLocations;
|
void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model::Locations& locations) {
|
||||||
Model::SkinLocations Model::_skinNormalMapLocations;
|
locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold");
|
||||||
Model::SkinLocations Model::_skinSpecularMapLocations;
|
locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices");
|
||||||
Model::SkinLocations Model::_skinNormalSpecularMapLocations;
|
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
|
||||||
Model::SkinLocations Model::_skinTranslucentLocations;
|
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
|
||||||
Model::SkinLocations Model::_skinShadowLocations;
|
|
||||||
|
locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
|
||||||
|
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
|
||||||
|
|
||||||
|
#if (GPU_FEATURE_PROFILE == GPU_CORE)
|
||||||
|
locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer");
|
||||||
|
#else
|
||||||
|
locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer");
|
||||||
|
#endif
|
||||||
|
locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices");
|
||||||
|
|
||||||
|
locations.clusterIndices = program->getInputs().findLocation("clusterIndices");;
|
||||||
|
locations.clusterWeights = program->getInputs().findLocation("clusterWeights");;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
AbstractViewStateInterface* Model::_viewState = NULL;
|
AbstractViewStateInterface* Model::_viewState = NULL;
|
||||||
|
|
||||||
const GLint MATERIAL_GPU_SLOT = 3;
|
|
||||||
|
|
||||||
void Model::setScale(const glm::vec3& scale) {
|
void Model::setScale(const glm::vec3& scale) {
|
||||||
setScaleInternal(scale);
|
setScaleInternal(scale);
|
||||||
|
@ -171,33 +210,6 @@ void Model::setOffset(const glm::vec3& offset) {
|
||||||
_snappedToRegistrationPoint = false;
|
_snappedToRegistrationPoint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::initProgram(gpu::ShaderPointer& program, Model::Locations& locations) {
|
|
||||||
locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold");
|
|
||||||
locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices");
|
|
||||||
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
|
|
||||||
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
|
|
||||||
|
|
||||||
locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
|
|
||||||
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
|
|
||||||
|
|
||||||
#if (GPU_FEATURE_PROFILE == GPU_CORE)
|
|
||||||
locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer");
|
|
||||||
#else
|
|
||||||
locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::initSkinProgram(gpu::ShaderPointer& program, Model::SkinLocations& locations) {
|
|
||||||
|
|
||||||
initProgram(program, locations);
|
|
||||||
|
|
||||||
locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices");
|
|
||||||
|
|
||||||
locations.clusterIndices = program->getInputs().findLocation("clusterIndices");;
|
|
||||||
locations.clusterWeights = program->getInputs().findLocation("clusterWeights");;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
|
QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
|
||||||
QVector<JointState> jointStates;
|
QVector<JointState> jointStates;
|
||||||
for (int i = 0; i < geometry.joints.size(); ++i) {
|
for (int i = 0; i < geometry.joints.size(); ++i) {
|
||||||
|
@ -231,7 +243,7 @@ void Model::initJointTransforms() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::init() {
|
void Model::init() {
|
||||||
if (_program.isNull()) {
|
if (_renderPipelineLib.empty()) {
|
||||||
gpu::Shader::BindingSet slotBindings;
|
gpu::Shader::BindingSet slotBindings;
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
|
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0));
|
slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0));
|
||||||
|
@ -261,75 +273,71 @@ void Model::init() {
|
||||||
auto modelLightmapSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)));
|
auto modelLightmapSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)));
|
||||||
auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)));
|
auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)));
|
||||||
|
|
||||||
|
// Fill the renderPipelineLib
|
||||||
bool makeResult = false;
|
|
||||||
|
|
||||||
// Programs
|
|
||||||
_program = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelPixel));
|
|
||||||
makeResult = gpu::Shader::makeProgram(*_program, slotBindings);
|
|
||||||
initProgram(_program, _locations);
|
|
||||||
|
|
||||||
_normalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalMapPixel));
|
|
||||||
makeResult = gpu::Shader::makeProgram(*_normalMapProgram, slotBindings);
|
|
||||||
initProgram(_normalMapProgram, _normalMapLocations);
|
|
||||||
|
|
||||||
_specularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelSpecularMapPixel));
|
|
||||||
makeResult = gpu::Shader::makeProgram(*_specularMapProgram, slotBindings);
|
|
||||||
initProgram(_specularMapProgram, _specularMapLocations);
|
|
||||||
|
|
||||||
_normalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalSpecularMapPixel));
|
|
||||||
makeResult = gpu::Shader::makeProgram(*_normalSpecularMapProgram, slotBindings);
|
|
||||||
initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations);
|
|
||||||
|
|
||||||
_translucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelTranslucentPixel));
|
|
||||||
makeResult = gpu::Shader::makeProgram(*_translucentProgram, slotBindings);
|
|
||||||
initProgram(_translucentProgram, _translucentLocations);
|
|
||||||
|
|
||||||
_shadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelShadowVertex, modelShadowPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_shadowProgram, slotBindings);
|
RenderKey(0),
|
||||||
initProgram(_shadowProgram, _shadowLocations);
|
modelVertex, modelPixel);
|
||||||
|
|
||||||
_lightmapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_lightmapProgram, slotBindings);
|
RenderKey(RenderKey::HAS_TANGENTS),
|
||||||
initProgram(_lightmapProgram, _lightmapLocations);
|
modelNormalMapVertex, modelNormalMapPixel);
|
||||||
|
|
||||||
_lightmapNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalMapPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_lightmapNormalMapProgram, slotBindings);
|
RenderKey(RenderKey::HAS_SPECULAR),
|
||||||
initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations);
|
modelVertex, modelSpecularMapPixel);
|
||||||
|
|
||||||
_lightmapSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapSpecularMapPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_lightmapSpecularMapProgram, slotBindings);
|
RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
||||||
initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations);
|
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
|
||||||
_lightmapNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_lightmapNormalSpecularMapProgram, slotBindings);
|
RenderKey(RenderKey::IS_TRANSLUCENT),
|
||||||
initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations);
|
modelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
_renderPipelineLib.addRenderPipeline(
|
||||||
|
RenderKey(RenderKey::HAS_LIGHTMAP),
|
||||||
|
modelLightmapVertex, modelLightmapPixel);
|
||||||
|
_renderPipelineLib.addRenderPipeline(
|
||||||
|
RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS),
|
||||||
|
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);
|
||||||
|
|
||||||
_skinProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_skinProgram, slotBindings);
|
RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_SPECULAR),
|
||||||
initSkinProgram(_skinProgram, _skinLocations);
|
modelLightmapVertex, modelLightmapSpecularMapPixel);
|
||||||
|
|
||||||
_skinNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalMapPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_skinNormalMapProgram, slotBindings);
|
RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
||||||
initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations);
|
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
||||||
|
|
||||||
_skinSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelSpecularMapPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_skinSpecularMapProgram, slotBindings);
|
RenderKey(RenderKey::IS_SKINNED),
|
||||||
initSkinProgram(_skinSpecularMapProgram, _skinSpecularMapLocations);
|
skinModelVertex, modelPixel);
|
||||||
|
|
||||||
_skinNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalSpecularMapPixel));
|
_renderPipelineLib.addRenderPipeline(
|
||||||
makeResult = gpu::Shader::makeProgram(*_skinNormalSpecularMapProgram, slotBindings);
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS),
|
||||||
initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations);
|
skinModelNormalMapVertex, modelNormalMapPixel);
|
||||||
|
|
||||||
_skinShadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelShadowVertex, modelShadowPixel));
|
|
||||||
makeResult = gpu::Shader::makeProgram(*_skinShadowProgram, slotBindings);
|
|
||||||
initSkinProgram(_skinShadowProgram, _skinShadowLocations);
|
|
||||||
|
|
||||||
_skinTranslucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelTranslucentPixel));
|
|
||||||
makeResult = gpu::Shader::makeProgram(*_skinTranslucentProgram, slotBindings);
|
|
||||||
initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations);
|
|
||||||
|
|
||||||
(void) makeResult; // quiet compiler
|
_renderPipelineLib.addRenderPipeline(
|
||||||
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR),
|
||||||
|
skinModelVertex, modelSpecularMapPixel);
|
||||||
|
|
||||||
|
_renderPipelineLib.addRenderPipeline(
|
||||||
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
|
||||||
|
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
|
||||||
|
_renderPipelineLib.addRenderPipeline(
|
||||||
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT),
|
||||||
|
skinModelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
|
||||||
|
_renderPipelineLib.addRenderPipeline(
|
||||||
|
RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
|
||||||
|
modelShadowVertex, modelShadowPixel);
|
||||||
|
|
||||||
|
_renderPipelineLib.addRenderPipeline(
|
||||||
|
RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW),
|
||||||
|
skinModelShadowVertex, modelShadowPixel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,6 +673,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// auto glowEffectIntensity = DependencyManager::get<GlowEffect>()->getIntensity();
|
||||||
|
|
||||||
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
||||||
_renderBatch.clear();
|
_renderBatch.clear();
|
||||||
gpu::Batch& batch = _renderBatch;
|
gpu::Batch& batch = _renderBatch;
|
||||||
|
@ -693,42 +703,48 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
batch.setViewTransform(_transforms[0]);
|
batch.setViewTransform(_transforms[0]);
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
// GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
||||||
|
|
||||||
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
// taking care of by the state?
|
||||||
|
/* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) {
|
||||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||||
} else {
|
} else {
|
||||||
GLBATCH(glEnable)(GL_CULL_FACE);
|
GLBATCH(glEnable)(GL_CULL_FACE);
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
GLBATCH(glCullFace)(GL_FRONT);
|
GLBATCH(glCullFace)(GL_FRONT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// render opaque meshes with alpha testing
|
// render opaque meshes with alpha testing
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_BLEND);
|
// GLBATCH(glDisable)(GL_BLEND);
|
||||||
GLBATCH(glEnable)(GL_ALPHA_TEST);
|
// GLBATCH(glEnable)(GL_ALPHA_TEST);
|
||||||
|
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
/* if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
||||||
mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE,
|
||||||
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE,
|
||||||
mode == DEFAULT_RENDER_MODE);
|
mode == RenderArgs::DEFAULT_RENDER_MODE);
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
GLenum buffers[3];
|
GLenum buffers[3];
|
||||||
int bufferCount = 0;
|
int bufferCount = 0;
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
|
||||||
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||||
}
|
}
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||||
}
|
}
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||||
}
|
}
|
||||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||||
|
@ -774,11 +790,11 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args, true);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args, true);
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
// GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||||
GLBATCH(glEnable)(GL_BLEND);
|
/* GLBATCH(glEnable)(GL_BLEND);
|
||||||
GLBATCH(glDepthMask)(false);
|
GLBATCH(glDepthMask)(false);
|
||||||
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
||||||
|
*/
|
||||||
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
|
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
|
||||||
{
|
{
|
||||||
GLenum buffers[1];
|
GLenum buffers[1];
|
||||||
|
@ -787,7 +803,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true);
|
||||||
|
@ -803,7 +820,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
GLBATCH(glDepthFunc)(GL_LESS);
|
GLBATCH(glDepthFunc)(GL_LESS);
|
||||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||||
|
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
GLBATCH(glCullFace)(GL_BACK);
|
GLBATCH(glCullFace)(GL_BACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,6 +847,9 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
|
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// Back to no program
|
||||||
|
GLBATCH(glUseProgram)(0);
|
||||||
|
|
||||||
// Render!
|
// Render!
|
||||||
{
|
{
|
||||||
PROFILE_RANGE("render Batch");
|
PROFILE_RANGE("render Batch");
|
||||||
|
@ -1738,6 +1758,9 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
|
||||||
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
|
||||||
|
// auto glowEffectIntensity = DependencyManager::get<GlowEffect>()->getIntensity();
|
||||||
|
|
||||||
|
|
||||||
#if defined(ANDROID)
|
#if defined(ANDROID)
|
||||||
#else
|
#else
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
@ -1769,42 +1792,45 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
_sceneRenderBatch.clear();
|
_sceneRenderBatch.clear();
|
||||||
gpu::Batch& batch = _sceneRenderBatch;
|
gpu::Batch& batch = _sceneRenderBatch;
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
// GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
||||||
|
|
||||||
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
/* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) {
|
||||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||||
} else {
|
} else {
|
||||||
GLBATCH(glEnable)(GL_CULL_FACE);
|
GLBATCH(glEnable)(GL_CULL_FACE);
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
GLBATCH(glCullFace)(GL_FRONT);
|
GLBATCH(glCullFace)(GL_FRONT);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// render opaque meshes with alpha testing
|
// render opaque meshes with alpha testing
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_BLEND);
|
// GLBATCH(glDisable)(GL_BLEND);
|
||||||
GLBATCH(glEnable)(GL_ALPHA_TEST);
|
// GLBATCH(glEnable)(GL_ALPHA_TEST);
|
||||||
|
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
/* if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
|
||||||
mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE,
|
||||||
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
|
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE,
|
||||||
mode == DEFAULT_RENDER_MODE);
|
mode == RenderArgs::DEFAULT_RENDER_MODE);
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
GLenum buffers[3];
|
GLenum buffers[3];
|
||||||
int bufferCount = 0;
|
int bufferCount = 0;
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||||
}
|
}
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
//if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||||
}
|
}
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||||
}
|
}
|
||||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||||
|
@ -1850,11 +1876,11 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
// GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||||
GLBATCH(glEnable)(GL_BLEND);
|
/* GLBATCH(glEnable)(GL_BLEND);
|
||||||
GLBATCH(glDepthMask)(false);
|
GLBATCH(glDepthMask)(false);
|
||||||
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
||||||
|
*/
|
||||||
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
|
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true);
|
||||||
{
|
{
|
||||||
GLenum buffers[1];
|
GLenum buffers[1];
|
||||||
|
@ -1863,7 +1889,8 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE || mode == DEBUG_RENDER_MODE) {
|
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
|
||||||
|
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args);
|
||||||
|
@ -1879,7 +1906,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
GLBATCH(glDepthFunc)(GL_LESS);
|
GLBATCH(glDepthFunc)(GL_LESS);
|
||||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||||
|
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
GLBATCH(glCullFace)(GL_BACK);
|
GLBATCH(glCullFace)(GL_BACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1907,6 +1934,10 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
|
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
|
||||||
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
|
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// Back to no program
|
||||||
|
GLBATCH(glUseProgram)(0);
|
||||||
|
|
||||||
if (args) {
|
if (args) {
|
||||||
args->_translucentMeshPartsRendered = translucentParts;
|
args->_translucentMeshPartsRendered = translucentParts;
|
||||||
args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered;
|
args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered;
|
||||||
|
@ -2298,83 +2329,34 @@ QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool h
|
||||||
|
|
||||||
void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
||||||
Locations*& locations, SkinLocations*& skinLocations) {
|
Locations*& locations) {
|
||||||
gpu::ShaderPointer program = _program;
|
|
||||||
locations = &_locations;
|
|
||||||
gpu::ShaderPointer skinProgram = _skinProgram;
|
|
||||||
skinLocations = &_skinLocations;
|
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
|
||||||
program = _shadowProgram;
|
|
||||||
locations = &_shadowLocations;
|
|
||||||
skinProgram = _skinShadowProgram;
|
|
||||||
skinLocations = &_skinShadowLocations;
|
|
||||||
} else if (translucent && alphaThreshold == 0.0f) {
|
|
||||||
program = _translucentProgram;
|
|
||||||
locations = &_translucentLocations;
|
|
||||||
skinProgram = _skinTranslucentProgram;
|
|
||||||
skinLocations = &_skinTranslucentLocations;
|
|
||||||
|
|
||||||
} else if (hasLightmap) {
|
|
||||||
if (hasTangents) {
|
|
||||||
if (hasSpecular) {
|
|
||||||
program = _lightmapNormalSpecularMapProgram;
|
|
||||||
locations = &_lightmapNormalSpecularMapLocations;
|
|
||||||
skinProgram.reset();
|
|
||||||
skinLocations = NULL;
|
|
||||||
} else {
|
|
||||||
program = _lightmapNormalMapProgram;
|
|
||||||
locations = &_lightmapNormalMapLocations;
|
|
||||||
skinProgram.reset();
|
|
||||||
skinLocations = NULL;
|
|
||||||
}
|
|
||||||
} else if (hasSpecular) {
|
|
||||||
program = _lightmapSpecularMapProgram;
|
|
||||||
locations = &_lightmapSpecularMapLocations;
|
|
||||||
skinProgram.reset();
|
|
||||||
skinLocations = NULL;
|
|
||||||
} else {
|
|
||||||
program = _lightmapProgram;
|
|
||||||
locations = &_lightmapLocations;
|
|
||||||
skinProgram.reset();
|
|
||||||
skinLocations = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (hasTangents) {
|
|
||||||
if (hasSpecular) {
|
|
||||||
program = _normalSpecularMapProgram;
|
|
||||||
locations = &_normalSpecularMapLocations;
|
|
||||||
skinProgram = _skinNormalSpecularMapProgram;
|
|
||||||
skinLocations = &_skinNormalSpecularMapLocations;
|
|
||||||
} else {
|
|
||||||
program = _normalMapProgram;
|
|
||||||
locations = &_normalMapLocations;
|
|
||||||
skinProgram = _skinNormalMapProgram;
|
|
||||||
skinLocations = &_skinNormalMapLocations;
|
|
||||||
}
|
|
||||||
} else if (hasSpecular) {
|
|
||||||
program = _specularMapProgram;
|
|
||||||
locations = &_specularMapLocations;
|
|
||||||
skinProgram = _skinSpecularMapProgram;
|
|
||||||
skinLocations = &_skinSpecularMapLocations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu::ShaderPointer activeProgram = program;
|
RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
||||||
Locations* activeLocations = locations;
|
auto pipeline = _renderPipelineLib.find(key.getRaw());
|
||||||
|
if (pipeline == _renderPipelineLib.end()) {
|
||||||
if (isSkinned) {
|
qDebug() << "No good, couldn;t find a pipeline from the key ?" << key.getRaw();
|
||||||
activeProgram = skinProgram;
|
return;
|
||||||
activeLocations = skinLocations;
|
|
||||||
locations = skinLocations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint glprogram = gpu::GLBackend::getShaderID(activeProgram);
|
gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram();
|
||||||
GLBATCH(glUseProgram)(glprogram);
|
locations = (*pipeline).second._locations.get();
|
||||||
|
|
||||||
|
//GLuint glprogram = gpu::GLBackend::getShaderID(program);
|
||||||
|
//GLBATCH(glUseProgram)(glprogram);
|
||||||
|
|
||||||
|
// dare!
|
||||||
|
batch.setPipeline((*pipeline).second._pipeline);
|
||||||
|
|
||||||
if ((activeLocations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) {
|
if ((locations->alphaThreshold > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
||||||
GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold);
|
GLBATCH(glUniform1f)(locations->alphaThreshold, alphaThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
||||||
|
GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get<GlowEffect>()->getIntensity());
|
||||||
|
}
|
||||||
|
// if (!(translucent && alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
|
||||||
|
// GLBATCH(glAlphaFunc)(GL_EQUAL, DependencyManager::get<GlowEffect>()->getIntensity());
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
|
@ -2385,7 +2367,6 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
|
||||||
|
|
||||||
bool pickProgramsNeeded = true;
|
bool pickProgramsNeeded = true;
|
||||||
Locations* locations;
|
Locations* locations;
|
||||||
SkinLocations* skinLocations;
|
|
||||||
|
|
||||||
foreach(Model* model, _modelsInScene) {
|
foreach(Model* model, _modelsInScene) {
|
||||||
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
||||||
|
@ -2393,24 +2374,25 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
|
||||||
QVector<int>& list = *whichList;
|
QVector<int>& list = *whichList;
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
if (pickProgramsNeeded) {
|
if (pickProgramsNeeded) {
|
||||||
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations);
|
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations);
|
||||||
pickProgramsNeeded = false;
|
pickProgramsNeeded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
model->setupBatchTransform(batch, args);
|
model->setupBatchTransform(batch, args);
|
||||||
meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations);
|
meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we selected a program, then unselect it
|
// if we selected a program, then unselect it
|
||||||
if (!pickProgramsNeeded) {
|
if (!pickProgramsNeeded) {
|
||||||
GLBATCH(glUseProgram)(0);
|
// GLBATCH(glUseProgram)(0);
|
||||||
}
|
}
|
||||||
return meshPartsRendered;
|
return meshPartsRendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
||||||
bool forceRenderMeshes) {
|
bool forceRenderSomeMeshes) {
|
||||||
|
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
int meshPartsRendered = 0;
|
int meshPartsRendered = 0;
|
||||||
|
@ -2429,24 +2411,23 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
||||||
}
|
}
|
||||||
|
|
||||||
Locations* locations;
|
Locations* locations;
|
||||||
SkinLocations* skinLocations;
|
|
||||||
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned,
|
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned,
|
||||||
args, locations, skinLocations);
|
args, locations);
|
||||||
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
|
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
|
||||||
args, locations, skinLocations, forceRenderMeshes);
|
args, locations, forceRenderSomeMeshes);
|
||||||
GLBATCH(glUseProgram)(0);
|
// GLBATCH(glUseProgram)(0);
|
||||||
|
|
||||||
|
|
||||||
return meshPartsRendered;
|
return meshPartsRendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent,
|
int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args,
|
||||||
float alphaThreshold, RenderArgs* args, Locations* locations, SkinLocations* skinLocations,
|
Locations* locations, bool forceRenderMeshes) {
|
||||||
bool forceRenderMeshes) {
|
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
auto glowEffect = DependencyManager::get<GlowEffect>();
|
// auto glowEffect = DependencyManager::get<GlowEffect>();
|
||||||
QString lastMaterialID;
|
QString lastMaterialID;
|
||||||
int meshPartsRendered = 0;
|
int meshPartsRendered = 0;
|
||||||
updateVisibleJointStates();
|
updateVisibleJointStates();
|
||||||
|
@ -2506,7 +2487,7 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
|
|
||||||
const MeshState& state = _meshStates.at(i);
|
const MeshState& state = _meshStates.at(i);
|
||||||
if (state.clusterMatrices.size() > 1) {
|
if (state.clusterMatrices.size() > 1) {
|
||||||
GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false,
|
||||||
(const float*)state.clusterMatrices.constData());
|
(const float*)state.clusterMatrices.constData());
|
||||||
batch.setModelTransform(Transform());
|
batch.setModelTransform(Transform());
|
||||||
} else {
|
} else {
|
||||||
|
@ -2524,7 +2505,7 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.colors.isEmpty()) {
|
if (mesh.colors.isEmpty()) {
|
||||||
GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f);
|
GLBATCH(glColor4f)(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 offset = 0;
|
qint64 offset = 0;
|
||||||
|
@ -2538,7 +2519,7 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply material properties
|
// apply material properties
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||||
/// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
/// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2550,13 +2531,13 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
qCDebug(renderutils) << "NEW part.materialID:" << part.materialID;
|
qCDebug(renderutils) << "NEW part.materialID:" << part.materialID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locations->glowIntensity >= 0) {
|
/* if (locations->glowIntensity >= 0) {
|
||||||
GLBATCH(glUniform1f)(locations->glowIntensity, glowEffect->getIntensity());
|
GLBATCH(glUniform1f)(locations->glowIntensity, glowEffect->getIntensity());
|
||||||
}
|
}
|
||||||
if (!(translucent && alphaThreshold == 0.0f)) {
|
if (!(translucent && alphaThreshold == 0.0f)) {
|
||||||
GLBATCH(glAlphaFunc)(GL_EQUAL, glowEffect->getIntensity());
|
GLBATCH(glAlphaFunc)(GL_EQUAL, glowEffect->getIntensity());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (locations->materialBufferUnit >= 0) {
|
if (locations->materialBufferUnit >= 0) {
|
||||||
batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer());
|
batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer());
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,16 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <AABox.h>
|
#include <AABox.h>
|
||||||
#include <AnimationCache.h>
|
#include <AnimationCache.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <GeometryUtil.h>
|
#include <GeometryUtil.h>
|
||||||
#include <gpu/Stream.h>
|
#include <gpu/Stream.h>
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
|
#include <gpu/Pipeline.h>
|
||||||
#include "PhysicsEntity.h"
|
#include "PhysicsEntity.h"
|
||||||
#include <Transform.h>
|
#include <Transform.h>
|
||||||
|
|
||||||
|
@ -47,6 +51,8 @@ class Model : public QObject, public PhysicsEntity {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
typedef RenderArgs::RenderMode RenderMode;
|
||||||
|
|
||||||
static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; }
|
static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; }
|
||||||
|
|
||||||
Model(QObject* parent = NULL);
|
Model(QObject* parent = NULL);
|
||||||
|
@ -90,15 +96,13 @@ public:
|
||||||
void init();
|
void init();
|
||||||
void reset();
|
void reset();
|
||||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||||
|
|
||||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, DEBUG_RENDER_MODE };
|
bool render(float alpha = 1.0f, RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||||
|
|
||||||
bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
|
||||||
|
|
||||||
// Scene rendering support
|
// Scene rendering support
|
||||||
static void startScene(RenderArgs::RenderSide renderSide);
|
static void startScene(RenderArgs::RenderSide renderSide);
|
||||||
bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL);
|
bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL);
|
||||||
static void endScene(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
static void endScene(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||||
|
|
||||||
/// Sets the URL of the model to render.
|
/// Sets the URL of the model to render.
|
||||||
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
||||||
|
@ -319,27 +323,6 @@ private:
|
||||||
int _blendNumber;
|
int _blendNumber;
|
||||||
int _appliedBlendNumber;
|
int _appliedBlendNumber;
|
||||||
|
|
||||||
static gpu::ShaderPointer _program;
|
|
||||||
static gpu::ShaderPointer _normalMapProgram;
|
|
||||||
static gpu::ShaderPointer _specularMapProgram;
|
|
||||||
static gpu::ShaderPointer _normalSpecularMapProgram;
|
|
||||||
static gpu::ShaderPointer _translucentProgram;
|
|
||||||
|
|
||||||
static gpu::ShaderPointer _lightmapProgram;
|
|
||||||
static gpu::ShaderPointer _lightmapNormalMapProgram;
|
|
||||||
static gpu::ShaderPointer _lightmapSpecularMapProgram;
|
|
||||||
static gpu::ShaderPointer _lightmapNormalSpecularMapProgram;
|
|
||||||
|
|
||||||
static gpu::ShaderPointer _shadowProgram;
|
|
||||||
|
|
||||||
static gpu::ShaderPointer _skinProgram;
|
|
||||||
static gpu::ShaderPointer _skinNormalMapProgram;
|
|
||||||
static gpu::ShaderPointer _skinSpecularMapProgram;
|
|
||||||
static gpu::ShaderPointer _skinNormalSpecularMapProgram;
|
|
||||||
static gpu::ShaderPointer _skinTranslucentProgram;
|
|
||||||
|
|
||||||
static gpu::ShaderPointer _skinShadowProgram;
|
|
||||||
|
|
||||||
class Locations {
|
class Locations {
|
||||||
public:
|
public:
|
||||||
int tangent;
|
int tangent;
|
||||||
|
@ -350,40 +333,10 @@ private:
|
||||||
int emissiveParams;
|
int emissiveParams;
|
||||||
int glowIntensity;
|
int glowIntensity;
|
||||||
int materialBufferUnit;
|
int materialBufferUnit;
|
||||||
};
|
|
||||||
|
|
||||||
static Locations _locations;
|
|
||||||
static Locations _normalMapLocations;
|
|
||||||
static Locations _specularMapLocations;
|
|
||||||
static Locations _normalSpecularMapLocations;
|
|
||||||
static Locations _translucentLocations;
|
|
||||||
static Locations _shadowLocations;
|
|
||||||
|
|
||||||
static Locations _lightmapLocations;
|
|
||||||
static Locations _lightmapNormalMapLocations;
|
|
||||||
static Locations _lightmapSpecularMapLocations;
|
|
||||||
static Locations _lightmapNormalSpecularMapLocations;
|
|
||||||
|
|
||||||
static void initProgram(ProgramObject& program, Locations& locations, bool link = true);
|
|
||||||
static void initProgram(gpu::ShaderPointer& program, Locations& locations);
|
|
||||||
|
|
||||||
class SkinLocations : public Locations {
|
|
||||||
public:
|
|
||||||
int clusterMatrices;
|
int clusterMatrices;
|
||||||
int clusterIndices;
|
int clusterIndices;
|
||||||
int clusterWeights;
|
int clusterWeights;
|
||||||
};
|
};
|
||||||
|
|
||||||
static SkinLocations _skinLocations;
|
|
||||||
static SkinLocations _skinNormalMapLocations;
|
|
||||||
static SkinLocations _skinSpecularMapLocations;
|
|
||||||
static SkinLocations _skinNormalSpecularMapLocations;
|
|
||||||
static SkinLocations _skinTranslucentLocations;
|
|
||||||
static SkinLocations _skinShadowLocations;
|
|
||||||
|
|
||||||
|
|
||||||
static void initSkinProgram(ProgramObject& program, SkinLocations& locations);
|
|
||||||
static void initSkinProgram(gpu::ShaderPointer& program, SkinLocations& locations);
|
|
||||||
|
|
||||||
QVector<AABox> _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes
|
QVector<AABox> _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes
|
||||||
bool _calculatedMeshBoxesValid;
|
bool _calculatedMeshBoxesValid;
|
||||||
|
@ -421,6 +374,9 @@ private:
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangents;
|
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangents;
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangentsSpecular;
|
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangentsSpecular;
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueLightmapSpecular;
|
QMap<QString, int> _unsortedMeshesOpaqueLightmapSpecular;
|
||||||
|
|
||||||
|
typedef std::unordered_map<int, QVector<int>> MeshListMap;
|
||||||
|
MeshListMap _sortedMeshes;
|
||||||
|
|
||||||
QVector<int> _meshesTranslucent;
|
QVector<int> _meshesTranslucent;
|
||||||
QVector<int> _meshesTranslucentTangents;
|
QVector<int> _meshesTranslucentTangents;
|
||||||
|
@ -455,33 +411,122 @@ private:
|
||||||
static QVector<Model*> _modelsInScene;
|
static QVector<Model*> _modelsInScene;
|
||||||
static gpu::Batch _sceneRenderBatch;
|
static gpu::Batch _sceneRenderBatch;
|
||||||
|
|
||||||
static void endSceneSimple(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
static void endSceneSimple(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||||
static void endSceneSplitPass(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
static void endSceneSplitPass(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||||
|
|
||||||
// helper functions used by render() or renderInScene()
|
// helper functions used by render() or renderInScene()
|
||||||
void renderSetup(RenderArgs* args);
|
void renderSetup(RenderArgs* args);
|
||||||
bool renderCore(float alpha, RenderMode mode, RenderArgs* args);
|
bool renderCore(float alpha, RenderArgs::RenderMode mode, RenderArgs* args);
|
||||||
int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL,
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL,
|
||||||
bool forceRenderMeshes = false);
|
bool forceRenderMeshes = false);
|
||||||
|
|
||||||
void setupBatchTransform(gpu::Batch& batch, RenderArgs* args);
|
void setupBatchTransform(gpu::Batch& batch, RenderArgs* args);
|
||||||
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned);
|
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned);
|
||||||
|
|
||||||
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
RenderArgs* args, Locations* locations, SkinLocations* skinLocations,
|
RenderArgs* args, Locations* locations,
|
||||||
bool forceRenderMeshes = false);
|
bool forceRenderSomeMeshes = false);
|
||||||
|
|
||||||
static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
static void pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
||||||
Locations*& locations, SkinLocations*& skinLocations);
|
Locations*& locations);
|
||||||
|
|
||||||
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args);
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args);
|
||||||
|
|
||||||
|
|
||||||
static AbstractViewStateInterface* _viewState;
|
static AbstractViewStateInterface* _viewState;
|
||||||
|
|
||||||
|
class RenderKey {
|
||||||
|
public:
|
||||||
|
enum FlagBit {
|
||||||
|
IS_TRANSLUCENT_FLAG = 0,
|
||||||
|
HAS_LIGHTMAP_FLAG,
|
||||||
|
HAS_TANGENTS_FLAG,
|
||||||
|
HAS_SPECULAR_FLAG,
|
||||||
|
HAS_EMISSIVE_FLAG,
|
||||||
|
IS_SKINNED_FLAG,
|
||||||
|
IS_STEREO_FLAG,
|
||||||
|
IS_DEPTH_ONLY_FLAG,
|
||||||
|
IS_SHADOW_FLAG,
|
||||||
|
IS_MIRROR_FLAG, //THis means that the mesh is rendered mirrored, not the same as "Rear view mirror"
|
||||||
|
|
||||||
|
NUM_FLAGS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Flag {
|
||||||
|
IS_TRANSLUCENT = (1 << IS_TRANSLUCENT_FLAG),
|
||||||
|
HAS_LIGHTMAP = (1 << HAS_LIGHTMAP_FLAG),
|
||||||
|
HAS_TANGENTS = (1 << HAS_TANGENTS_FLAG),
|
||||||
|
HAS_SPECULAR = (1 << HAS_SPECULAR_FLAG),
|
||||||
|
HAS_EMISSIVE = (1 << HAS_EMISSIVE_FLAG),
|
||||||
|
IS_SKINNED = (1 << IS_SKINNED_FLAG),
|
||||||
|
IS_STEREO = (1 << IS_STEREO_FLAG),
|
||||||
|
IS_DEPTH_ONLY = (1 << IS_DEPTH_ONLY_FLAG),
|
||||||
|
IS_SHADOW = (1 << IS_SHADOW_FLAG),
|
||||||
|
IS_MIRROR = (1 << IS_MIRROR_FLAG),
|
||||||
|
|
||||||
|
};
|
||||||
|
typedef unsigned short Flags;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }
|
||||||
|
|
||||||
|
bool isTranslucent() const { return isFlag(IS_TRANSLUCENT); }
|
||||||
|
bool hasLightmap() const { return isFlag(HAS_LIGHTMAP); }
|
||||||
|
bool hasTangents() const { return isFlag(HAS_TANGENTS); }
|
||||||
|
bool hasSpecular() const { return isFlag(HAS_SPECULAR); }
|
||||||
|
bool hasEmissive() const { return isFlag(HAS_EMISSIVE); }
|
||||||
|
bool isSkinned() const { return isFlag(IS_SKINNED); }
|
||||||
|
bool isStereo() const { return isFlag(IS_STEREO); }
|
||||||
|
bool isDepthOnly() const { return isFlag(IS_DEPTH_ONLY); }
|
||||||
|
bool isShadow() const { return isFlag(IS_SHADOW); } // = depth only but with back facing
|
||||||
|
bool isMirror() const { return isFlag(IS_MIRROR); }
|
||||||
|
|
||||||
|
Flags _flags = 0;
|
||||||
|
short _spare = 0;
|
||||||
|
|
||||||
|
int getRaw() { return *reinterpret_cast<int*>(this); }
|
||||||
|
|
||||||
|
RenderKey(RenderArgs::RenderMode mode,
|
||||||
|
bool translucent, float alphaThreshold, bool hasLightmap,
|
||||||
|
bool hasTangents, bool hasSpecular, bool isSkinned) :
|
||||||
|
RenderKey( ((translucent && (alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0)
|
||||||
|
| (hasLightmap && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly
|
||||||
|
| (hasTangents && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0)
|
||||||
|
| (hasSpecular && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0)
|
||||||
|
| (isSkinned ? IS_SKINNED : 0)
|
||||||
|
| ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_DEPTH_ONLY : 0)
|
||||||
|
| ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_SHADOW : 0)
|
||||||
|
| ((mode == RenderArgs::MIRROR_RENDER_MODE) ? IS_MIRROR :0)
|
||||||
|
) {}
|
||||||
|
|
||||||
|
RenderKey(int bitmask) : _flags(bitmask) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RenderPipeline {
|
||||||
|
public:
|
||||||
|
gpu::PipelinePointer _pipeline;
|
||||||
|
std::shared_ptr<Locations> _locations;
|
||||||
|
RenderPipeline(gpu::PipelinePointer pipeline, std::shared_ptr<Locations> locations) :
|
||||||
|
_pipeline(pipeline), _locations(locations) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::unordered_map<int, RenderPipeline> BaseRenderPipelineMap;
|
||||||
|
class RenderPipelineLib : public BaseRenderPipelineMap {
|
||||||
|
public:
|
||||||
|
typedef RenderKey Key;
|
||||||
|
|
||||||
|
|
||||||
|
void addRenderPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader);
|
||||||
|
|
||||||
|
void initLocations(gpu::ShaderPointer& program, Locations& locations);
|
||||||
|
};
|
||||||
|
static RenderPipelineLib _renderPipelineLib;
|
||||||
|
|
||||||
bool _renderCollisionHull;
|
bool _renderCollisionHull;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ void main(void) {
|
||||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5);
|
vec3 localNormal = normalize(vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5));
|
||||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ void main(void) {
|
||||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5);
|
vec3 localNormal = normalize(vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5));
|
||||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,15 @@ void main(void) {
|
||||||
// and the texture coordinates
|
// and the texture coordinates
|
||||||
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||||
|
|
||||||
|
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);
|
||||||
|
interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);
|
||||||
|
|
||||||
// standard transform
|
// standard transform
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
TransformObject obj = getTransformObject();
|
TransformObject obj = getTransformObject();
|
||||||
<$transformModelToClipPos(cam, obj, interpolatedPosition, gl_Position)$>
|
<$transformModelToClipPos(cam, obj, interpolatedPosition, gl_Position)$>
|
||||||
<$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$>
|
<$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$>
|
||||||
<$transformModelToEyeDir(cam, obj, tangent, interpolatedTangent.xyz)$>
|
<$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$>
|
||||||
|
|
||||||
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);
|
interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);
|
||||||
interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);
|
interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);
|
||||||
|
|
|
@ -17,7 +17,8 @@ class OctreeRenderer;
|
||||||
|
|
||||||
class RenderArgs {
|
class RenderArgs {
|
||||||
public:
|
public:
|
||||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, DEBUG_RENDER_MODE };
|
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE, DEBUG_RENDER_MODE };
|
||||||
|
|
||||||
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
|
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
|
||||||
|
|
||||||
OctreeRenderer* _renderer;
|
OctreeRenderer* _renderer;
|
||||||
|
|
Loading…
Reference in a new issue