summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2019-08-29 15:03:13 +0300
committerAntti Määttä <antti.maatta@qt.io>2019-09-12 14:29:39 +0300
commitbc4a0aa611242083403fd11f791f51cbab8d4f3a (patch)
tree3fa11a231a382513560f84db5a8b7999dd84d94b
parent18138ffc6b063e94b792ef61cbe310f90ea21287 (diff)
Implement two-pass rendering for transparent objects
If object has both opaque parts and transparent parts it will be rendered incorrectly due to no z-buffering. Add two-pass method to render the opaque and transparent parts separately. - Add opaque pixel check to transparency check of images. - Add alpha test rendering to default material shadows too. Task-number: QT3DS-3515 Change-Id: I9700b8fb463df9143c5bb9cbe66c7570081ebf5c Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--res/effectlib/tessellationNPatch.glsllib2
-rw-r--r--res/effectlib/tessellationPhong.glsllib2
-rw-r--r--src/engine/Qt3DSRenderRuntimeBinding.cpp4
-rw-r--r--src/render/Qt3DSRenderShaderProgram.h4
-rw-r--r--src/render/backends/Qt3DSRenderBackend.h4
-rw-r--r--src/render/backends/gl/Q3DSRenderBackendGLES2.cpp4
-rw-r--r--src/render/backends/gl/Qt3DSOpenGLExtensions.h2
-rw-r--r--src/render/backends/gl/Qt3DSOpenGLUtil.h4
-rw-r--r--src/render/backends/gl/Qt3DSRenderBackendGL3.cpp8
-rw-r--r--src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp22
-rw-r--r--src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h3
-rw-r--r--src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp8
-rw-r--r--src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp426
-rw-r--r--src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h24
-rw-r--r--src/runtimerender/Qt3DSRenderImageTextureData.h16
-rw-r--r--src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h3
-rw-r--r--src/runtimerender/Qt3DSRenderPathManager.cpp2
-rw-r--r--src/runtimerender/Qt3DSRenderShaderKeys.h73
-rw-r--r--src/runtimerender/Qt3DSRenderUIPLoader.cpp5
-rw-r--r--src/runtimerender/Qt3DSRenderer.h2
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp111
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h41
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp201
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImpl.h43
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp131
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h4
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp61
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h2
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp60
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h32
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp21
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h3
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp45
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h3
34 files changed, 1041 insertions, 335 deletions
diff --git a/res/effectlib/tessellationNPatch.glsllib b/res/effectlib/tessellationNPatch.glsllib
index 62ec263..94efcf6 100644
--- a/res/effectlib/tessellationNPatch.glsllib
+++ b/res/effectlib/tessellationNPatch.glsllib
@@ -213,7 +213,7 @@ bool doLinear(int i, int j)
vec4 tessShader ( )
{
- // pre compute square tesselation coord
+ // pre compute square tessellation coord
vec3 tessSquared = gl_TessCoord * gl_TessCoord;
vec3 tessCubed = tessSquared * gl_TessCoord;
diff --git a/res/effectlib/tessellationPhong.glsllib b/res/effectlib/tessellationPhong.glsllib
index 98a683d..bde9f68 100644
--- a/res/effectlib/tessellationPhong.glsllib
+++ b/res/effectlib/tessellationPhong.glsllib
@@ -138,7 +138,7 @@ uniform float phongBlend;
vec4 tessShader ( )
{
- // pre compute square tesselation coord
+ // pre compute square tessellation coord
vec3 tessSquared = gl_TessCoord * gl_TessCoord;
// barycentric linear position
diff --git a/src/engine/Qt3DSRenderRuntimeBinding.cpp b/src/engine/Qt3DSRenderRuntimeBinding.cpp
index 33f9f5c..038fd8f 100644
--- a/src/engine/Qt3DSRenderRuntimeBinding.cpp
+++ b/src/engine/Qt3DSRenderRuntimeBinding.cpp
@@ -1110,7 +1110,9 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
if (theSourcePathStr.size() > 4) {
CRegisteredString theObjectPath = m_SourcePaths[idx].first;
if (qt3ds::runtime::isImagePath(theSourcePathStr.c_str())) {
- theManager.SetImageHasTransparency(theObjectPath, hasTransparency);
+ theManager.SetImageHasTransparency(
+ theObjectPath, hasTransparency,
+ theManager.GetImageHasOpaquePixels(theObjectPath));
if (isIbl)
iblImagePathList.push_back(theObjectPath);
else
diff --git a/src/render/Qt3DSRenderShaderProgram.h b/src/render/Qt3DSRenderShaderProgram.h
index ed8c677..5ad3f06 100644
--- a/src/render/Qt3DSRenderShaderProgram.h
+++ b/src/render/Qt3DSRenderShaderProgram.h
@@ -106,7 +106,7 @@ namespace render {
NVConstDataRef<QT3DSI8> fragmentShaderSource, bool binaryProgram = false);
/**
- * @brief create tesselation control shader
+ * @brief create tessellation control shader
*
* @param[in] context Pointer to render context
* @param[in] tessControlShaderSource Tessellation control shader source code
@@ -120,7 +120,7 @@ namespace render {
bool binaryProgram = false);
/**
- * @brief create tesselation evaluation shader
+ * @brief create tessellation evaluation shader
*
* @param[in] context Pointer to render context
* @param[in] tessEvaluationShaderSource Tessellation evaluation shader source code
diff --git a/src/render/backends/Qt3DSRenderBackend.h b/src/render/backends/Qt3DSRenderBackend.h
index 4e9e177..226e0b7 100644
--- a/src/render/backends/Qt3DSRenderBackend.h
+++ b/src/render/backends/Qt3DSRenderBackend.h
@@ -73,10 +73,10 @@ namespace render {
typedef struct _NVRenderBackendVertexShaderObject *NVRenderBackendVertexShaderObject;
/// opaque fragment shader object handle
typedef struct _NVRenderBackendFragmentShaderObject *NVRenderBackendFragmentShaderObject;
- /// opaque tesselation control shader object handle
+ /// opaque tessellation control shader object handle
typedef struct _NVRenderBackendTessControlShaderObject
*NVRenderBackendTessControlShaderObject;
- /// opaque tesselation evaluation shader object handle
+ /// opaque tessellation evaluation shader object handle
typedef struct _NVRenderBackendTessEvaluationShaderObject
*NVRenderBackendTessEvaluationShaderObject;
/// opaque geometry shader object handle
diff --git a/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp b/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp
index 1db51ef..54d8d5d 100644
--- a/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp
+++ b/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp
@@ -42,13 +42,13 @@
#if defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE)
#define GL_CALL_TIMER_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
-#define GL_CALL_TESSELATION_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
+#define GL_CALL_TESSELLATION_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
#define GL_CALL_MULTISAMPLE_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; RENDER_LOG_ERROR_PARAMS(x);
#define GL_CALL_EXTENSION_FUNCTION(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
#else
#define GL_CALL_TIMER_EXT(x)
-#define GL_CALL_TESSELATION_EXT(x)
+#define GL_CALL_TESSELLATION_EXT(x)
#define GL_CALL_MULTISAMPLE_EXT(x)
#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; RENDER_LOG_ERROR_PARAMS(x);
#define GL_CALL_EXTENSION_FUNCTION(x)
diff --git a/src/render/backends/gl/Qt3DSOpenGLExtensions.h b/src/render/backends/gl/Qt3DSOpenGLExtensions.h
index c9ba76a..e79fe1b 100644
--- a/src/render/backends/gl/Qt3DSOpenGLExtensions.h
+++ b/src/render/backends/gl/Qt3DSOpenGLExtensions.h
@@ -134,7 +134,7 @@ class Qt3DSOpenGLES2Extensions : public Qt3DSOpenGLExtensions
public:
Qt3DSOpenGLES2Extensions();
- // tesselation shader
+ // tessellation shader
void glPatchParameteriEXT(GLenum pname, GLint value);
// timer
diff --git a/src/render/backends/gl/Qt3DSOpenGLUtil.h b/src/render/backends/gl/Qt3DSOpenGLUtil.h
index 32f7dad..47f4230 100644
--- a/src/render/backends/gl/Qt3DSOpenGLUtil.h
+++ b/src/render/backends/gl/Qt3DSOpenGLUtil.h
@@ -1757,7 +1757,7 @@ namespace render {
return NVRenderClearFlags(retval);
}
- static GLenum fromDrawModeToGL(NVRenderDrawMode::Enum value, bool inTesselationSupported)
+ static GLenum fromDrawModeToGL(NVRenderDrawMode::Enum value, bool inTessellationSupported)
{
switch (value) {
case NVRenderDrawMode::Points:
@@ -1775,7 +1775,7 @@ namespace render {
case NVRenderDrawMode::Triangles:
return GL_TRIANGLES;
case NVRenderDrawMode::Patches:
- return (inTesselationSupported) ? GL_PATCHES : GL_TRIANGLES;
+ return (inTessellationSupported) ? GL_PATCHES : GL_TRIANGLES;
default:
break;
}
diff --git a/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp b/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp
index e5caf5e..4e637da 100644
--- a/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp
+++ b/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp
@@ -43,10 +43,10 @@
#if defined(QT_OPENGL_ES)
#define GL_CALL_TIMER_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
-#define GL_CALL_TESSELATION_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
+#define GL_CALL_TESSELLATION_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x);
#else
#define GL_CALL_TIMER_EXT(x) m_timerExtension->x; RENDER_LOG_ERROR_PARAMS(x);
-#define GL_CALL_TESSELATION_EXT(x) m_tessellationShader->x; RENDER_LOG_ERROR_PARAMS(x);
+#define GL_CALL_TESSELLATION_EXT(x) m_tessellationShader->x; RENDER_LOG_ERROR_PARAMS(x);
#define GL_CALL_MULTISAMPLE_EXT(x) m_multiSample->x; RENDER_LOG_ERROR_PARAMS(x);
#endif
@@ -408,9 +408,9 @@ namespace render {
&& m_pCurrentMiscState->m_PatchVertexCount != inputAssembler->m_PatchVertexCount) {
m_pCurrentMiscState->m_PatchVertexCount = inputAssembler->m_PatchVertexCount;
#if defined(QT_OPENGL_ES)
- GL_CALL_TESSELATION_EXT(glPatchParameteriEXT(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount));
+ GL_CALL_TESSELLATION_EXT(glPatchParameteriEXT(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount));
#else
- GL_CALL_TESSELATION_EXT(glPatchParameteri(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount));
+ GL_CALL_TESSELLATION_EXT(glPatchParameteri(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount));
#endif
}
diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp
index 1391565..1b0b304 100644
--- a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp
+++ b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp
@@ -755,7 +755,8 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
NVRenderTexture2D *inDepthTexture, NVRenderTexture2D *inSSaoTexture,
SImage *inLightProbe, SImage *inLightProbe2, QT3DSF32 inProbeHorizon,
QT3DSF32 inProbeBright, QT3DSF32 inProbe2Window, QT3DSF32 inProbe2Pos,
- QT3DSF32 inProbe2Fade, QT3DSF32 inProbeFOV)
+ QT3DSF32 inProbe2Fade, QT3DSF32 inProbeFOV,
+ const QT3DSVec2 &alphaOpRef)
{
ICustomMaterialSystem &theMaterialSystem(m_RenderContext.GetCustomMaterialSystem());
SShaderGeneratorGeneratedShader &theShader(GetShaderForProgram(inProgram));
@@ -858,12 +859,13 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
}
void SetMaterialProperties(NVRenderShaderProgram &inProgram,
- const SGraphObject &inMaterial, const QT3DSVec2 &inCameraVec,
- const QT3DSMat44 &inModelViewProjection,
- const QT3DSMat33 &inNormalMatrix,
- const QT3DSMat44 &inGlobalTransform,
- SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
- SLayerGlobalRenderProperties inRenderProperties) override
+ const SGraphObject &inMaterial, const QT3DSVec2 &inCameraVec,
+ const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix,
+ const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ SLayerGlobalRenderProperties inRenderProperties,
+ const QT3DSVec2 &alphaOpRef) override
{
const SCustomMaterial &theCustomMaterial(
reinterpret_cast<const SCustomMaterial &>(inMaterial));
@@ -880,7 +882,8 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
inRenderProperties.m_LightProbe, inRenderProperties.m_LightProbe2,
inRenderProperties.m_ProbeHorizon, inRenderProperties.m_ProbeBright,
inRenderProperties.m_Probe2Window, inRenderProperties.m_Probe2Pos,
- inRenderProperties.m_Probe2Fade, inRenderProperties.m_ProbeFOV);
+ inRenderProperties.m_Probe2Fade, inRenderProperties.m_ProbeFOV,
+ alphaOpRef);
}
void GenerateLightmapIndirectFunc(IShaderStageGenerator &inFragmentShader,
@@ -1207,7 +1210,8 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
m_GeneratedShaderString.assign(nonNull(inShaderPrefix));
m_GeneratedShaderString.append(inCustomMaterialName);
SShaderDefaultMaterialKey theKey(Key());
- theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties);
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties,
+ SShaderDefaultMaterialKeyProperties::DefaultKey);
// Add hash of the shader code to the cache key so that custom materials with the same name
// can have different shaders and the shaders are recompiled when the code is changed
diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h
index 44e2c06..29c31ff 100644
--- a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h
+++ b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h
@@ -58,7 +58,8 @@ namespace render {
const QT3DSVec2 &inCameraVec, const QT3DSMat44 &inModelViewProjection,
const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
- SLayerGlobalRenderProperties inRenderProperties) override = 0;
+ SLayerGlobalRenderProperties inRenderProperties,
+ const QT3DSVec2 &alphaOpRef) override = 0;
static ICustomMaterialShaderGenerator &
CreateCustomMaterialShaderGenerator(IQt3DSRenderContext &inRenderContext);
diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp
index 470014f..62d9805 100644
--- a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp
+++ b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp
@@ -662,8 +662,8 @@ typedef eastl::pair<CRegisteredString, NVScopedRefCounted<SCustomMaterialTexture
*/
struct SCustomMaterialsTessellationProperties
{
- NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessLevel; ///< tesselation value for the edges
- NVRenderCachedShaderProperty<QT3DSF32> m_InsideTessLevel; ///< tesselation value for the inside
+ NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessLevel; ///< tessellation value for the edges
+ NVRenderCachedShaderProperty<QT3DSF32> m_InsideTessLevel; ///< tessellation value for the inside
NVRenderCachedShaderProperty<QT3DSF32>
m_PhongBlend; ///< blending between linear and phong component
NVRenderCachedShaderProperty<QT3DSVec2>
@@ -1684,7 +1684,7 @@ struct SMaterialSystem : public ICustomMaterialSystem
*inShader.m_Shader, inRenderContext.m_Material, QT3DSVec2(1.0, 1.0),
inRenderContext.m_ModelViewProjection, inRenderContext.m_NormalMatrix,
inRenderContext.m_ModelMatrix, inRenderContext.m_FirstImage, inRenderContext.m_Opacity,
- GetLayerGlobalRenderProperties(inRenderContext));
+ GetLayerGlobalRenderProperties(inRenderContext), QT3DSVec2());
NVRenderContext &theContext(m_Context->GetRenderContext());
theContext.SetRenderTarget(inFrameBuffer);
@@ -1702,7 +1702,7 @@ struct SMaterialSystem : public ICustomMaterialSystem
// for this frame
NVRenderDrawMode::Enum theDrawMode = inAssembler.GetPrimitiveType();
- // tesselation
+ // tessellation
if (inRenderContext.m_Subset.m_PrimitiveType == NVRenderDrawMode::Patches) {
QT3DSVec2 camProps(inRenderContext.m_Camera.m_ClipNear,
inRenderContext.m_Camera.m_ClipFar);
diff --git a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
index cf276e7..4a1f6e3 100644
--- a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
+++ b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
@@ -170,6 +170,7 @@ struct SShaderGeneratorGeneratedShader
NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe2;
NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbe2Props;
NVRenderCachedShaderProperty<QT3DSVec2> m_LightProbe2Size;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_alphaTestOp;
NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AoShadowParams;
NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_LightsBuffer;
@@ -216,9 +217,10 @@ struct SShaderGeneratorGeneratedShader
, m_LightProbe2("light_probe2", inShader)
, m_LightProbe2Props("light_probe2_props", inShader)
, m_LightProbe2Size("light_probe2_size", inShader)
+ , m_alphaTestOp("alphaOpRef", inShader)
, m_AoShadowParams("cbAoShadow", inShader)
, m_LightsBuffer("cbBufferLights", inShader)
- , m_lightConstantProperties(NULL)
+ , m_lightConstantProperties(nullptr)
, m_Images(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_Images")
, m_Lights(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_Lights")
, m_ShadowMaps(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_ShadowMaps")
@@ -316,11 +318,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
SShaderGenerator(IQt3DSRenderContext &inRc)
: m_RenderContext(inRc)
, m_ProgramGenerator(m_RenderContext.GetShaderProgramGenerator())
- , m_CurrentMaterial(NULL)
- , m_CurrentKey(NULL)
- , m_ShadowMapManager(NULL)
- , m_CurrentPipeline(NULL)
- , m_FirstImage(NULL)
+ , m_CurrentMaterial(nullptr)
+ , m_CurrentKey(nullptr)
+ , m_ShadowMapManager(nullptr)
+ , m_CurrentPipeline(nullptr)
+ , m_FirstImage(nullptr)
, m_LightsAsSeparateUniforms(false)
, m_ProgramToShaderMap(inRc.GetAllocator(), "m_ProgramToShaderMap")
, m_ConstantBuffers(inRc.GetAllocator(), "m_ConstantBuffers")
@@ -546,7 +548,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
void AddTranslucencyIrradiance(IShaderStageGenerator &infragmentShader, SRenderableImage *image,
TStrType inLightPrefix, bool areaLight)
{
- if (image == NULL)
+ if (image == nullptr)
return;
addFunction(infragmentShader, "diffuseReflectionWrapBSDF");
@@ -792,7 +794,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
// we only create if if we have lights
if (!inLightCount || !theContext.GetConstantBufferSupport())
- return NULL;
+ return nullptr;
CRegisteredString theName = theContext.GetStringTable().RegisterStr("cbBufferLights");
NVRenderConstantBuffer *pCB = theContext.GetConstantBuffer(theName);
@@ -807,7 +809,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
(sizeof(SLightSourceShader) * QT3DS_MAX_NUM_LIGHTS) + (4 * sizeof(QT3DSI32)), cBuffer);
if (!pCB) {
QT3DS_ASSERT(false);
- return NULL;
+ return nullptr;
}
// init first set
memset(&s[0], 0x0, sizeof(SLightSourceShader));
@@ -888,10 +890,10 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
{
// vertex displacement
QT3DSU32 imageIdx = 0;
- SRenderableImage *displacementImage = NULL;
+ SRenderableImage *displacementImage = nullptr;
QT3DSU32 displacementImageIdx = 0;
- for (SRenderableImage *img = m_FirstImage; img != NULL;
+ for (SRenderableImage *img = m_FirstImage; img != nullptr;
img = img->m_NextImage, ++imageIdx) {
if (img->m_MapType == ImageMapTypes::Displacement) {
displacementImage = img;
@@ -910,7 +912,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
bool vertexColorsEnabled = Material().IsVertexColorsEnabled();
bool hasLighting = Material().HasLighting();
- bool hasImage = m_FirstImage != NULL;
+ bool hasImage = m_FirstImage != nullptr;
bool hasIblProbe = m_DefaultMaterialShaderKeyProperties.m_HasIbl.GetValue(inKey);
bool hasSpecMap = false;
@@ -918,30 +920,30 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
bool hasEmissiveMap = false;
bool hasLightmaps = false;
// Pull the bump out as
- SRenderableImage *bumpImage = NULL;
+ SRenderableImage *bumpImage = nullptr;
QT3DSU32 imageIdx = 0;
QT3DSU32 bumpImageIdx = 0;
- SRenderableImage *specularAmountImage = NULL;
+ SRenderableImage *specularAmountImage = nullptr;
QT3DSU32 specularAmountImageIdx = 0;
- SRenderableImage *roughnessImage = NULL;
+ SRenderableImage *roughnessImage = nullptr;
QT3DSU32 roughnessImageIdx = 0;
// normal mapping
- SRenderableImage *normalImage = NULL;
+ SRenderableImage *normalImage = nullptr;
QT3DSU32 normalImageIdx = 0;
// translucency map
- SRenderableImage *translucencyImage = NULL;
+ SRenderableImage *translucencyImage = nullptr;
QT3DSU32 translucencyImageIdx = 0;
// lightmaps
- SRenderableImage *lightmapIndirectImage = NULL;
+ SRenderableImage *lightmapIndirectImage = nullptr;
QT3DSU32 lightmapIndirectImageIdx = 0;
- SRenderableImage *lightmapRadiosityImage = NULL;
+ SRenderableImage *lightmapRadiosityImage = nullptr;
QT3DSU32 lightmapRadiosityImageIdx = 0;
- SRenderableImage *lightmapShadowImage = NULL;
+ SRenderableImage *lightmapShadowImage = nullptr;
QT3DSU32 lightmapShadowImageIdx = 0;
const bool supportStandardDerivatives
= m_RenderContext.GetRenderContext().IsStandardDerivativesSupported();
- for (SRenderableImage *img = m_FirstImage; img != NULL;
+ for (SRenderableImage *img = m_FirstImage; img != nullptr;
img = img->m_NextImage, ++imageIdx) {
hasSpecMap = img->m_MapType == ImageMapTypes::Specular;
if (img->m_MapType == ImageMapTypes::Bump) {
@@ -983,6 +985,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
bool enableSSDO = false;
bool enableShadowMaps = false;
bool enableBumpNormal = normalImage || bumpImage;
+ bool enableAlphaTest
+ = m_DefaultMaterialShaderKeyProperties.m_AlphaTestEnabled.GetValue(inKey);
for (QT3DSU32 idx = 0; idx < FeatureSet().size(); ++idx) {
eastl::string name(FeatureSet()[idx].m_Name.c_str());
@@ -1051,7 +1055,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
fragmentShader.Append("\tvec3 vertColor = vec3(1.0);");
// You do bump or normal mapping but not both
- if (bumpImage != NULL) {
+ if (bumpImage != nullptr) {
GenerateImageUVCoordinates(bumpImageIdx, *bumpImage);
fragmentShader.AddUniform("bumpAmount", "float");
@@ -1065,7 +1069,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
fragmentShader << "\tbinormal = normalize(cross(world_normal, tangent) );\n";
fragmentShader << "\ttangent = normalize(cross(binormal, world_normal) );\n";
- } else if (normalImage != NULL) {
+ } else if (normalImage != nullptr) {
GenerateImageUVCoordinates(normalImageIdx, *normalImage);
fragmentShader.AddInclude("defaultMaterialFileNormalTexture.glsllib");
@@ -1098,7 +1102,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
fragmentShader.AddUniform("material_properties", "vec4");
}
- if (lightmapIndirectImage != NULL) {
+ if (lightmapIndirectImage != nullptr) {
GenerateImageUVCoordinates(lightmapIndirectImageIdx, *lightmapIndirectImage, 1);
fragmentShader << "\tvec4 indirect_light = texture2D( " << m_ImageSampler << ", "
<< m_ImageFragCoords << ");" << Endl;
@@ -1110,7 +1114,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
}
- if (lightmapRadiosityImage != NULL) {
+ if (lightmapRadiosityImage != nullptr) {
GenerateImageUVCoordinates(lightmapRadiosityImageIdx, *lightmapRadiosityImage, 1);
fragmentShader << "\tvec4 direct_light = texture2D( " << m_ImageSampler << ", "
<< m_ImageFragCoords << ");" << Endl;
@@ -1122,7 +1126,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
}
- if (translucencyImage != NULL) {
+ if (translucencyImage != nullptr) {
fragmentShader.AddUniform("translucentFalloff", "float");
fragmentShader.AddUniform("diffuseLightWrap", "float");
@@ -1478,6 +1482,14 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
}
+ // Alpha test
+ if (enableAlphaTest) {
+ fragmentShader.AddUniform("alphaOpRef", "vec2");
+ fragmentShader.Append(
+ "\tif (dot(vec2(global_diffuse_light.a, 1.0), alphaOpRef) <= 0.0)\n"
+ "\t\tdiscard;");
+ }
+
if (hasEmissiveMap) {
fragmentShader.Append("\tglobal_diffuse_light.rgb += global_emission.rgb;");
}
@@ -1498,6 +1510,343 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
}
+ // generate default material shader for depth only pass
+ NVRenderShaderProgram *GenerateDepthPassShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override
+ {
+ QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::DefaultMaterial);
+ m_CurrentMaterial = static_cast<const SDefaultMaterial *>(&inMaterial);
+ m_CurrentKey = &inShaderDescription;
+ m_CurrentPipeline = static_cast<IDefaultMaterialVertexPipeline *>(&inVertexPipeline);
+ m_CurrentFeatureSet = inFeatureSet;
+ m_FirstImage = inFirstImage;
+ m_HasTransparency = inHasTransparency;
+
+ ProgramGenerator().BeginProgram();
+
+ bool enableAlphaTest = m_DefaultMaterialShaderKeyProperties
+ .m_AlphaTestEnabled.GetValue(inShaderDescription);
+
+ QT3DS_ASSERT(m_FirstImage != nullptr);
+ if (!enableAlphaTest)
+ return nullptr;
+ QT3DS_ASSERT(enableAlphaTest);
+
+ m_GeneratedShaderString.clear();
+ m_GeneratedShaderString.assign(nonNull(inVertexPipelineName));
+ m_GeneratedShaderString.append("depth--");
+
+ SShaderDefaultMaterialKey theKey(Key());
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties,
+ SShaderDefaultMaterialKeyProperties::DepthKey);
+
+ m_LightsAsSeparateUniforms = !m_RenderContext.GetRenderContext().GetConstantBufferSupport();
+
+ VertexGenerator().BeginFragmentGeneration();
+ IShaderStageGenerator &fragmentShader(FragmentGenerator());
+ IDefaultMaterialVertexPipeline &vertexShader(VertexGenerator());
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append("\tvec3 uTransform;");
+ vertexShader.Append("\tvec3 vTransform;");
+
+ fragmentShader << "\tfloat global_opacity = object_opacity;" << Endl;
+
+ fragmentShader.Append("\tvec4 texture_color;");
+ QT3DSU32 idx = 0;
+ for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
+ // Various maps are handled on a different locations
+ if (image->m_MapType == ImageMapTypes::Bump
+ || image->m_MapType == ImageMapTypes::Normal
+ || image->m_MapType == ImageMapTypes::Displacement
+ || image->m_MapType == ImageMapTypes::SpecularAmountMap
+ || image->m_MapType == ImageMapTypes::Roughness
+ || image->m_MapType == ImageMapTypes::Translucency
+ || image->m_MapType == ImageMapTypes::LightmapIndirect
+ || image->m_MapType == ImageMapTypes::LightmapRadiosity
+ || image->m_MapType == ImageMapTypes::Emissive) {
+ continue;
+ }
+
+ eastl::basic_string<char8_t> texSwizzle, lookupSwizzle, texLodStr;
+
+ GenerateImageUVCoordinates(idx, *image, 0);
+
+ GenerateTextureSwizzle(
+ image->m_Image.m_TextureData.m_Texture->GetTextureSwizzleMode(), texSwizzle,
+ lookupSwizzle);
+
+ if (texLodStr.empty()) {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ")"
+ << lookupSwizzle.c_str() << ";" << Endl;
+ } else {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ", "
+ << texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
+ << Endl;
+ }
+
+ switch (image->m_MapType) {
+ case ImageMapTypes::Diffuse: // assume images are premultiplied.
+ case ImageMapTypes::LightmapShadow:
+ case ImageMapTypes::Specular:
+ case ImageMapTypes::Opacity:
+ fragmentShader.Append("\tglobal_opacity *= texture_color.a;");
+ break;
+ default:
+ break;
+ }
+ }
+
+ fragmentShader.AddUniform("alphaOpRef", "vec2");
+ fragmentShader.Append("\tif (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
+ "\t\tdiscard;");
+ fragmentShader.Append("\tfragOutput = vec4(0.0);");
+ fragmentShader.Append("}");
+ vertexShader.Append("}");
+
+ return ProgramGenerator().CompileGeneratedShader(m_GeneratedShaderString.c_str(),
+ SShaderCacheProgramFlags(), FeatureSet());
+
+ }
+
+ // generate default material shader cube depth shader
+ NVRenderShaderProgram *GenerateCubeDepthShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override
+ {
+ QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::DefaultMaterial);
+ m_CurrentMaterial = static_cast<const SDefaultMaterial *>(&inMaterial);
+ m_CurrentKey = &inShaderDescription;
+ m_CurrentPipeline = static_cast<IDefaultMaterialVertexPipeline *>(&inVertexPipeline);
+ m_CurrentFeatureSet = inFeatureSet;
+ m_FirstImage = inFirstImage;
+ m_HasTransparency = inHasTransparency;
+
+ ProgramGenerator().BeginProgram();
+
+ bool enableAlphaTest = m_DefaultMaterialShaderKeyProperties
+ .m_AlphaTestEnabled.GetValue(inShaderDescription);
+
+ QT3DS_ASSERT(m_FirstImage != nullptr);
+ if (!enableAlphaTest)
+ return nullptr;
+ QT3DS_ASSERT(enableAlphaTest);
+
+ m_GeneratedShaderString.clear();
+ m_GeneratedShaderString.assign(nonNull(inVertexPipelineName));
+ m_GeneratedShaderString.append("shadowcube--");
+
+ SShaderDefaultMaterialKey theKey(Key());
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties,
+ SShaderDefaultMaterialKeyProperties::DepthKey);
+
+ m_LightsAsSeparateUniforms = !m_RenderContext.GetRenderContext().GetConstantBufferSupport();
+
+ VertexGenerator().BeginFragmentGeneration();
+ IShaderStageGenerator &fragmentShader(FragmentGenerator());
+ IDefaultMaterialVertexPipeline &vertexShader(VertexGenerator());
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddUniform("model_matrix", "mat4");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.AddOutgoing("raw_pos", "vec4");
+ vertexShader.AddOutgoing("world_pos", "vec4");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tvec3 uTransform;");
+ vertexShader.Append("\tvec3 vTransform;");
+ vertexShader.Append("\tworld_pos = model_matrix * vec4( attr_pos, 1.0 );");
+ vertexShader.Append("\tworld_pos /= world_pos.w;");
+ vertexShader.Append("\tgl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append("\traw_pos = vec4( attr_pos, 1.0 );");
+
+ fragmentShader << "\tfloat global_opacity = object_opacity;" << Endl;
+
+ fragmentShader.Append("\tvec4 texture_color;");
+ QT3DSU32 idx = 0;
+ for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
+ // Various maps are handled on different locations
+ if (image->m_MapType == ImageMapTypes::Bump
+ || image->m_MapType == ImageMapTypes::Normal
+ || image->m_MapType == ImageMapTypes::Displacement
+ || image->m_MapType == ImageMapTypes::SpecularAmountMap
+ || image->m_MapType == ImageMapTypes::Roughness
+ || image->m_MapType == ImageMapTypes::Translucency
+ || image->m_MapType == ImageMapTypes::LightmapIndirect
+ || image->m_MapType == ImageMapTypes::LightmapRadiosity
+ || image->m_MapType == ImageMapTypes::Emissive) {
+ continue;
+ }
+
+ eastl::basic_string<char8_t> texSwizzle, lookupSwizzle, texLodStr;
+
+ GenerateImageUVCoordinates(idx, *image, 0);
+
+ GenerateTextureSwizzle(
+ image->m_Image.m_TextureData.m_Texture->GetTextureSwizzleMode(), texSwizzle,
+ lookupSwizzle);
+
+ if (texLodStr.empty()) {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ")"
+ << lookupSwizzle.c_str() << ";" << Endl;
+ } else {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ", "
+ << texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
+ << Endl;
+ }
+
+ switch (image->m_MapType) {
+ case ImageMapTypes::Diffuse: // assume images are premultiplied.
+ case ImageMapTypes::LightmapShadow:
+ case ImageMapTypes::Specular:
+ case ImageMapTypes::Opacity:
+ fragmentShader.Append("\tglobal_opacity *= texture_color.a;");
+ break;
+ default:
+ break;
+ }
+ }
+
+ fragmentShader.AddUniform("camera_position", "vec3");
+ fragmentShader.AddUniform("camera_properties", "vec2");
+ fragmentShader.Append("\tvec3 camPos = vec3(camera_position.x, camera_position.y, "
+ "-camera_position.z);");
+ fragmentShader.Append("\tfloat dist = length(world_pos.xyz - camPos);");
+ fragmentShader.Append("\tdist = max((dist - 1.0) / (camera_properties.y - 1.0), 0.0);");
+ fragmentShader.AddUniform("alphaOpRef", "vec2");
+ fragmentShader.Append("\tif (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
+ "\t\tdist = 1.0;");
+ fragmentShader.Append("\tfragOutput = vec4(dist);");
+ fragmentShader.Append("}");
+
+ vertexShader.Append("}");
+
+ return ProgramGenerator().CompileGeneratedShader(m_GeneratedShaderString.c_str(),
+ SShaderCacheProgramFlags(), FeatureSet());
+ }
+
+ // generate default material shader orthographic depth shader
+ NVRenderShaderProgram *GenerateOrthoDepthShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override
+ {
+ QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::DefaultMaterial);
+ m_CurrentMaterial = static_cast<const SDefaultMaterial *>(&inMaterial);
+ m_CurrentKey = &inShaderDescription;
+ m_CurrentPipeline = static_cast<IDefaultMaterialVertexPipeline *>(&inVertexPipeline);
+ m_CurrentFeatureSet = inFeatureSet;
+ m_FirstImage = inFirstImage;
+ m_HasTransparency = inHasTransparency;
+
+ ProgramGenerator().BeginProgram();
+
+ bool enableAlphaTest = m_DefaultMaterialShaderKeyProperties
+ .m_AlphaTestEnabled.GetValue(inShaderDescription);
+
+ QT3DS_ASSERT(m_FirstImage != nullptr);
+ if (!enableAlphaTest)
+ return nullptr;
+ QT3DS_ASSERT(enableAlphaTest);
+
+ m_GeneratedShaderString.clear();
+ m_GeneratedShaderString.assign(nonNull(inVertexPipelineName));
+ m_GeneratedShaderString.append("shadowmap--");
+
+ SShaderDefaultMaterialKey theKey(Key());
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties,
+ SShaderDefaultMaterialKeyProperties::DepthKey);
+
+ m_LightsAsSeparateUniforms = !m_RenderContext.GetRenderContext().GetConstantBufferSupport();
+
+ VertexGenerator().BeginFragmentGeneration();
+ IShaderStageGenerator &fragmentShader(FragmentGenerator());
+ IDefaultMaterialVertexPipeline &vertexShader(VertexGenerator());
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.AddOutgoing("outDepth", "vec3");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tvec3 uTransform;");
+ vertexShader.Append("\tvec3 vTransform;");
+ vertexShader.Append("\tgl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;");
+
+ fragmentShader << "\tfloat global_opacity = object_opacity;" << Endl;
+
+ fragmentShader.Append("\tvec4 texture_color;");
+ QT3DSU32 idx = 0;
+ for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
+ // Various maps are handled on different locations
+ if (image->m_MapType == ImageMapTypes::Bump
+ || image->m_MapType == ImageMapTypes::Normal
+ || image->m_MapType == ImageMapTypes::Displacement
+ || image->m_MapType == ImageMapTypes::SpecularAmountMap
+ || image->m_MapType == ImageMapTypes::Roughness
+ || image->m_MapType == ImageMapTypes::Translucency
+ || image->m_MapType == ImageMapTypes::LightmapIndirect
+ || image->m_MapType == ImageMapTypes::LightmapRadiosity
+ || image->m_MapType == ImageMapTypes::Emissive) {
+ continue;
+ }
+
+ eastl::basic_string<char8_t> texSwizzle, lookupSwizzle, texLodStr;
+
+ GenerateImageUVCoordinates(idx, *image, 0);
+
+ GenerateTextureSwizzle(
+ image->m_Image.m_TextureData.m_Texture->GetTextureSwizzleMode(), texSwizzle,
+ lookupSwizzle);
+
+ if (texLodStr.empty()) {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ")"
+ << lookupSwizzle.c_str() << ";" << Endl;
+ } else {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ", "
+ << texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
+ << Endl;
+ }
+
+ switch (image->m_MapType) {
+ case ImageMapTypes::Diffuse: // assume images are premultiplied.
+ case ImageMapTypes::LightmapShadow:
+ case ImageMapTypes::Specular:
+ case ImageMapTypes::Opacity:
+ fragmentShader.Append("\tglobal_opacity *= texture_color.a;");
+ break;
+ default:
+ break;
+ }
+ }
+
+ fragmentShader.AddUniform("alphaOpRef", "vec2");
+ fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;");
+ fragmentShader.Append("\tif (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
+ "\t\tdepth = 1.0;");
+ fragmentShader.Append("\tfragOutput = vec4(depth);");
+ fragmentShader.Append("}");
+ vertexShader.Append("}");
+
+ return ProgramGenerator().CompileGeneratedShader(m_GeneratedShaderString.c_str(),
+ SShaderCacheProgramFlags(), FeatureSet());
+ }
+
NVRenderShaderProgram *GenerateMaterialShader(const char8_t *inShaderPrefix)
{
// build a string that allows us to print out the shader we are generating to the log.
@@ -1509,7 +1858,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
m_GeneratedShaderString.assign(nonNull(inShaderPrefix));
SShaderDefaultMaterialKey theKey(Key());
- theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties);
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties,
+ SShaderDefaultMaterialKeyProperties::DefaultKey);
m_LightsAsSeparateUniforms = !m_RenderContext.GetRenderContext().GetConstantBufferSupport();
@@ -1545,7 +1895,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
{
eastl::pair<TProgramToShaderMap::iterator, bool> inserter =
m_ProgramToShaderMap.insert(eastl::make_pair(
- &inProgram, NVScopedRefCounted<SShaderGeneratorGeneratedShader>(NULL)));
+ &inProgram, NVScopedRefCounted<SShaderGeneratorGeneratedShader>(nullptr)));
if (inserter.second) {
NVAllocatorCallback &alloc(m_RenderContext.GetRenderContext().GetAllocator());
inserter.first->second = QT3DS_NEW(alloc, SShaderGeneratorGeneratedShader)(
@@ -1671,7 +2021,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
NVRenderTexture2D *inDepthTexture, NVRenderTexture2D *inSSaoTexture,
SImage *inLightProbe, SImage *inLightProbe2, QT3DSF32 inProbeHorizon,
QT3DSF32 inProbeBright, QT3DSF32 inProbe2Window, QT3DSF32 inProbe2Pos,
- QT3DSF32 inProbe2Fade, QT3DSF32 inProbeFOV)
+ QT3DSF32 inProbe2Fade, QT3DSF32 inProbeFOV,
+ const QT3DSVec2 &alphaOpRef)
{
NVRenderContext &context(m_RenderContext.GetRenderContext());
@@ -1776,6 +2127,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
shader.m_MaterialSpecular.Set(material_specular);
shader.m_CameraProperties.Set(inCameraVec);
shader.m_FresnelPower.Set(inMaterial.m_FresnelPower);
+ shader.m_alphaTestOp.Set(alphaOpRef);
if (context.GetConstantBufferSupport()) {
NVRenderConstantBuffer *pLightCb = GetLightConstantBuffer(shader.m_Lights.size());
@@ -1885,12 +2237,13 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
context.SetBlendEquation(blendEqua);
}
void SetMaterialProperties(NVRenderShaderProgram &inProgram,
- const SGraphObject &inMaterial, const QT3DSVec2 &inCameraVec,
- const QT3DSMat44 &inModelViewProjection,
- const QT3DSMat33 &inNormalMatrix,
- const QT3DSMat44 &inGlobalTransform,
- SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
- SLayerGlobalRenderProperties inRenderProperties) override
+ const SGraphObject &inMaterial, const QT3DSVec2 &inCameraVec,
+ const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix,
+ const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ SLayerGlobalRenderProperties inRenderProperties,
+ const QT3DSVec2 &alphaOpRef) override
{
const SDefaultMaterial &theMaterial(static_cast<const SDefaultMaterial &>(inMaterial));
QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::DefaultMaterial);
@@ -1905,7 +2258,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
inRenderProperties.m_LightProbe, inRenderProperties.m_LightProbe2,
inRenderProperties.m_ProbeHorizon, inRenderProperties.m_ProbeBright,
inRenderProperties.m_Probe2Window, inRenderProperties.m_Probe2Pos,
- inRenderProperties.m_Probe2Fade, inRenderProperties.m_ProbeFOV);
+ inRenderProperties.m_Probe2Fade, inRenderProperties.m_ProbeFOV,
+ alphaOpRef);
}
SLightConstantProperties<SShaderGeneratorGeneratedShader> *GetLightConstantProperties(SShaderGeneratorGeneratedShader &shader)
diff --git a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h
index 7453e1d..871ab1b 100644
--- a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h
+++ b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h
@@ -103,13 +103,35 @@ namespace render {
NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency,
const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override = 0;
+ // generate default material shader for depth only pass
+ virtual NVRenderShaderProgram *GenerateDepthPassShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") = 0;
+
+ // generate default material shader cube depth shader
+ virtual NVRenderShaderProgram *GenerateCubeDepthShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") = 0;
+
+ // generate default material shader orthographic depth shader
+ virtual NVRenderShaderProgram *GenerateOrthoDepthShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") = 0;
+
// Also sets the blend function on the render context.
virtual void
SetMaterialProperties(NVRenderShaderProgram &inProgram, const SGraphObject &inMaterial,
const QT3DSVec2 &inCameraVec, const QT3DSMat44 &inModelViewProjection,
const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
- SLayerGlobalRenderProperties inRenderProperties) override = 0;
+ SLayerGlobalRenderProperties inRenderProperties,
+ const QT3DSVec2 &alphaOpRef) override = 0;
static IDefaultMaterialShaderGenerator &
CreateDefaultMaterialShaderGenerator(IQt3DSRenderContext &inRenderContext);
diff --git a/src/runtimerender/Qt3DSRenderImageTextureData.h b/src/runtimerender/Qt3DSRenderImageTextureData.h
index aaa73d7..a029451 100644
--- a/src/runtimerender/Qt3DSRenderImageTextureData.h
+++ b/src/runtimerender/Qt3DSRenderImageTextureData.h
@@ -48,6 +48,7 @@ namespace render {
HasTransparency = 1,
InvertUVCoords = 1 << 1,
PreMultiplied = 1 << 2,
+ HasOpaquePixels = 1 << 3,
};
};
@@ -55,7 +56,7 @@ namespace render {
{
bool HasTransparency() const
{
- return this->operator&(ImageTextureFlagValues::HasTransparency);
+ return *this & ImageTextureFlagValues::HasTransparency;
}
void SetHasTransparency(bool inValue)
{
@@ -64,7 +65,7 @@ namespace render {
bool IsInvertUVCoords() const
{
- return this->operator&(ImageTextureFlagValues::InvertUVCoords);
+ return *this & ImageTextureFlagValues::InvertUVCoords;
}
void SetInvertUVCoords(bool inValue)
{
@@ -73,12 +74,21 @@ namespace render {
bool IsPreMultiplied() const
{
- return this->operator&(ImageTextureFlagValues::PreMultiplied);
+ return *this & ImageTextureFlagValues::PreMultiplied;
}
void SetPreMultiplied(bool inValue)
{
clearOrSet(inValue, ImageTextureFlagValues::PreMultiplied);
}
+
+ bool HasOpaquePixels() const
+ {
+ return *this & ImageTextureFlagValues::HasOpaquePixels;
+ }
+ void setHasOpaquePixels(bool inValue)
+ {
+ clearOrSet(inValue, ImageTextureFlagValues::HasOpaquePixels);
+ }
};
struct SImageTextureData
diff --git a/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h b/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h
index e8b9880..88858bd 100644
--- a/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h
+++ b/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h
@@ -144,7 +144,8 @@ namespace render {
const QT3DSVec2 &inCameraVec, const QT3DSMat44 &inModelViewProjection,
const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
- SLayerGlobalRenderProperties inRenderProperties) = 0;
+ SLayerGlobalRenderProperties inRenderProperties,
+ const QT3DSVec2 &alphaOpRef) = 0;
};
}
}
diff --git a/src/runtimerender/Qt3DSRenderPathManager.cpp b/src/runtimerender/Qt3DSRenderPathManager.cpp
index 5b2c51d..b845ead 100644
--- a/src/runtimerender/Qt3DSRenderPathManager.cpp
+++ b/src/runtimerender/Qt3DSRenderPathManager.cpp
@@ -1433,7 +1433,7 @@ struct SPathManager : public IPathManager
inShader, inRenderContext.m_Material, inRenderContext.m_CameraVec,
inRenderContext.m_ModelViewProjection, inRenderContext.m_NormalMatrix,
inRenderContext.m_Path.m_GlobalTransform, inRenderContext.m_FirstImage,
- inRenderContext.m_Opacity, inRenderProperties);
+ inRenderContext.m_Opacity, inRenderProperties, QT3DSVec2());
}
void DoRenderGeometryPath(SPathGeneratedShader &inShader, SPathRenderContext &inRenderContext,
diff --git a/src/runtimerender/Qt3DSRenderShaderKeys.h b/src/runtimerender/Qt3DSRenderShaderKeys.h
index 5d02e41..298c198 100644
--- a/src/runtimerender/Qt3DSRenderShaderKeys.h
+++ b/src/runtimerender/Qt3DSRenderShaderKeys.h
@@ -558,6 +558,12 @@ namespace render {
ImageMapCount
};
+ enum KeyMode
+ {
+ DefaultKey,
+ DepthKey,
+ };
+
SShaderKeyBoolean m_HasLighting;
SShaderKeyBoolean m_HasIbl;
SShaderKeyUnsigned<3> m_LightCount;
@@ -566,6 +572,7 @@ namespace render {
SShaderKeyBoolean m_LightShadowFlags[LightCount];
SShaderKeyBoolean m_SpecularEnabled;
SShaderKeyBoolean m_FresnelEnabled;
+ SShaderKeyBoolean m_AlphaTestEnabled;
SShaderKeyBoolean m_VertexColorsEnabled;
SShaderKeySpecularModel m_SpecularModel;
SShaderKeyImageMap m_ImageMaps[ImageMapCount];
@@ -580,6 +587,7 @@ namespace render {
, m_LightCount("lightCount")
, m_SpecularEnabled("specularEnabled")
, m_FresnelEnabled("fresnelEnabled")
+ , m_AlphaTestEnabled("alphaTestEnabled")
, m_VertexColorsEnabled("vertexColorsEnabled")
, m_SpecularModel("specularModel")
, m_TessellationMode("tessellationMode")
@@ -642,38 +650,50 @@ namespace render {
SetPropertyOffsets();
}
+ bool isDepthKeyImage(QT3DSU32 idx) const
+ {
+ if (idx == DiffuseMap0 || idx == DiffuseMap1 || idx == DiffuseMap2 || idx == SpecularMap
+ || idx == OpacityMap || idx == LightmapShadow) {
+ return true;
+ }
+ return false;
+ }
+
template <typename TVisitor>
- void VisitProperties(TVisitor &inVisitor)
+ void VisitProperties(TVisitor &inVisitor, KeyMode mode)
{
- inVisitor.Visit(m_HasLighting);
- inVisitor.Visit(m_HasIbl);
- inVisitor.Visit(m_LightCount);
+ if (mode == DefaultKey) {
+ inVisitor.Visit(m_HasLighting);
+ inVisitor.Visit(m_HasIbl);
+ inVisitor.Visit(m_LightCount);
- for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
- inVisitor.Visit(m_LightFlags[idx]);
- }
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx)
+ inVisitor.Visit(m_LightFlags[idx]);
- for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
- inVisitor.Visit(m_LightAreaFlags[idx]);
- }
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx)
+ inVisitor.Visit(m_LightAreaFlags[idx]);
- for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
- inVisitor.Visit(m_LightShadowFlags[idx]);
- }
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx)
+ inVisitor.Visit(m_LightShadowFlags[idx]);
- inVisitor.Visit(m_SpecularEnabled);
- inVisitor.Visit(m_FresnelEnabled);
- inVisitor.Visit(m_VertexColorsEnabled);
- inVisitor.Visit(m_SpecularModel);
+ inVisitor.Visit(m_SpecularEnabled);
+ inVisitor.Visit(m_FresnelEnabled);
+ inVisitor.Visit(m_VertexColorsEnabled);
+ inVisitor.Visit(m_SpecularModel);
+ }
+ inVisitor.Visit(m_AlphaTestEnabled);
for (QT3DSU32 idx = 0, end = ImageMapCount; idx < end; ++idx) {
- inVisitor.Visit(m_ImageMaps[idx]);
- inVisitor.Visit(m_TextureSwizzle[idx]);
+ if (mode == DefaultKey || isDepthKeyImage(idx)) {
+ inVisitor.Visit(m_ImageMaps[idx]);
+ inVisitor.Visit(m_TextureSwizzle[idx]);
+ }
+ }
+ if (mode == DefaultKey) {
+ inVisitor.Visit(m_TessellationMode);
+ inVisitor.Visit(m_HasSkinning);
+ inVisitor.Visit(m_WireframeMode);
}
-
- inVisitor.Visit(m_TessellationMode);
- inVisitor.Visit(m_HasSkinning);
- inVisitor.Visit(m_WireframeMode);
}
struct SOffsetVisitor
@@ -703,7 +723,7 @@ namespace render {
void SetPropertyOffsets()
{
SOffsetVisitor visitor;
- VisitProperties(visitor);
+ VisitProperties(visitor, DefaultKey);
// If this assert fires, then the default material key needs more bits.
QT3DS_ASSERT(visitor.m_Offset < 224);
}
@@ -779,10 +799,11 @@ namespace render {
};
void ToString(eastl::string &ioString,
- SShaderDefaultMaterialKeyProperties &inProperties) const
+ SShaderDefaultMaterialKeyProperties &inProperties,
+ SShaderDefaultMaterialKeyProperties::KeyMode mode) const
{
SStringVisitor theVisitor(ioString, *this);
- inProperties.VisitProperties(theVisitor);
+ inProperties.VisitProperties(theVisitor, mode);
}
};
}
diff --git a/src/runtimerender/Qt3DSRenderUIPLoader.cpp b/src/runtimerender/Qt3DSRenderUIPLoader.cpp
index 4740839..3c8a0bf 100644
--- a/src/runtimerender/Qt3DSRenderUIPLoader.cpp
+++ b/src/runtimerender/Qt3DSRenderUIPLoader.cpp
@@ -1825,7 +1825,10 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
CRegisteredString imgPath = m_StrTable.RegisterStr(srcPath);
bool hasTransparency = false;
m_Reader.Att("hasTransparency", hasTransparency);
- m_BufferManager.SetImageHasTransparency(imgPath, hasTransparency);
+ bool hasOpaque = false;
+ m_Reader.Att("hasOpaquePixels", hasOpaque);
+ m_BufferManager.SetImageHasTransparency(imgPath, hasTransparency,
+ hasOpaque);
}
}
}
diff --git a/src/runtimerender/Qt3DSRenderer.h b/src/runtimerender/Qt3DSRenderer.h
index db3eee8..fb6c3de 100644
--- a/src/runtimerender/Qt3DSRenderer.h
+++ b/src/runtimerender/Qt3DSRenderer.h
@@ -100,6 +100,8 @@ namespace render {
virtual void EnableLayerGpuProfiling(bool inEnabled) = 0;
virtual bool IsLayerGpuProfilingEnabled() const = 0;
+ virtual void setAlphaTest(bool enable, float op, float ref) = 0;
+
// Get the camera that rendered this node last render
virtual SCamera *GetCameraForNode(const SNode &inNode) const = 0;
virtual Option<SCuboidRect> GetCameraBounds(const SGraphObject &inObject) = 0;
diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
index fff7e32..e3b570d 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
@@ -96,8 +96,8 @@ namespace render {
SShadowMapEntry *inShadowMapEntry)
{
NVRenderContext &context(m_Generator.GetContext());
- SRenderableDepthPrepassShader *shader = NULL;
- NVRenderInputAssembler *pIA = NULL;
+ SRenderableDepthPrepassShader *shader = nullptr;
+ NVRenderInputAssembler *pIA = nullptr;
/*
if ( inLight->m_LightType == RenderLightTypes::Area )
@@ -114,7 +114,7 @@ namespace render {
else
shader = m_Generator.GetCubeShadowDepthShader(m_TessellationMode);
- if (shader == NULL || inShadowMapEntry == NULL)
+ if (shader == nullptr || inShadowMapEntry == nullptr)
return;
// for phong and npatch tesselleation we need the normals too
@@ -144,7 +144,7 @@ namespace render {
shader->m_Projection.Set( inCamera.m_Projection );
*/
- // tesselation
+ // tessellation
if (m_TessellationMode != TessModeValues::NoTess) {
// set uniforms we need
shader->m_Tessellation.m_EdgeTessLevel.Set(m_Subset.m_EdgeTessFactor);
@@ -166,17 +166,18 @@ namespace render {
float inDisplacementAmount)
{
NVRenderContext &context(m_Generator.GetContext());
- SRenderableDepthPrepassShader *shader = NULL;
- NVRenderInputAssembler *pIA = NULL;
+ SRenderableDepthPrepassShader *shader = nullptr;
+ NVRenderInputAssembler *pIA = nullptr;
SRenderableImage *displacementImage = inDisplacementImage;
- if (m_Subset.m_PrimitiveType != NVRenderDrawMode::Patches)
- shader = m_Generator.GetDepthPrepassShader(displacementImage != NULL);
- else
+ if (m_Subset.m_PrimitiveType != NVRenderDrawMode::Patches) {
+ shader = m_Generator.GetDepthPrepassShader(displacementImage != nullptr);
+ } else {
shader = m_Generator.GetDepthTessPrepassShader(m_TessellationMode,
- displacementImage != NULL);
+ displacementImage != nullptr);
+ }
- if (shader == NULL)
+ if (shader == nullptr)
return;
// for phong and npatch tesselleation or displacement mapping we need the normals (and uv's)
@@ -214,7 +215,7 @@ namespace render {
displacementImage->m_Image.m_TextureData.m_Texture);
}
- // tesselation
+ // tessellation
if (m_TessellationMode != TessModeValues::NoTess) {
// set uniforms we need
shader->m_GlobalTransform.Set(m_GlobalTransform);
@@ -241,12 +242,18 @@ namespace render {
// An interface to the shader generator that is available to the renderables
- void SSubsetRenderable::Render(const QT3DSVec2 &inCameraVec, TShaderFeatureSet inFeatureSet)
+ void SSubsetRenderable::Render(const QT3DSVec2 &inCameraVec, TShaderFeatureSet inFeatureSet,
+ bool depth)
{
NVRenderContext &context(m_Generator.GetContext());
+ SShaderGeneratorGeneratedShader *shader = nullptr;
- SShaderGeneratorGeneratedShader *shader = m_Generator.GetShader(*this, inFeatureSet);
- if (shader == NULL)
+ // Do not render if alpha test is enabled, but no alpha test in object or vice versa
+ if (m_Generator.alphaTestEnabled() ^ m_RenderableFlags.hasAlphaTest())
+ return;
+
+ shader = m_Generator.GetShader(*this, inFeatureSet, depth);
+ if (shader == nullptr)
return;
context.SetActiveShader(&shader->m_Shader);
@@ -254,9 +261,10 @@ namespace render {
m_Generator.GetQt3DSContext().GetDefaultMaterialShaderGenerator().SetMaterialProperties(
shader->m_Shader, m_Material, inCameraVec, m_ModelContext.m_ModelViewProjection,
m_ModelContext.m_NormalMatrix, m_ModelContext.m_Model.m_GlobalTransform, m_FirstImage,
- m_Opacity, m_Generator.GetLayerGlobalRenderProperties());
+ m_Opacity, m_Generator.GetLayerGlobalRenderProperties(),
+ QT3DSVec2(m_Generator.alphaOpRef()));
- // tesselation
+ // tessellation
if (m_Subset.m_PrimitiveType == NVRenderDrawMode::Patches) {
shader->m_Tessellation.m_EdgeTessLevel.Set(m_Subset.m_EdgeTessFactor);
shader->m_Tessellation.m_InsideTessLevel.Set(m_Subset.m_InnerTessFactor);
@@ -287,11 +295,56 @@ namespace render {
context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
}
+ void SSubsetRenderable::RenderShadow(const QT3DSVec2 &inCameraVec,
+ TShaderFeatureSet inFeatureSet, const SLight *inLight,
+ const SCamera &inCamera, SShadowMapEntry *inShadowMapEntry)
+ {
+ NVRenderContext &context(m_Generator.GetContext());
+ SRenderableDepthPrepassShader *shader = nullptr;
+
+ // Do not render if alpha test is enabled, but no alpha test in object or vice versa
+ if (m_Generator.alphaTestEnabled() ^ m_RenderableFlags.hasAlphaTest())
+ return;
+
+ shader = m_Generator.GetShadowShader(*this, inFeatureSet, inLight->m_LightType);
+ if (shader == nullptr || inShadowMapEntry == nullptr)
+ return;
+
+ QT3DSMat44 theModelViewProjection = inShadowMapEntry->m_LightVP * m_GlobalTransform;
+
+ context.SetActiveShader(&shader->m_Shader);
+ m_Generator.GetQt3DSContext().GetDefaultMaterialShaderGenerator().SetMaterialProperties(
+ shader->m_Shader, m_Material, inCameraVec, m_ModelContext.m_ModelViewProjection,
+ m_ModelContext.m_NormalMatrix, m_ModelContext.m_Model.m_GlobalTransform, m_FirstImage,
+ m_Opacity, m_Generator.GetLayerGlobalRenderProperties(),
+ QT3DSVec2(m_Generator.alphaOpRef()));
+
+ shader->m_MVP.Set(theModelViewProjection);
+ shader->m_CameraPosition.Set(inCamera.m_Position);
+ shader->m_GlobalTransform.Set(m_GlobalTransform);
+ shader->m_CameraProperties.Set(inCameraVec);
+
+ // tessellation
+ if (m_Subset.m_PrimitiveType == NVRenderDrawMode::Patches) {
+ shader->m_Tessellation.m_EdgeTessLevel.Set(m_Subset.m_EdgeTessFactor);
+ shader->m_Tessellation.m_InsideTessLevel.Set(m_Subset.m_InnerTessFactor);
+ // the blend value is hardcoded
+ shader->m_Tessellation.m_PhongBlend.Set(0.75);
+ // this should finally be based on some user input
+ shader->m_Tessellation.m_DistanceRange.Set(inCameraVec);
+ // enable culling
+ shader->m_Tessellation.m_DisableCulling.Set(0.0);
+ }
+
+ context.SetInputAssembler(m_Subset.m_InputAssembler);
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ }
+
void SSubsetRenderable::RenderDepthPass(const QT3DSVec2 &inCameraVec)
{
- SRenderableImage *displacementImage = NULL;
+ SRenderableImage *displacementImage = nullptr;
for (SRenderableImage *theImage = m_FirstImage;
- theImage != NULL && displacementImage == NULL; theImage = theImage->m_NextImage) {
+ theImage != nullptr && displacementImage == nullptr; theImage = theImage->m_NextImage) {
if (theImage->m_MapType == ImageMapTypes::Displacement)
displacementImage = theImage;
}
@@ -302,11 +355,13 @@ namespace render {
void STextRenderable::Render(const QT3DSVec2 &inCameraVec)
{
NVRenderContext &context(m_Generator.GetContext());
+ if (m_Generator.alphaTestEnabled())
+ return;
if (!m_Text.m_PathFontDetails) {
STextRenderHelper theInfo = m_Generator.GetShader(*this, false);
- if (theInfo.m_Shader == NULL)
+ if (theInfo.m_Shader == nullptr)
return;
// All of our shaders produce premultiplied values.
qt3ds::render::NVRenderBlendFunctionArgument blendFunc(
@@ -330,7 +385,7 @@ namespace render {
QT3DS_ASSERT(context.IsPathRenderingSupported() && context.IsProgramPipelineSupported());
STextRenderHelper theInfo = m_Generator.GetShader(*this, true);
- if (theInfo.m_Shader == NULL)
+ if (theInfo.m_Shader == nullptr)
return;
// All of our shaders produce premultiplied values.
@@ -357,7 +412,7 @@ namespace render {
{
NVRenderContext &context(m_Generator.GetContext());
STextDepthShader *theDepthShader = m_Generator.GetTextDepthShader();
- if (theDepthShader == NULL)
+ if (theDepthShader == nullptr || m_Generator.alphaTestEnabled())
return;
if (!m_Text.m_PathFontDetails) {
@@ -403,7 +458,7 @@ namespace render {
theDepthFunction, false, theArg, theArg, theOpArg,
theOpArg);
- context.SetActiveShader(NULL);
+ context.SetActiveShader(nullptr);
context.SetCullingEnabled(false);
context.SetDepthStencilState(depthStencilState);
@@ -451,6 +506,8 @@ namespace render {
const NVRenderTexture2D *inSsaoTexture,
TShaderFeatureSet inFeatureSet)
{
+ if (m_Generator.alphaTestEnabled())
+ return;
IQt3DSRenderContext &qt3dsContext(m_Generator.GetQt3DSContext());
SCustomMaterialRenderContext theRenderContext(
inLayer, inLayerData, inLights, inCamera, m_ModelContext.m_Model, m_Subset,
@@ -468,13 +525,15 @@ namespace render {
const SCamera & /*inCamera*/,
const NVRenderTexture2D * /*inDepthTexture*/)
{
-
+ if (m_Generator.alphaTestEnabled())
+ return;
IQt3DSRenderContext &qt3dsContext(m_Generator.GetQt3DSContext());
if (!qt3dsContext.GetCustomMaterialSystem().RenderDepthPrepass(
m_ModelContext.m_ModelViewProjection, m_Material, m_Subset)) {
- SRenderableImage *displacementImage = NULL;
+ SRenderableImage *displacementImage = nullptr;
for (SRenderableImage *theImage = m_FirstImage;
- theImage != NULL && displacementImage == NULL; theImage = theImage->m_NextImage) {
+ theImage != nullptr && displacementImage == nullptr;
+ theImage = theImage->m_NextImage) {
if (theImage->m_MapType == ImageMapTypes::Displacement)
displacementImage = theImage;
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
index 6924f9e..f79b169 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
@@ -62,6 +62,7 @@ namespace render {
Path = 1 << 9,
ShadowCaster = 1 << 10,
DistanceField = 1 << 11,
+ HasAlphaTest = 1 << 12,
};
};
@@ -70,7 +71,7 @@ namespace render {
void ClearOrSet(bool value, RenderPreparationResultFlagValues::Enum enumVal)
{
if (value)
- this->operator|=(enumVal);
+ *this |= enumVal;
else
clear(enumVal);
}
@@ -81,11 +82,11 @@ namespace render {
}
bool HasTransparency() const
{
- return this->operator&(RenderPreparationResultFlagValues::HasTransparency);
+ return *this & RenderPreparationResultFlagValues::HasTransparency;
}
bool HasRefraction() const
{
- return this->operator&(RenderPreparationResultFlagValues::HasRefraction);
+ return *this & RenderPreparationResultFlagValues::HasRefraction;
}
void SetCompletelyTransparent(bool inTransparent)
{
@@ -93,20 +94,20 @@ namespace render {
}
bool IsCompletelyTransparent() const
{
- return this->operator&(RenderPreparationResultFlagValues::CompletelyTransparent);
+ return *this & RenderPreparationResultFlagValues::CompletelyTransparent;
}
void SetDirty(bool inDirty)
{
ClearOrSet(inDirty, RenderPreparationResultFlagValues::Dirty);
}
- bool IsDirty() const { return this->operator&(RenderPreparationResultFlagValues::Dirty); }
+ bool IsDirty() const { return *this & RenderPreparationResultFlagValues::Dirty; }
void SetPickable(bool inPickable)
{
ClearOrSet(inPickable, RenderPreparationResultFlagValues::Pickable);
}
bool GetPickable() const
{
- return this->operator&(RenderPreparationResultFlagValues::Pickable);
+ return *this & RenderPreparationResultFlagValues::Pickable;
}
// Mutually exclusive values
@@ -116,7 +117,7 @@ namespace render {
}
bool IsDefaultMaterialMeshSubset() const
{
- return this->operator&(RenderPreparationResultFlagValues::DefaultMaterialMeshSubset);
+ return *this & RenderPreparationResultFlagValues::DefaultMaterialMeshSubset;
}
void SetCustomMaterialMeshSubset(bool inMeshSubset)
@@ -125,11 +126,11 @@ namespace render {
}
bool IsCustomMaterialMeshSubset() const
{
- return this->operator&(RenderPreparationResultFlagValues::CustomMaterialMeshSubset);
+ return *this & RenderPreparationResultFlagValues::CustomMaterialMeshSubset;
}
void SetText(bool inText) { ClearOrSet(inText, RenderPreparationResultFlagValues::Text); }
- bool IsText() const { return this->operator&(RenderPreparationResultFlagValues::Text); }
+ bool IsText() const { return *this & RenderPreparationResultFlagValues::Text; }
void setDistanceField(bool inText)
{
@@ -138,17 +139,17 @@ namespace render {
bool isDistanceField() const
{
- return this->operator&(RenderPreparationResultFlagValues::DistanceField);
+ return *this & RenderPreparationResultFlagValues::DistanceField;
}
void SetCustom(bool inCustom)
{
ClearOrSet(inCustom, RenderPreparationResultFlagValues::Custom);
}
- bool IsCustom() const { return this->operator&(RenderPreparationResultFlagValues::Custom); }
+ bool IsCustom() const { return *this & RenderPreparationResultFlagValues::Custom; }
void SetPath(bool inPath) { ClearOrSet(inPath, RenderPreparationResultFlagValues::Path); }
- bool IsPath() const { return this->operator&(RenderPreparationResultFlagValues::Path); }
+ bool IsPath() const { return *this & RenderPreparationResultFlagValues::Path; }
void SetShadowCaster(bool inCaster)
{
@@ -156,7 +157,15 @@ namespace render {
}
bool IsShadowCaster() const
{
- return this->operator&(RenderPreparationResultFlagValues::ShadowCaster);
+ return *this & RenderPreparationResultFlagValues::ShadowCaster;
+ }
+ void setAlphaTest(bool set)
+ {
+ ClearOrSet(set, RenderPreparationResultFlagValues::HasAlphaTest);
+ }
+ bool hasAlphaTest() const
+ {
+ return *this & RenderPreparationResultFlagValues::HasAlphaTest;
}
};
@@ -311,8 +320,10 @@ namespace render {
m_RenderableFlags.setDistanceField(false);
}
- void Render(const QT3DSVec2 &inCameraVec, TShaderFeatureSet inFeatureSet);
-
+ void Render(const QT3DSVec2 &inCameraVec, TShaderFeatureSet inFeatureSet, bool depth);
+ void RenderShadow(const QT3DSVec2 &inCameraVec, TShaderFeatureSet inFeatureSet,
+ const SLight *inLight, const SCamera &inCamera,
+ SShadowMapEntry *inShadowMapEntry);
void RenderDepthPass(const QT3DSVec2 &inCameraVec);
DefaultMaterialBlendMode::Enum getBlendingMode()
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
index 466ac5c..db3697a 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
@@ -103,6 +103,9 @@ namespace render {
, m_StringTable(ctx.GetStringTable())
, m_LayerShaders(ctx.GetAllocator(), "Qt3DSRendererImpl::m_LayerShaders")
, m_Shaders(ctx.GetAllocator(), "Qt3DSRendererImpl::m_Shaders")
+ , m_DepthShaders(ctx.GetAllocator(), "Qt3DSRendererImpl::m_DepthShaders")
+ , m_ShadowMapShaders(ctx.GetAllocator(), "Qt3DSRendererImpl::m_ShadowMapShaders")
+ , m_ShadowCubeShaders(ctx.GetAllocator(), "Qt3DSRendererImpl::m_ShadowCubeShaders")
, m_ConstantBuffers(ctx.GetAllocator(), "Qt3DSRendererImpl::m_ConstantBuffers")
, m_TextShader(ctx.GetAllocator())
, m_TextPathShader(ctx.GetAllocator())
@@ -110,13 +113,13 @@ namespace render {
, m_TextOnscreenShader(ctx.GetAllocator())
#ifdef ADVANCED_BLEND_SW_FALLBACK
, m_LayerBlendTexture(ctx.GetResourceManager())
- , m_BlendFB(NULL)
+ , m_BlendFB(nullptr)
#endif
, m_InstanceRenderMap(ctx.GetAllocator(), "Qt3DSRendererImpl::m_InstanceRenderMap")
, m_LastFrameLayers(ctx.GetAllocator(), "Qt3DSRendererImpl::m_LastFrameLayers")
, mRefCount(0)
, m_LastPickResults(ctx.GetAllocator(), "Qt3DSRendererImpl::m_LastPickResults")
- , m_CurrentLayer(NULL)
+ , m_CurrentLayer(nullptr)
, m_WidgetVertexBuffers(ctx.GetAllocator(), "Qt3DSRendererImpl::m_WidgetVertexBuffers")
, m_WidgetIndexBuffers(ctx.GetAllocator(), "Qt3DSRendererImpl::m_WidgetIndexBuffers")
, m_WidgetShaders(ctx.GetAllocator(), "Qt3DSRendererImpl::m_WidgetShaders")
@@ -131,10 +134,25 @@ namespace render {
{
m_LayerShaders.clear();
for (TShaderMap::iterator iter = m_Shaders.begin(), end = m_Shaders.end(); iter != end;
- ++iter)
+ ++iter) {
NVDelete(m_Context->GetAllocator(), iter->second);
-
+ }
+ for (TShaderMap::iterator iter = m_DepthShaders.begin(), end = m_DepthShaders.end();
+ iter != end; ++iter) {
+ NVDelete(m_Context->GetAllocator(), iter->second);
+ }
+ for (TShadowShaderMap::iterator iter = m_ShadowMapShaders.begin(),
+ end = m_ShadowMapShaders.end(); iter != end; ++iter) {
+ NVDelete(m_Context->GetAllocator(), iter->second);
+ }
+ for (TShadowShaderMap::iterator iter = m_ShadowCubeShaders.begin(),
+ end = m_ShadowCubeShaders.end(); iter != end; ++iter) {
+ NVDelete(m_Context->GetAllocator(), iter->second);
+ }
+ m_ShadowMapShaders.clear();
+ m_ShadowCubeShaders.clear();
m_Shaders.clear();
+ m_DepthShaders.clear();
m_InstanceRenderMap.clear();
m_ConstantBuffers.clear();
}
@@ -177,7 +195,7 @@ namespace render {
{
if (inLayer.m_NextSibling && inLayer.m_NextSibling->m_Type == GraphObjectTypes::Layer)
return static_cast<SLayer *>(inLayer.m_NextSibling);
- return NULL;
+ return nullptr;
}
static inline void MaybePushLayer(SLayer &inLayer, nvvector<SLayer *> &outLayerList)
@@ -290,7 +308,7 @@ namespace render {
m_LayerBlendTexture.EnsureTexture(viewport.m_Width + viewport.m_X,
viewport.m_Height + viewport.m_Y,
NVRenderTextureFormats::RGBA8);
- if (m_BlendFB == NULL)
+ if (m_BlendFB == nullptr)
m_BlendFB = theRenderContext.CreateFrameBuffer();
m_BlendFB->Attach(NVRenderFrameBufferAttachments::Color0, *m_LayerBlendTexture);
theRenderContext.SetRenderTarget(m_BlendFB);
@@ -333,7 +351,7 @@ namespace render {
}
if (inNode.m_Parent)
return GetLayerForNode(*inNode.m_Parent);
- return NULL;
+ return nullptr;
}
SLayerRenderData *Qt3DSRendererImpl::GetOrCreateLayerRenderDataForNode(const SNode &inNode,
@@ -356,7 +374,7 @@ namespace render {
return theRenderData;
}
- return NULL;
+ return nullptr;
}
SCamera *Qt3DSRendererImpl::GetCameraForNode(const SNode &inNode) const
@@ -365,7 +383,7 @@ namespace render {
const_cast<Qt3DSRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
if (theLayer)
return theLayer->m_Camera;
- return NULL;
+ return nullptr;
}
Option<SCuboidRect> Qt3DSRendererImpl::GetCameraBounds(const SGraphObject &inObject)
@@ -552,8 +570,8 @@ namespace render {
IResourceManager &theManager(m_qt3dsContext.GetResourceManager());
theManager.Release(*m_WidgetFBO);
theManager.Release(*m_WidgetTexture);
- m_WidgetTexture = NULL;
- m_WidgetFBO = NULL;
+ m_WidgetTexture = nullptr;
+ m_WidgetFBO = nullptr;
}
}
@@ -652,7 +670,7 @@ namespace render {
// If picking against the sub object doesn't return a valid result *and*
// the current object isn't globally pickable then we move onto the next object returned
// by the pick query.
- if (thePickResult.m_HitObject != NULL && thePickResult.m_FirstSubObject != NULL
+ if (thePickResult.m_HitObject != nullptr && thePickResult.m_FirstSubObject != nullptr
&& m_PickRenderPlugins) {
QT3DSVec2 theUVCoords(thePickResult.m_LocalUVCoords.x,
thePickResult.m_LocalUVCoords.y);
@@ -686,7 +704,7 @@ namespace render {
bool wasPickConsumed =
theSubRenderer->Pick(theMouseCoords, theViewportDimensions, this);
if (wasPickConsumed) {
- thePickResult.m_HitObject = NULL;
+ thePickResult.m_HitObject = nullptr;
foundValidResult = true;
}
}
@@ -728,8 +746,8 @@ namespace render {
if (inPickSiblings)
theLayer = GetNextLayer(*theLayer);
else
- theLayer = NULL;
- } while (theLayer != NULL);
+ theLayer = nullptr;
+ } while (theLayer != nullptr);
return Qt3DSRenderPickResult();
}
@@ -787,15 +805,15 @@ namespace render {
SBasisPlanes::Enum inPlane)
{
SLayerRenderData *theLayerData = GetOrCreateLayerRenderDataForNode(inNode);
- if (theLayerData == NULL)
+ if (theLayerData == nullptr)
return Empty();
// This function assumes the layer was rendered to the scene itself. There is another
// function
// for completely offscreen layers that don't get rendered to the scene.
bool wasRenderToTarget(theLayerData->m_Layer.m_Flags.IsLayerRenderToTarget());
- if (wasRenderToTarget == false || theLayerData->m_Camera == NULL
+ if (wasRenderToTarget == false || theLayerData->m_Camera == nullptr
|| theLayerData->m_LayerPrepResult.hasValue() == false
- || theLayerData->m_LastFrameOffscreenRenderer.mPtr != NULL)
+ || theLayerData->m_LastFrameOffscreenRenderer.mPtr != nullptr)
return Empty();
QT3DSVec2 theMouseCoords(inMouseCoords);
@@ -808,7 +826,7 @@ namespace render {
// This is extremely counter intuitive but a good sign.
} else if (currentObject.m_Type == GraphObjectTypes::Image) {
SImage &theImage = static_cast<SImage &>(currentObject);
- SModel *theParentModel = NULL;
+ SModel *theParentModel = nullptr;
if (theImage.m_Parent
&& theImage.m_Parent->m_Type == GraphObjectTypes::DefaultMaterial) {
SDefaultMaterial *theMaterial =
@@ -817,7 +835,7 @@ namespace render {
theParentModel = theMaterial->m_Parent;
}
}
- if (theParentModel == NULL) {
+ if (theParentModel == nullptr) {
QT3DS_ASSERT(false);
return Empty();
}
@@ -871,7 +889,7 @@ namespace render {
// Translate mouse into layer's coordinates
SLayerRenderData *theData =
const_cast<Qt3DSRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
- if (theData == NULL || theData->m_Camera == NULL) {
+ if (theData == nullptr || theData->m_Camera == nullptr) {
return QT3DSVec3(0, 0, 0);
} // QT3DS_ASSERT( false ); return QT3DSVec3(0,0,0); }
@@ -890,7 +908,7 @@ namespace render {
// Translate mouse into layer's coordinates
SLayerRenderData *theData =
const_cast<Qt3DSRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
- if (theData == NULL || theData->m_Camera == NULL) {
+ if (theData == nullptr || theData->m_Camera == nullptr) {
return QT3DSVec3(0, 0, 0);
} // QT3DS_ASSERT( false ); return QT3DSVec3(0,0,0); }
@@ -903,7 +921,7 @@ namespace render {
SRay theRay = thePrepResult.GetPickRay(
theMouse, QT3DSVec2((QT3DSF32)theWindow.width(), (QT3DSF32)theWindow.height()), true);
QT3DSVec3 theTargetPosition = theRay.m_Origin + theRay.m_Direction * theDepth;
- if (inNode.m_Parent != NULL && inNode.m_Parent->m_Type != GraphObjectTypes::Layer)
+ if (inNode.m_Parent != nullptr && inNode.m_Parent->m_Type != GraphObjectTypes::Layer)
theTargetPosition =
inNode.m_Parent->m_GlobalTransform.getInverse().transform(theTargetPosition);
// Our default global space is right handed, so if you are left handed z means something
@@ -918,7 +936,7 @@ namespace render {
// Translate mouse into layer's coordinates
SLayerRenderData *theData =
const_cast<Qt3DSRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
- if (theData == NULL || theData->m_Camera == NULL) {
+ if (theData == nullptr || theData->m_Camera == nullptr) {
return QT3DSVec3(0, 0, 0);
}
@@ -955,7 +973,7 @@ namespace render {
const QSize &inPickDims)
{
SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
- if (theData == NULL || theData->m_Camera == NULL) {
+ if (theData == nullptr || theData->m_Camera == nullptr) {
QT3DS_ASSERT(false);
return Empty();
}
@@ -968,7 +986,7 @@ namespace render {
}
SLayerRenderPreparationResult &thePrepResult(*theData->m_LayerPrepResult);
- if (thePrepResult.GetCamera() == NULL) {
+ if (thePrepResult.GetCamera() == nullptr) {
return Empty();
}
// Perform gluPickMatrix and pre-multiply it into the view projection
@@ -1009,7 +1027,7 @@ namespace render {
Option<NVRenderRectF> Qt3DSRendererImpl::GetLayerRect(SLayer &inLayer)
{
SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
- if (theData == NULL || theData->m_Camera == NULL) {
+ if (theData == nullptr || theData->m_Camera == nullptr) {
QT3DS_ASSERT(false);
return Empty();
}
@@ -1021,7 +1039,7 @@ namespace render {
void Qt3DSRendererImpl::RunLayerRender(SLayer &inLayer, const QT3DSMat44 &inViewProjection)
{
SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
- if (theData == NULL || theData->m_Camera == NULL) {
+ if (theData == nullptr || theData->m_Camera == nullptr) {
QT3DS_ASSERT(false);
return;
}
@@ -1077,7 +1095,7 @@ namespace render {
const QT3DSVec3 &inWorldPoint)
{
SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
- if (theData == NULL || theData->m_Camera == NULL) {
+ if (theData == nullptr || theData->m_Camera == nullptr) {
QT3DS_ASSERT(false);
return SScaleAndPosition();
}
@@ -1141,7 +1159,7 @@ namespace render {
m_CurrentLayer = &inLayer;
}
- void Qt3DSRendererImpl::EndLayerDepthPassRender() { m_CurrentLayer = NULL; }
+ void Qt3DSRendererImpl::EndLayerDepthPassRender() { m_CurrentLayer = nullptr; }
void Qt3DSRendererImpl::BeginLayerRender(SLayerRenderData &inLayer)
{
@@ -1151,7 +1169,7 @@ namespace render {
// shaders that are in the layer.
m_LayerShaders.clear();
}
- void Qt3DSRendererImpl::EndLayerRender() { m_CurrentLayer = NULL; }
+ void Qt3DSRendererImpl::EndLayerRender() { m_CurrentLayer = nullptr; }
// Allocate an object that lasts only this frame.
#define RENDER_FRAME_NEW(type) \
@@ -1170,7 +1188,7 @@ namespace render {
bool NodeContainsBoneRoot(SNode &childNode, QT3DSI32 rootID)
{
- for (SNode *childChild = childNode.m_FirstChild; childChild != NULL;
+ for (SNode *childChild = childNode.m_FirstChild; childChild != nullptr;
childChild = childChild->m_NextSibling) {
if (childChild->m_SkeletonId == rootID)
return true;
@@ -1183,7 +1201,7 @@ namespace render {
{
if (childNode.m_SkeletonId >= 0)
ioMap[childNode.m_SkeletonId] = &childNode;
- for (SNode *childChild = childNode.m_FirstChild; childChild != NULL;
+ for (SNode *childChild = childNode.m_FirstChild; childChild != nullptr;
childChild = childChild->m_NextSibling)
FillBoneIdNodeMap(*childChild, ioMap);
}
@@ -1191,7 +1209,7 @@ namespace render {
bool Qt3DSRendererImpl::PrepareTextureAtlasForRender()
{
ITextTextureAtlas *theTextureAtlas = m_qt3dsContext.GetTextureAtlas();
- if (theTextureAtlas == NULL)
+ if (theTextureAtlas == nullptr)
return false;
// this is a one time creation
@@ -1344,13 +1362,13 @@ namespace render {
// function
// for completely offscreen layers that don't get rendered to the scene.
bool wasRenderToTarget(inLayerRenderData.m_Layer.m_Flags.IsLayerRenderToTarget());
- if (wasRenderToTarget && inLayerRenderData.m_Camera != NULL) {
+ if (wasRenderToTarget && inLayerRenderData.m_Camera != nullptr) {
Option<SRay> theHitRay;
if (inLayerRenderData.m_LayerPrepResult.hasValue()) {
theHitRay = inLayerRenderData.m_LayerPrepResult->GetPickRay(
inPresCoords, inViewportDimensions, false, m_Context->isSceneCameraView());
}
- if (inLayerRenderData.m_LastFrameOffscreenRenderer.mPtr == NULL) {
+ if (inLayerRenderData.m_LastFrameOffscreenRenderer.mPtr == nullptr) {
if (theHitRay.hasValue()) {
// Scale the mouse coords to change them into the camera's numerical space.
SRay thePickRay = *theHitRay;
@@ -1410,7 +1428,7 @@ namespace render {
SRayIntersectionResult &theResult(*theIntersectionResultOpt);
// Leave the coordinates relative for right now.
- const SGraphObject *thePickObject = NULL;
+ const SGraphObject *thePickObject = nullptr;
if (inRenderableObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
thePickObject =
&static_cast<SSubsetRenderable *>(&inRenderableObject)->m_ModelContext.m_Model;
@@ -1426,26 +1444,26 @@ namespace render {
else if (inRenderableObject.m_RenderableFlags.IsPath())
thePickObject = &static_cast<SPathRenderable *>(&inRenderableObject)->m_Path;
- if (thePickObject != NULL) {
+ if (thePickObject != nullptr) {
outIntersectionResultList.push_back(Qt3DSRenderPickResult(
*thePickObject, theResult.m_RayLengthSquared, theResult.m_RelXY));
// For subsets, we know we can find images on them which may have been the result
// of rendering a sub-presentation.
if (inRenderableObject.m_RenderableFlags.IsDefaultMaterialMeshSubset()) {
- Qt3DSRenderPickSubResult *theLastResult = NULL;
+ Qt3DSRenderPickSubResult *theLastResult = nullptr;
for (SRenderableImage *theImage =
static_cast<SSubsetRenderable *>(&inRenderableObject)->m_FirstImage;
- theImage != NULL; theImage = theImage->m_NextImage) {
- if (theImage->m_Image.m_LastFrameOffscreenRenderer != NULL
- && theImage->m_Image.m_TextureData.m_Texture != NULL) {
+ theImage != nullptr; theImage = theImage->m_NextImage) {
+ if (theImage->m_Image.m_LastFrameOffscreenRenderer != nullptr
+ && theImage->m_Image.m_TextureData.m_Texture != nullptr) {
Qt3DSRenderPickSubResult *theSubResult =
(Qt3DSRenderPickSubResult *)inTempAllocator.allocate(
sizeof(Qt3DSRenderPickSubResult), "Qt3DSRenderPickSubResult",
__FILE__, __LINE__);
new (theSubResult) Qt3DSRenderPickSubResult(ConstructSubResult(*theImage));
- if (theLastResult == NULL)
+ if (theLastResult == nullptr)
outIntersectionResultList.back().m_FirstSubObject = theSubResult;
else
theLastResult->m_NextSibling = theSubResult;
@@ -1493,17 +1511,20 @@ namespace render {
}
SShaderGeneratorGeneratedShader *Qt3DSRendererImpl::GetShader(SSubsetRenderable &inRenderable,
- TShaderFeatureSet inFeatureSet)
+ TShaderFeatureSet inFeatureSet,
+ bool depth)
{
- if (m_CurrentLayer == NULL) {
+ if (m_CurrentLayer == nullptr) {
QT3DS_ASSERT(false);
- return NULL;
+ return nullptr;
}
- TShaderMap::iterator theFind = m_Shaders.find(inRenderable.m_ShaderDescription);
- SShaderGeneratorGeneratedShader *retval = NULL;
- if (theFind == m_Shaders.end()) {
+
+ SShaderGeneratorGeneratedShader *retval = nullptr;
+ TShaderMap &map = depth ? m_DepthShaders : m_Shaders;
+ TShaderMap::iterator theFind = map.find(inRenderable.m_ShaderDescription);
+ if (theFind == map.end()) {
// Generate the shader.
- NVRenderShaderProgram *theShader(GenerateShader(inRenderable, inFeatureSet));
+ NVRenderShaderProgram *theShader(GenerateShader(inRenderable, inFeatureSet, depth));
if (theShader) {
SShaderGeneratorGeneratedShader *theGeneratedShader =
(SShaderGeneratorGeneratedShader *)m_Context->GetAllocator().allocate(
@@ -1511,18 +1532,18 @@ namespace render {
__FILE__, __LINE__);
new (theGeneratedShader) SShaderGeneratorGeneratedShader(
m_StringTable->RegisterStr(m_GeneratedShaderString.c_str()), *theShader);
- m_Shaders.insert(make_pair(inRenderable.m_ShaderDescription, theGeneratedShader));
+ map.insert(make_pair(inRenderable.m_ShaderDescription, theGeneratedShader));
retval = theGeneratedShader;
}
- // We still insert something because we don't to attempt to generate the same bad shader
- // twice.
+ // We still insert something because we don't want to attempt to generate the same
+ // bad shader twice.
else
- m_Shaders.insert(make_pair(inRenderable.m_ShaderDescription,
- (SShaderGeneratorGeneratedShader *)NULL));
+ map.insert(make_pair(inRenderable.m_ShaderDescription,
+ (SShaderGeneratorGeneratedShader *)nullptr));
} else
retval = theFind->second;
- if (retval != NULL) {
+ if (retval != nullptr && !depth) {
if (!m_LayerShaders.contains(*retval)) {
m_LayerShaders.insert(*retval);
}
@@ -1534,6 +1555,45 @@ namespace render {
}
return retval;
}
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetShadowShader(
+ SSubsetRenderable &inRenderable, TShaderFeatureSet inFeatureSet,
+ RenderLightTypes::Enum lightType)
+ {
+ if (m_CurrentLayer == nullptr) {
+ QT3DS_ASSERT(false);
+ return nullptr;
+ }
+
+ SRenderableDepthPrepassShader *retval = nullptr;
+ TShadowShaderMap &map = lightType == RenderLightTypes::Point ? m_ShadowCubeShaders
+ : m_ShadowMapShaders;
+ TShadowShaderMap::iterator theFind = map.find(inRenderable.m_ShaderDescription);
+ if (theFind == map.end()) {
+ // Generate the shader.
+ NVRenderShaderProgram *theShader(GenerateShadowShader(inRenderable, inFeatureSet,
+ lightType));
+ if (theShader) {
+ SRenderableDepthPrepassShader *theGeneratedShader =
+ (SRenderableDepthPrepassShader *)m_Context->GetAllocator().allocate(
+ sizeof(SRenderableDepthPrepassShader), "SRenderableDepthPrepassShader",
+ __FILE__, __LINE__);
+ new (theGeneratedShader) SRenderableDepthPrepassShader(*theShader, GetContext());
+ map.insert(make_pair(inRenderable.m_ShaderDescription, theGeneratedShader));
+ retval = theGeneratedShader;
+ }
+ // We still insert something because we don't want to attempt to generate the same
+ // bad shader twice.
+ else {
+ map.insert(make_pair(inRenderable.m_ShaderDescription, nullptr));
+ }
+ } else {
+ retval = theFind->second;
+ }
+
+ return retval;
+ }
+
static QT3DSVec3 g_fullScreenRectFace[] = {
QT3DSVec3(-1, -1, 0), QT3DSVec3(-1, 1, 0), QT3DSVec3(1, 1, 0), QT3DSVec3(1, -1, 0),
};
@@ -1613,7 +1673,7 @@ namespace render {
QT3DSU32 strides = m_PointVertexBuffer->GetStride();
QT3DSU32 offsets = 0;
m_PointInputAssembler = m_Context->CreateInputAssembler(
- m_PointAttribLayout, toConstDataRef(&m_PointVertexBuffer.mPtr, 1), NULL,
+ m_PointAttribLayout, toConstDataRef(&m_PointVertexBuffer.mPtr, 1), nullptr,
toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
}
@@ -1666,7 +1726,7 @@ namespace render {
QT3DSU32 strides = m_QuadStripVertexBuffer->GetStride();
QT3DSU32 offsets = 0;
m_QuadStripInputAssembler = m_Context->CreateInputAssembler(
- m_QuadStripAttribLayout, toConstDataRef(&m_QuadStripVertexBuffer.mPtr, 1), NULL,
+ m_QuadStripAttribLayout, toConstDataRef(&m_QuadStripVertexBuffer.mPtr, 1), nullptr,
toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
}
@@ -1796,7 +1856,7 @@ namespace render {
TStrVertBufMap::iterator theIter = m_WidgetVertexBuffers.find(inStr);
if (theIter != m_WidgetVertexBuffers.end())
return theIter->second;
- return NULL;
+ return nullptr;
}
NVRenderIndexBuffer *Qt3DSRendererImpl::GetIndexBuffer(CRegisteredString &inStr)
@@ -1804,7 +1864,7 @@ namespace render {
TStrIndexBufMap::iterator theIter = m_WidgetIndexBuffers.find(inStr);
if (theIter != m_WidgetIndexBuffers.end())
return theIter->second;
- return NULL;
+ return nullptr;
}
NVRenderInputAssembler *Qt3DSRendererImpl::GetInputAssembler(CRegisteredString &inStr)
@@ -1812,7 +1872,7 @@ namespace render {
TStrIAMap::iterator theIter = m_WidgetInputAssembler.find(inStr);
if (theIter != m_WidgetInputAssembler.end())
return theIter->second;
- return NULL;
+ return nullptr;
}
NVRenderShaderProgram *Qt3DSRendererImpl::GetShader(CRegisteredString inStr)
@@ -1820,7 +1880,7 @@ namespace render {
TStrShaderMap::iterator theIter = m_WidgetShaders.find(inStr);
if (theIter != m_WidgetShaders.end())
return theIter->second;
- return NULL;
+ return nullptr;
}
NVRenderShaderProgram *Qt3DSRendererImpl::CompileAndStoreShader(CRegisteredString inStr)
@@ -1838,7 +1898,7 @@ namespace render {
STextDimensions Qt3DSRendererImpl::MeasureText(const STextRenderInfo &inText)
{
- if (m_qt3dsContext.GetTextRenderer() != NULL)
+ if (m_qt3dsContext.GetTextRenderer() != nullptr)
return m_qt3dsContext.GetTextRenderer()->MeasureText(inText, 0);
return STextDimensions();
}
@@ -1846,14 +1906,14 @@ namespace render {
void Qt3DSRendererImpl::RenderText(const STextRenderInfo &inText, const QT3DSVec3 &inTextColor,
const QT3DSVec3 &inBackgroundColor, const QT3DSMat44 &inMVP)
{
- if (m_qt3dsContext.GetTextRenderer() != NULL) {
+ if (m_qt3dsContext.GetTextRenderer() != nullptr) {
ITextRenderer &theTextRenderer(*m_qt3dsContext.GetTextRenderer());
NVRenderTexture2D *theTexture = m_qt3dsContext.GetResourceManager().AllocateTexture2D(
32, 32, NVRenderTextureFormats::RGBA8);
STextTextureDetails theTextTextureDetails =
theTextRenderer.RenderText(inText, *theTexture);
STextRenderHelper theTextHelper(GetTextWidgetShader());
- if (theTextHelper.m_Shader != NULL) {
+ if (theTextHelper.m_Shader != nullptr) {
m_qt3dsContext.GetRenderContext().SetBlendingEnabled(false);
STextScaleAndOffset theScaleAndOffset(*theTexture, theTextTextureDetails, inText);
theTextHelper.m_Shader->Render(*theTexture, theScaleAndOffset,
@@ -1870,7 +1930,7 @@ namespace render {
qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor,
const char *text)
{
- if (m_qt3dsContext.GetOnscreenTextRenderer() != NULL) {
+ if (m_qt3dsContext.GetOnscreenTextRenderer() != nullptr) {
GenerateXYQuadStrip();
if (PrepareTextureAtlasForRender()) {
@@ -1892,7 +1952,7 @@ namespace render {
if (theRenderTextDetails.first.m_Vertices.size()) {
STextRenderHelper theTextHelper(GetOnscreenTextShader());
- if (theTextHelper.m_Shader != NULL) {
+ if (theTextHelper.m_Shader != nullptr) {
// setup 2D projection
SCamera theCamera;
theCamera.m_ClipNear = -1.0;
@@ -1900,7 +1960,8 @@ namespace render {
theCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
theCamera.m_Flags.SetOrthographic(true);
- QT3DSVec2 theWindowDim((QT3DSF32)theWindow.width(), (QT3DSF32)theWindow.height());
+ QT3DSVec2 theWindowDim((QT3DSF32)theWindow.width(),
+ (QT3DSF32)theWindow.height());
theCamera.CalculateGlobalVariables(
NVRenderRect(0, 0, theWindow.width(), theWindow.height()),
theWindowDim);
@@ -1973,12 +2034,12 @@ namespace render {
{
SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inNode);
SCamera *theCamera = theData->m_Camera;
- if (theCamera == NULL || theData->m_LayerPrepResult.hasValue() == false) {
+ if (theCamera == nullptr || theData->m_LayerPrepResult.hasValue() == false) {
QT3DS_ASSERT(false);
return SWidgetRenderInformation();
}
QT3DSMat44 theGlobalTransform(QT3DSMat44::createIdentity());
- if (inNode.m_Parent != NULL && inNode.m_Parent->m_Type != GraphObjectTypes::Layer
+ if (inNode.m_Parent != nullptr && inNode.m_Parent->m_Type != GraphObjectTypes::Layer
&& !inNode.m_Flags.IsIgnoreParentTransform())
theGlobalTransform = inNode.m_Parent->m_GlobalTransform;
QT3DSMat44 theCameraInverse(theCamera->m_GlobalTransform.getInverse());
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
index 6311a2d..cd104df 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
@@ -66,6 +66,7 @@
#include "Qt3DSRenderShaderCache.h"
#include "Qt3DSRenderProfiler.h"
#include "Qt3DSRenderDefaultMaterialShaderGenerator.h"
+#include "Qt3DSRenderLight.h"
namespace qt3ds {
namespace render {
@@ -150,9 +151,12 @@ namespace render {
operator STextShader *() { return m_Shader; }
};
- class QT3DS_AUTOTEST_EXPORT Qt3DSRendererImpl : public IQt3DSRenderer, public IRenderWidgetContext
+ class QT3DS_AUTOTEST_EXPORT Qt3DSRendererImpl : public IQt3DSRenderer,
+ public IRenderWidgetContext
{
typedef nvhash_map<SShaderDefaultMaterialKey, SShaderGeneratorGeneratedShader *> TShaderMap;
+ typedef nvhash_map<SShaderDefaultMaterialKey, SRenderableDepthPrepassShader *>
+ TShadowShaderMap;
typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderConstantBuffer>>
TStrConstanBufMap;
typedef nvhash_map<SRenderInstanceId, NVScopedRefCounted<SLayerRenderData>,
@@ -210,11 +214,12 @@ namespace render {
Option<NVScopedRefCounted<SLayerProgAABlendShader>> m_LayerProgAAShader;
TShaderMap m_Shaders;
+ TShaderMap m_DepthShaders;
+ TShadowShaderMap m_ShadowMapShaders;
+ TShadowShaderMap m_ShadowCubeShaders;
TStrConstanBufMap m_ConstantBuffers; ///< store the the shader constant buffers
// Option is true if we have attempted to generate the shader.
// This does not mean we were successul, however.
- Option<NVScopedRefCounted<SDefaultMaterialRenderableDepthShader>>
- m_DefaultMaterialDepthPrepassShader;
Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthPrepassShader;
Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthPrepassShaderDisplaced;
Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthTessLinearPrepassShader;
@@ -295,6 +300,10 @@ namespace render {
QHash<SLayer *, SLayerRenderData *> m_initialPrepareData;
QSet<SGraphObject *> m_materialClearDirty;
+ bool m_alphaTest = false;
+ float m_alphaOp = 1.0f;
+ float m_alphaRef = 1.0f;
+
public:
Qt3DSRendererImpl(IQt3DSRenderContext &ctx);
virtual ~Qt3DSRendererImpl();
@@ -313,6 +322,23 @@ namespace render {
void EnableLayerGpuProfiling(bool inEnabled) override;
bool IsLayerGpuProfilingEnabled() const override { return m_LayerGPuProfilingEnabled; }
+ void setAlphaTest(bool enable, float op, float ref) override
+ {
+ m_alphaTest = enable;
+ m_alphaOp = op;
+ m_alphaRef = ref;
+ }
+
+ bool alphaTestEnabled() const
+ {
+ return m_alphaTest;
+ }
+
+ QT3DSVec2 alphaOpRef() const
+ {
+ return QT3DSVec2(m_alphaOp, m_alphaRef);
+ }
+
// Calls prepare layer for render
// and then do render layer.
bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
@@ -411,14 +437,19 @@ namespace render {
const char8_t *inFrame);
NVRenderShaderProgram *GenerateShader(SSubsetRenderable &inRenderable,
- TShaderFeatureSet inFeatureSet);
+ TShaderFeatureSet inFeatureSet, bool depth);
+ NVRenderShaderProgram *GenerateShadowShader(SSubsetRenderable &inRenderable,
+ TShaderFeatureSet inFeatureSet,
+ RenderLightTypes::Enum lightType);
SShaderGeneratorGeneratedShader *GetShader(SSubsetRenderable &inRenderable,
- TShaderFeatureSet inFeatureSet);
+ TShaderFeatureSet inFeatureSet, bool depth);
+ SRenderableDepthPrepassShader *GetShadowShader(SSubsetRenderable &inRenderable,
+ TShaderFeatureSet inFeatureSet,
+ RenderLightTypes::Enum lightType);
SDefaultAoPassShader *GetDefaultAoPassShader(TShaderFeatureSet inFeatureSet);
SDefaultAoPassShader *GetFakeDepthShader(TShaderFeatureSet inFeatureSet);
SDefaultAoPassShader *GetFakeCubeDepthShader(TShaderFeatureSet inFeatureSet);
- SDefaultMaterialRenderableDepthShader *GetRenderableDepthShader();
SRenderableDepthPrepassShader *GetParaboloidDepthShader(TessModeValues::Enum inTessMode);
SRenderableDepthPrepassShader *GetParaboloidDepthNoTessShader();
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
index b99773b..2d11615 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
@@ -497,7 +497,7 @@ namespace render {
}
inline void RenderRenderableShadowMapPass(SLayerRenderData &inData, SRenderableObject &inObject,
- const QT3DSVec2 &inCameraProps, TShaderFeatureSet,
+ const QT3DSVec2 &inCameraProps, TShaderFeatureSet set,
QT3DSU32 lightIndex, const SCamera &inCamera)
{
if (!inObject.m_RenderableFlags.IsShadowCaster())
@@ -505,10 +505,15 @@ namespace render {
SShadowMapEntry *pEntry = inData.m_ShadowMapManager->GetShadowMapEntry(lightIndex);
- if (inObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
- static_cast<SSubsetRenderableBase &>(inObject).RenderShadowMapPass(
- inCameraProps, inData.m_Lights[lightIndex], inCamera, pEntry);
- else if (inObject.m_RenderableFlags.IsCustomMaterialMeshSubset()) {
+ if (inObject.m_RenderableFlags.IsDefaultMaterialMeshSubset()) {
+ auto &sub = static_cast<SSubsetRenderable &>(inObject);
+ if (sub.m_Generator.alphaTestEnabled()) {
+ sub.RenderShadow(inCameraProps, set, inData.m_Lights[lightIndex], inCamera, pEntry);
+ } else {
+ sub.RenderShadowMapPass(inCameraProps, inData.m_Lights[lightIndex], inCamera,
+ pEntry);
+ }
+ } else if (inObject.m_RenderableFlags.IsCustomMaterialMeshSubset()) {
static_cast<SSubsetRenderableBase &>(inObject).RenderShadowMapPass(
inCameraProps, inData.m_Lights[lightIndex], inCamera, pEntry);
} else if (inObject.m_RenderableFlags.IsPath()) {
@@ -667,8 +672,10 @@ namespace render {
return;
// Check if we have anything to render
- if (m_OpaqueObjects.size() == 0 || m_Lights.size() == 0)
+ if ((m_OpaqueObjects.size() == 0 && GetTransparentRenderableObjects().size() == 0)
+ || m_Lights.size() == 0) {
return;
+ }
m_Renderer.BeginLayerDepthPassRender(*this);
@@ -786,11 +793,15 @@ namespace render {
}
inline void RenderRenderableDepthPass(SLayerRenderData &inData, SRenderableObject &inObject,
- const QT3DSVec2 &inCameraProps, TShaderFeatureSet, QT3DSU32,
- const SCamera &inCamera)
+ const QT3DSVec2 &inCameraProps, TShaderFeatureSet set,
+ QT3DSU32, const SCamera &inCamera)
{
if (inObject.m_RenderableFlags.IsDefaultMaterialMeshSubset()) {
- static_cast<SSubsetRenderable &>(inObject).RenderDepthPass(inCameraProps);
+ SSubsetRenderable &sub = static_cast<SSubsetRenderable &>(inObject);
+ if (sub.m_Generator.alphaTestEnabled())
+ sub.Render(inCameraProps, set, true);
+ else
+ sub.RenderDepthPass(inCameraProps);
} else if (inObject.m_RenderableFlags.IsText()) {
static_cast<STextRenderable &>(inObject).RenderDepthPass(inCameraProps);
#if QT_VERSION >= QT_VERSION_CHECK(5,12,2)
@@ -817,7 +828,7 @@ namespace render {
// Avoid running this method if possible.
if ((inEnableTransparentDepthWrite == false
- && (m_OpaqueObjects.size() == 0
+ && ((m_OpaqueObjects.size() == 0 && m_TransparentObjects.size() == 0)
|| m_Layer.m_Flags.IsLayerEnableDepthPrepass() == false))
|| m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
return;
@@ -844,11 +855,11 @@ namespace render {
}
inline void RenderRenderable(SLayerRenderData &inData, SRenderableObject &inObject,
- const QT3DSVec2 &inCameraProps, TShaderFeatureSet inFeatureSet, QT3DSU32,
- const SCamera &inCamera)
+ const QT3DSVec2 &inCameraProps, TShaderFeatureSet inFeatureSet,
+ QT3DSU32, const SCamera &inCamera)
{
if (inObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
- static_cast<SSubsetRenderable &>(inObject).Render(inCameraProps, inFeatureSet);
+ static_cast<SSubsetRenderable &>(inObject).Render(inCameraProps, inFeatureSet, false);
else if (inObject.m_RenderableFlags.IsText())
static_cast<STextRenderable &>(inObject).Render(inCameraProps);
#if QT_VERSION >= QT_VERSION_CHECK(5,12,2)
@@ -880,42 +891,18 @@ namespace render {
}
}
- void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn,
- bool inEnableBlending, bool inEnableDepthWrite,
- bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
- const SCamera &inCamera, CResourceFrameBuffer *theFB)
+ void SLayerRenderData::renderTransparentObjectsPass(
+ TRenderRenderableFunction inRenderFn, bool inEnableBlending,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
{
+ NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
NVRenderContext &theRenderContext(m_Renderer.GetContext());
- theRenderContext.SetDepthFunction(qt3ds::render::NVRenderBoolOp::LessThanOrEqual);
- theRenderContext.SetBlendingEnabled(false);
QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
- NVDataRef<SRenderableObject *> theOpaqueObjects = GetOpaqueRenderableObjects();
- bool usingDepthBuffer =
- m_Layer.m_Flags.IsLayerEnableDepthTest() && theOpaqueObjects.size() > 0;
-
- if (usingDepthBuffer) {
- theRenderContext.SetDepthTestEnabled(true);
- theRenderContext.SetDepthWriteEnabled(inEnableDepthWrite);
- } else {
- theRenderContext.SetDepthWriteEnabled(false);
- theRenderContext.SetDepthTestEnabled(false);
- }
-
- for (QT3DSU32 idx = 0, end = theOpaqueObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theOpaqueObjects[idx]);
- SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
- theObject.m_ScopedLights);
- SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
- inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
- inCamera);
- }
-
- // transparent objects
if (inEnableBlending || m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
theRenderContext.SetBlendingEnabled(true && inEnableBlending);
theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
- NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
// Assume all objects have transparency if the layer's depth test enabled flag is true.
if (m_Layer.m_Flags.IsLayerEnableDepthTest() == true) {
for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
@@ -953,7 +940,8 @@ namespace render {
// restore blending status
theRenderContext.SetBlendingEnabled(inEnableBlending);
// restore depth test status
- theRenderContext.SetDepthTestEnabled(usingDepthBuffer);
+ theRenderContext.SetDepthTestEnabled(
+ m_Layer.m_Flags.IsLayerEnableDepthTest());
theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
}
#endif
@@ -1004,6 +992,59 @@ namespace render {
}
}
}
+ };
+
+ void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+ {
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ theRenderContext.SetDepthFunction(qt3ds::render::NVRenderBoolOp::LessThanOrEqual);
+ theRenderContext.SetBlendingEnabled(false);
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ NVDataRef<SRenderableObject *> theOpaqueObjects = GetOpaqueRenderableObjects();
+
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest()) {
+ theRenderContext.SetDepthTestEnabled(true);
+ theRenderContext.SetDepthWriteEnabled(inEnableDepthWrite);
+ } else {
+ theRenderContext.SetDepthWriteEnabled(false);
+ theRenderContext.SetDepthTestEnabled(false);
+ }
+
+ for (QT3DSU32 idx = 0, end = theOpaqueObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theOpaqueObjects[idx]);
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
+ theObject.m_ScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ }
+
+ NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
+ // Also draw opaque parts of transparent objects
+ m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
+ theObject.m_ScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ }
+
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ // transparent parts of transparent objects
+ // does not render objects without alpha test enabled so
+ // we need another pass without alpha test
+ renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
+ indexLight, inCamera, theFB);
+
+ m_Renderer.setAlphaTest(false, 1.0, 1.0);
+ // transparent objects without alpha test
+ renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
+ indexLight, inCamera, theFB);
}
void SLayerRenderData::Render(CResourceFrameBuffer *theFB)
@@ -1483,7 +1524,7 @@ namespace render {
// to that frame buffer.
theFB.EnsureFrameBuffer();
- bool hasDepthObjects = m_OpaqueObjects.size() > 0;
+ bool hasDepthObjects = m_OpaqueObjects.size() > 0 || m_TransparentObjects.size() > 0;
bool requiresDepthStencilBuffer =
hasDepthObjects || thePrepResult.m_Flags.RequiresStencilBuffer();
NVRenderRect theNewViewport(0, 0, theLayerTextureDimensions.width(),
@@ -1543,7 +1584,9 @@ namespace render {
if (thePrepResult.m_Flags.RequiresShadowMapPass() && m_ProgressiveAAPassIndex == 0) {
// shadow map path
+ StartProfiling("Shadow pass", false);
RenderShadowMapPass(&theFB);
+ EndProfiling("Shadow pass");
}
if (sampleCount > 1) {
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
index 8e5c694..0f0a838 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
@@ -178,6 +178,10 @@ struct AdvancedBlendModes
void BlendAdvancedToFB(DefaultMaterialBlendMode::Enum blendMode, bool depthEnabled,
CResourceFrameBuffer *theFB);
#endif
+ void renderTransparentObjectsPass(TRenderRenderableFunction inRenderFn,
+ bool inEnableBlending, bool inEnableTransparentDepthWrite,
+ QT3DSU32 indexLight, const SCamera &inCamera,
+ CResourceFrameBuffer *theFB);
};
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
index bfd52d6..04bc4ae 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
@@ -595,7 +595,8 @@ namespace render {
void SLayerRenderPreparationData::PrepareImageForRender(
SImage &inImage, ImageMapTypes::Enum inMapType, SRenderableImage *&ioFirstImage,
SRenderableImage *&ioNextImage, SRenderableObjectFlags &ioFlags,
- SShaderDefaultMaterialKey &inShaderKey, QT3DSU32 inImageIndex)
+ SShaderDefaultMaterialKey &inShaderKey, QT3DSU32 inImageIndex,
+ bool *opaqueCheck)
{
IQt3DSRenderContext &qt3dsContext(m_Renderer.GetQt3DSContext());
IBufferManager &bufferManager = qt3dsContext.GetBufferManager();
@@ -619,6 +620,8 @@ namespace render {
|| inMapType == ImageMapTypes::Opacity
|| inMapType == ImageMapTypes::Translucency)) {
ioFlags |= RenderPreparationResultFlagValues::HasTransparency;
+ if (opaqueCheck)
+ *opaqueCheck = inImage.m_TextureData.m_TextureFlags.HasOpaquePixels();
}
// Textures used in general have linear characteristics.
// PKC -- The filters are properly set already. Setting them here only overrides what
@@ -683,6 +686,9 @@ namespace render {
SRenderableImage *firstImage = NULL;
+ // Combined check for images for having opaque pixels
+ bool transparencyImagesHaveOpaquePixels = true;
+
// set wireframe mode
m_Renderer.DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
theGeneratedKey, m_Renderer.GetQt3DSContext().GetWireframeMode());
@@ -725,46 +731,47 @@ namespace render {
// this may in fact set pickable on the renderable flags if one of the images
// links to a sub presentation or any offscreen rendered object.
SRenderableImage *nextImage = NULL;
-#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent) \
+#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent, checkOpaque) \
if ((img)) \
PrepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags, \
- theGeneratedKey, shadercomponent);
+ theGeneratedKey, shadercomponent, \
+ checkOpaque ? &transparencyImagesHaveOpaquePixels : nullptr);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_DiffuseMaps[0], ImageMapTypes::Diffuse,
- SShaderDefaultMaterialKeyProperties::DiffuseMap0);
+ SShaderDefaultMaterialKeyProperties::DiffuseMap0, true);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_DiffuseMaps[1], ImageMapTypes::Diffuse,
- SShaderDefaultMaterialKeyProperties::DiffuseMap1);
+ SShaderDefaultMaterialKeyProperties::DiffuseMap1, true);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_DiffuseMaps[2], ImageMapTypes::Diffuse,
- SShaderDefaultMaterialKeyProperties::DiffuseMap2);
+ SShaderDefaultMaterialKeyProperties::DiffuseMap2, true);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_EmissiveMap, ImageMapTypes::Emissive,
- SShaderDefaultMaterialKeyProperties::EmissiveMap);
+ SShaderDefaultMaterialKeyProperties::EmissiveMap, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_EmissiveMap2, ImageMapTypes::Emissive,
- SShaderDefaultMaterialKeyProperties::EmissiveMap2);
+ SShaderDefaultMaterialKeyProperties::EmissiveMap2, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_SpecularReflection, ImageMapTypes::Specular,
- SShaderDefaultMaterialKeyProperties::SpecularMap);
+ SShaderDefaultMaterialKeyProperties::SpecularMap, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_RoughnessMap, ImageMapTypes::Roughness,
- SShaderDefaultMaterialKeyProperties::RoughnessMap);
+ SShaderDefaultMaterialKeyProperties::RoughnessMap, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_OpacityMap, ImageMapTypes::Opacity,
- SShaderDefaultMaterialKeyProperties::OpacityMap);
+ SShaderDefaultMaterialKeyProperties::OpacityMap, true);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_BumpMap, ImageMapTypes::Bump,
- SShaderDefaultMaterialKeyProperties::BumpMap);
+ SShaderDefaultMaterialKeyProperties::BumpMap, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_SpecularMap, ImageMapTypes::SpecularAmountMap,
- SShaderDefaultMaterialKeyProperties::SpecularAmountMap);
+ SShaderDefaultMaterialKeyProperties::SpecularAmountMap, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_NormalMap, ImageMapTypes::Normal,
- SShaderDefaultMaterialKeyProperties::NormalMap);
+ SShaderDefaultMaterialKeyProperties::NormalMap, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_DisplacementMap, ImageMapTypes::Displacement,
- SShaderDefaultMaterialKeyProperties::DisplacementMap);
+ SShaderDefaultMaterialKeyProperties::DisplacementMap, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_TranslucencyMap, ImageMapTypes::Translucency,
- SShaderDefaultMaterialKeyProperties::TranslucencyMap);
+ SShaderDefaultMaterialKeyProperties::TranslucencyMap, true);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_Lightmaps.m_LightmapIndirect,
ImageMapTypes::LightmapIndirect,
- SShaderDefaultMaterialKeyProperties::LightmapIndirect);
+ SShaderDefaultMaterialKeyProperties::LightmapIndirect, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_Lightmaps.m_LightmapRadiosity,
ImageMapTypes::LightmapRadiosity,
- SShaderDefaultMaterialKeyProperties::LightmapRadiosity);
+ SShaderDefaultMaterialKeyProperties::LightmapRadiosity, false);
CHECK_IMAGE_AND_PREPARE(theMaterial->m_Lightmaps.m_LightmapShadow,
ImageMapTypes::LightmapShadow,
- SShaderDefaultMaterialKeyProperties::LightmapShadow);
+ SShaderDefaultMaterialKeyProperties::LightmapShadow, false);
}
#undef CHECK_IMAGE_AND_PREPARE
@@ -780,6 +787,17 @@ namespace render {
if (IsNotOne(subsetOpacity))
renderableFlags |= RenderPreparationResultFlagValues::HasTransparency;
+ // Enable alpha test, but only if the whole object opacity is full
+ // so parts of the object might be fully opaque
+ if (renderableFlags & RenderPreparationResultFlagValues::HasTransparency
+ && subsetOpacity >= 1.0f && transparencyImagesHaveOpaquePixels) {
+ m_Renderer.DefaultMaterialShaderKeyProperties()
+ .m_AlphaTestEnabled.SetValue(theGeneratedKey, true);
+ renderableFlags.setAlphaTest(true);
+ } else {
+ renderableFlags.setAlphaTest(false);
+ }
+
retval.m_FirstImage = firstImage;
if (retval.m_RenderableFlags.IsDirty())
retval.m_Dirty = true;
@@ -826,7 +844,7 @@ namespace render {
#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent) \
if ((img)) \
PrepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags, \
- theGeneratedKey, shadercomponent);
+ theGeneratedKey, shadercomponent, nullptr);
CHECK_IMAGE_AND_PREPARE(inMaterial.m_DisplacementMap, ImageMapTypes::Displacement,
SShaderDefaultMaterialKeyProperties::DisplacementMap);
@@ -1205,7 +1223,8 @@ namespace render {
if (iter->second) {
PrepareImageForRender(*iter->second, ImageMapTypes::Unknown,
firstImage, nextImage, flags, key,
- SShaderDefaultMaterialKeyProperties::ImageMapCount);
+ SShaderDefaultMaterialKeyProperties::ImageMapCount,
+ nullptr);
}
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
index 1eb8766..eae29f6 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
@@ -310,7 +310,7 @@ namespace render {
SRenderableImage *&ioFirstImage, SRenderableImage *&ioNextImage,
SRenderableObjectFlags &ioFlags,
SShaderDefaultMaterialKey &ioGeneratedShaderKey,
- QT3DSU32 inImageIndex);
+ QT3DSU32 inImageIndex, bool *opaqueCheck);
SDefaultMaterialPreparationResult
PrepareDefaultMaterialForRender(SDefaultMaterial &inMaterial,
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp
index 64de27d..c33aaeb 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp
@@ -554,19 +554,23 @@ namespace render {
};
NVRenderShaderProgram *Qt3DSRendererImpl::GenerateShader(SSubsetRenderable &inRenderable,
- TShaderFeatureSet inFeatureSet)
+ TShaderFeatureSet inFeatureSet,
+ bool depth)
{
// build a string that allows us to print out the shader we are generating to the log.
// This is time consuming but I feel like it doesn't happen all that often and is very
- // useful to users
- // looking at the log file.
+ // useful to users looking at the log file.
QLatin1String logPrefix("mesh subset pipeline-- ");
m_GeneratedShaderString.clear();
m_GeneratedShaderString.assign(logPrefix.data());
+ if (depth)
+ m_GeneratedShaderString.append("depth--");
SShaderDefaultMaterialKey theKey(inRenderable.m_ShaderDescription);
- theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties);
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties,
+ depth ? SShaderDefaultMaterialKeyProperties::DepthKey
+ : SShaderDefaultMaterialKeyProperties::DefaultKey);
IShaderCache &theCache = m_qt3dsContext.GetShaderCache();
CRegisteredString theCacheKey =
m_qt3dsContext.GetStringTable().RegisterStr(m_GeneratedShaderString.c_str());
@@ -577,6 +581,13 @@ namespace render {
SSubsetMaterialVertexPipeline pipeline(
*this, inRenderable,
m_DefaultMaterialShaderKeyProperties.m_WireframeMode.GetValue(theKey));
+ if (depth) {
+ return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateDepthPassShader(
+ inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet,
+ inRenderable.m_FirstImage,
+ inRenderable.m_RenderableFlags.HasTransparency(),
+ logPrefix.data());
+ }
return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateShader(
inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet,
m_CurrentLayer->m_Lights, inRenderable.m_FirstImage,
@@ -584,6 +595,47 @@ namespace render {
logPrefix.data());
}
+ NVRenderShaderProgram *Qt3DSRendererImpl::GenerateShadowShader(SSubsetRenderable &inRenderable,
+ TShaderFeatureSet inFeatureSet,
+ RenderLightTypes::Enum lightType)
+ {
+ // build a string that allows us to print out the shader we are generating to the log.
+ // This is time consuming but I feel like it doesn't happen all that often and is very
+ // useful to users looking at the log file.
+ QLatin1String logPrefix("mesh subset pipeline-- ");
+
+ m_GeneratedShaderString.clear();
+ m_GeneratedShaderString.assign(logPrefix.data());
+ if (lightType == RenderLightTypes::Point)
+ m_GeneratedShaderString.append("shadowcube--");
+ else
+ m_GeneratedShaderString.append("shadowmap--");
+
+ SShaderDefaultMaterialKey theKey(inRenderable.m_ShaderDescription);
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties,
+ SShaderDefaultMaterialKeyProperties::DepthKey);
+ IShaderCache &theCache = m_qt3dsContext.GetShaderCache();
+ CRegisteredString theCacheKey
+ = m_qt3dsContext.GetStringTable().RegisterStr(m_GeneratedShaderString.c_str());
+ NVRenderShaderProgram *cachedProgram = theCache.GetProgram(theCacheKey, inFeatureSet);
+ if (cachedProgram)
+ return cachedProgram;
+
+ SSubsetMaterialVertexPipeline pipeline(
+ *this, inRenderable,
+ m_DefaultMaterialShaderKeyProperties.m_WireframeMode.GetValue(theKey));
+ if (lightType == RenderLightTypes::Point) {
+ return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateCubeDepthShader(
+ inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet,
+ inRenderable.m_FirstImage, inRenderable.m_RenderableFlags.HasTransparency(),
+ logPrefix.data());
+ }
+ return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateOrthoDepthShader(
+ inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet,
+ inRenderable.m_FirstImage, inRenderable.m_RenderableFlags.HasTransparency(),
+ logPrefix.data());
+ }
+
// -------------- Special cases for shadows -------------------
SRenderableDepthPrepassShader *
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h
index 1ac85db..9753256 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h
@@ -44,8 +44,8 @@ namespace render {
*/
struct SShaderTessellationProperties
{
- NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessLevel; ///< tesselation value for the edges
- NVRenderCachedShaderProperty<QT3DSF32> m_InsideTessLevel; ///< tesselation value for the inside
+ NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessLevel; ///< tessellation value for the edges
+ NVRenderCachedShaderProperty<QT3DSF32> m_InsideTessLevel; ///< tessellation value for the inside
NVRenderCachedShaderProperty<QT3DSF32>
m_PhongBlend; ///< blending between linear and phong component
NVRenderCachedShaderProperty<QT3DSVec2>
@@ -98,34 +98,6 @@ namespace render {
}
};
- struct SDefaultMaterialRenderableDepthShader
- {
- NVAllocatorCallback &m_Allocator;
- NVRenderShaderProgram &m_Shader;
- NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
-
- QT3DSI32 m_RefCount;
- SDefaultMaterialRenderableDepthShader(NVRenderShaderProgram &inShader,
- NVRenderContext &inContext)
- : m_Allocator(inContext.GetAllocator())
- , m_Shader(inShader)
- , m_MVP("model_view_projection", inShader)
- , m_RefCount(0)
- {
- m_Shader.addRef();
- }
-
- ~SDefaultMaterialRenderableDepthShader() { m_Shader.release(); }
-
- void addRef() { ++m_RefCount; }
- void release()
- {
- --m_RefCount;
- if (m_RefCount <= 0)
- NVDelete(m_Allocator, this);
- }
- };
-
/**
* Cached texture property lookups, used one per texture so a shader generator for N
* textures will have an array of N of these lookup objects.
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
index eb23f3d..b140e85 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
@@ -154,11 +154,13 @@ struct SBufferManager : public IBufferManager
return m_StrTable->RegisterStr(m_PathBuilder.c_str());
}
- void SetImageHasTransparency(CRegisteredString inImagePath, bool inHasTransparency) override
+ void SetImageHasTransparency(CRegisteredString inImagePath, bool inHasTransparency,
+ bool hasOpaque) override
{
pair<TImageMap::iterator, bool> theImage =
m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
theImage.first->second.m_TextureFlags.SetHasTransparency(inHasTransparency);
+ theImage.first->second.m_TextureFlags.setHasOpaquePixels(hasOpaque);
}
bool GetImageHasTransparency(CRegisteredString inSourcePath) const override
@@ -169,6 +171,14 @@ struct SBufferManager : public IBufferManager
return false;
}
+ bool GetImageHasOpaquePixels(CRegisteredString inSourcePath) const override
+ {
+ TImageMap::const_iterator theIter = m_ImageMap.find(inSourcePath);
+ if (theIter != m_ImageMap.end())
+ return theIter->second.m_TextureFlags.HasOpaquePixels();
+ return false;
+ }
+
void SetImageTransparencyToFalseIfNotSet(CRegisteredString inSourcePath) override
{
pair<TImageMap::iterator, bool> theImage =
@@ -512,9 +522,12 @@ struct SBufferManager : public IBufferManager
if (theDecompressedImage.data)
inLoadedImage.ReleaseDecompressedTexture(theDecompressedImage);
}
- if (wasInserted == true || inForceScanForTransparency)
- theImage.first->second.m_TextureFlags.SetHasTransparency(
- inLoadedImage.ScanForTransparency());
+ if (wasInserted || inForceScanForTransparency) {
+ auto &flags = theImage.first->second.m_TextureFlags;
+ bool alsoOpaquePixels = false;
+ flags.SetHasTransparency(inLoadedImage.ScanForTransparency(alsoOpaquePixels));
+ flags.setHasOpaquePixels(alsoOpaquePixels);
+ }
theImage.first->second.m_Texture = theTexture;
return theImage.first->second;
}
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
index 070ab67..7930158 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
@@ -54,8 +54,9 @@ namespace render {
virtual CRegisteredString CombineBaseAndRelative(const char8_t *inBase,
const char8_t *inRelative) = 0;
virtual void SetImageHasTransparency(CRegisteredString inSourcePath,
- bool inHasTransparency) = 0;
+ bool inHasTransparency, bool alsoOpaque) = 0;
virtual bool GetImageHasTransparency(CRegisteredString inSourcePath) const = 0;
+ virtual bool GetImageHasOpaquePixels(CRegisteredString inSourcePath) const = 0;
virtual void SetImageTransparencyToFalseIfNotSet(CRegisteredString inSourcePath) = 0;
virtual void SetInvertImageUVCoords(CRegisteredString inSourcePath,
bool inShouldInvertCoords) = 0;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
index 1176273..ff221f9 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
@@ -370,9 +370,10 @@ struct STextureDataWriter
struct STextureAlphaScanner
{
bool &m_Alpha;
+ bool *m_alsoOpaque = nullptr;
- STextureAlphaScanner(bool &inAlpha)
- : m_Alpha(inAlpha)
+ STextureAlphaScanner(bool &inAlpha, bool *alsoOpaque)
+ : m_Alpha(inAlpha), m_alsoOpaque(alsoOpaque)
{
}
@@ -381,12 +382,19 @@ struct STextureAlphaScanner
Q_UNUSED(X)
Q_UNUSED(Y)
QT3DSU32 offset = 0;
- for (QT3DSU32 yidx = 0; yidx < height; ++yidx) {
- for (QT3DSU32 xidx = 0; xidx < width; ++xidx, offset += 4) {
+ bool opq = false;
+ bool exitLoop = false;
+ for (QT3DSU32 yidx = 0; yidx < height && !exitLoop; ++yidx) {
+ for (QT3DSU32 xidx = 0; xidx < width && !exitLoop; ++xidx, offset += 4) {
if (pixelData[offset + 3] < 255)
m_Alpha = true;
+ else
+ opq = true;
+ exitLoop = m_Alpha && (opq || !m_alsoOpaque);
}
}
+ if (m_alsoOpaque)
+ *m_alsoOpaque = opq;
}
// If we detect alpha we can stop right there.
@@ -423,21 +431,27 @@ static void DecompressDDS(void *inSrc, QT3DSU32 inDataSize, QT3DSU32 inWidth, QT
}
}
-bool ScanDDSForAlpha(Qt3DSDDSImage *dds)
+bool ScanDDSForAlpha(Qt3DSDDSImage *dds, bool *alsoOpaquePixels = nullptr)
{
bool hasAlpha = false;
switch (dds->format) {
case qt3ds::render::NVRenderTextureFormats::RGBA_DXT1:
DecompressDDS<DXT_BLOCKDECODER_1>(dds->data[0], dds->size[0], dds->mipwidth[0],
- dds->mipheight[0], STextureAlphaScanner(hasAlpha));
+ dds->mipheight[0], STextureAlphaScanner(hasAlpha,
+ alsoOpaquePixels)
+ );
break;
case qt3ds::render::NVRenderTextureFormats::RGBA_DXT3:
DecompressDDS<DXT_BLOCKDECODER_3>(dds->data[0], dds->size[0], dds->mipwidth[0],
- dds->mipheight[0], STextureAlphaScanner(hasAlpha));
+ dds->mipheight[0], STextureAlphaScanner(hasAlpha,
+ alsoOpaquePixels)
+ );
break;
case qt3ds::render::NVRenderTextureFormats::RGBA_DXT5:
DecompressDDS<DXT_BLOCKDECODER_5>(dds->data[0], dds->size[0], dds->mipwidth[0],
- dds->mipheight[0], STextureAlphaScanner(hasAlpha));
+ dds->mipheight[0], STextureAlphaScanner(hasAlpha,
+ alsoOpaquePixels)
+ );
break;
default:
QT3DS_ASSERT(false);
@@ -447,10 +461,11 @@ bool ScanDDSForAlpha(Qt3DSDDSImage *dds)
}
bool ScanImageForAlpha(const void *inData, QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 inPixelSizeInBytes,
- QT3DSU8 inAlphaSizeInBits)
+ QT3DSU8 inAlphaSizeInBits, bool *alsoOpaque = nullptr)
{
const QT3DSU8 *rowPtr = reinterpret_cast<const QT3DSU8 *>(inData);
bool hasAlpha = false;
+ bool hasOpaque = false;
if (inAlphaSizeInBits == 0)
return hasAlpha;
if (inPixelSizeInBytes != 2 && inPixelSizeInBytes != 4) {
@@ -476,8 +491,12 @@ bool ScanImageForAlpha(const void *inData, QT3DSU32 inWidth, QT3DSU32 inHeight,
pixelValue = pixelValue >> alphaRightShift;
if (pixelValue < maxAlphaValue)
hasAlpha = true;
+ else
+ hasOpaque = true;
}
}
+ if (alsoOpaque)
+ *alsoOpaque = hasOpaque;
return hasAlpha;
}
}
@@ -505,7 +524,7 @@ void SLoadedTexture::release()
theAllocator->deallocate(this);
}
-bool SLoadedTexture::ScanForTransparency()
+bool SLoadedTexture::ScanForTransparency(bool &alsoOpaquePixels)
{
switch (format) {
case NVRenderTextureFormats::SRGB8A8:
@@ -513,7 +532,7 @@ bool SLoadedTexture::ScanForTransparency()
if (!data) { // dds
return true;
} else {
- return ScanImageForAlpha(data, width, height, 4, 8);
+ return ScanImageForAlpha(data, width, height, 4, 8, &alsoOpaquePixels);
}
break;
// Scan the image.
@@ -528,7 +547,7 @@ bool SLoadedTexture::ScanForTransparency()
if (!data) { // dds
return true;
} else {
- return ScanImageForAlpha(data, width, height, 2, 1);
+ return ScanImageForAlpha(data, width, height, 2, 1, &alsoOpaquePixels);
}
break;
case NVRenderTextureFormats::Alpha8:
@@ -551,7 +570,7 @@ bool SLoadedTexture::ScanForTransparency()
case NVRenderTextureFormats::RGBA_DXT1:
case NVRenderTextureFormats::RGBA_DXT5:
if (dds) {
- return ScanDDSForAlpha(dds);
+ return ScanDDSForAlpha(dds, &alsoOpaquePixels);
} else {
QT3DS_ASSERT(false);
return false;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
index f019400..10200ad 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
@@ -141,7 +141,8 @@ namespace render {
void EnsureMultiplerOfFour(NVFoundationBase &inFoundation, const char *inPath);
// Returns true if this image has a pixel less than 255.
- bool ScanForTransparency();
+ // If yes, then alsoOpaquePixels is true if some are not
+ bool ScanForTransparency(bool &alsoOpaquePixels);
// Be sure to call this or risk leaking an enormous amount of memory
void release() override;