diff --git a/examples/quick3d/simple/CopperCube.qml b/examples/quick3d/simple/CopperCube.qml new file mode 100644 index 0000000000000000000000000000000000000000..bd0474a43d8a1f6b2f3fab6659f8dc08b8767e8b --- /dev/null +++ b/examples/quick3d/simple/CopperCube.qml @@ -0,0 +1,11 @@ +import QtQuick 2.12 +import QtDemon 1.0 + +DemonModel { + source: "#Cube" + property alias metalColor: copperMaterial.metal_color + materials: [ CopperMaterial { + id: copperMaterial + } + ] +} diff --git a/examples/quick3d/simple/CopperMaterial.qml b/examples/quick3d/simple/CopperMaterial.qml new file mode 100644 index 0000000000000000000000000000000000000000..ade4b408e4e01a4126b917f48e4626e3587b72ee --- /dev/null +++ b/examples/quick3d/simple/CopperMaterial.qml @@ -0,0 +1,42 @@ +import QtQuick 2.12 +import QtDemon 1.0 + +DemonCustomMaterial { + // These properties names need to match the ones in the shader code! + property bool uEnvironmentMappingEnabled: false + property bool uShadowMappingEnabled: false + property real roughness: 0.0 + property vector3d metal_color: Qt.vector3d(0.805, 0.395, 0.305) + + shaderInfo: DemonCustomMaterialShaderInfo { + version: "330" + type: "GLSL" + shaderKey: DemonCustomMaterialShaderInfo.Glossy + layers: 1 + } + + textures: [ DemonCustomMaterialTexture { + id: uEnvironmentTexture + enabled: uEnvironmentMappingEnabled + type: DemonCustomMaterialTexture.Environment + name: "uEnvironmentTexture" + image: DemonImage { + id: envImage + source: "maps/spherical_checker.png" + } + }, DemonCustomMaterialTexture { + id: uBakedShadowTexture + enabled: uShadowMappingEnabled + type: DemonCustomMaterialTexture.LightmapShadow + name: "uBakedShadowTexture" + image: DemonImage { + id: shadowImage + source: "maps/shadow.png" + } + } ] + + shaders: DemonCustomMaterialShader { + stage: DemonCustomMaterialShader.Fragment + shader: "copper.frag" + } +} diff --git a/examples/quick3d/simple/FrostedThinGlassMaterial.qml b/examples/quick3d/simple/FrostedThinGlassMaterial.qml new file mode 100644 index 0000000000000000000000000000000000000000..927c5b06fa46fb1ace31fce66a2f7879fba2c9c4 --- /dev/null +++ b/examples/quick3d/simple/FrostedThinGlassMaterial.qml @@ -0,0 +1,163 @@ +import QtQuick 2.12 +import QtDemon 1.0 + +DemonCustomMaterial { + + // <Property formalName="Glass Bump map" name="glass_bump" description="Additional bump map for surface" type="Texture" clamp="repeat" category="Material"/> + // <Property formalName="Gradient1D Map" description="Gradient texture of the material" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.jpg"/> + // <Property formalName="Gradient2D Map" description="Gradient texture of the material" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.jpg"/> + // <Property formalName="Gradient3D Map" description="Gradient texture of the material" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.jpg"/> + // <Property formalName="Gradient4D Map" description="Gradient texture of the material" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.jpg"/> + + // These properties names need to match the ones in the shader code! + property real roughness: 1.0 + property real blur_size: 8.0 + property real refract_depth: 5 + property bool uEnvironmentMappingEnabled: true + property bool uShadowMappingEnabled: false + property real glass_bfactor: 0.0 + property bool glass_binside: false + property real uFresnelPower: 1.0 + property real reflectivity_amount: 0.1 + property real glass_ior: 1.1 + property real intLightFall: 2.0 + property real intLightRot: 0.0 + property real intLightBrt: 0.0 + property real bumpScale: 0.5 + property int bumpBands: 1 + property vector3d bumpCoords: Qt.vector3d(1.0, 1.0, 1.0) + property vector2d intLightPos: Qt.vector2d(0.5, 0.0) + property vector3d glass_color: Qt.vector3d(0.9, 0.9, 0.9) + property vector3d intLightCol: Qt.vector3d(0.9, 0.9, 0.9) + hasTransparency: true + + shaderInfo: DemonCustomMaterialShaderInfo { + version: "330" + type: "GLSL" + shaderKey: DemonCustomMaterialShaderInfo.Refraction | DemonCustomMaterialShaderInfo.Glossy + layers: 1 + } + + textures: [ DemonCustomMaterialTexture { + id: uEnvironmentTexture + type: DemonCustomMaterialTexture.Environment + name: "uEnvironmentTexture" + enabled: uEnvironmentMappingEnabled + image: DemonImage { + id: envImage + source: "maps/spherical_checker.png" + } + }, DemonCustomMaterialTexture { + id: uBakedShadowTexture + type: DemonCustomMaterialTexture.LightmapShadow + name: "uBakedShadowTexture" + enabled: uShadowMappingEnabled + image: DemonImage { + id: shadowImage + source: "maps/shadow.png" + } + }, DemonCustomMaterialTexture { + id: randomGradient1D + type: DemonCustomMaterialTexture.Gradient + name: "randomGradient1D" + // hidden = true + image: DemonImage { + tilingmodehorz: DemonImage.Repeat + tilingmodevert: DemonImage.Repeat + source: "maps/randomGradient1D.png" + } + }, DemonCustomMaterialTexture { + id: randomGradient2D + type: DemonCustomMaterialTexture.Gradient + name: "randomGradient2D" + // hidden = true + image: DemonImage { + tilingmodehorz: DemonImage.Repeat + tilingmodevert: DemonImage.Repeat + source: "maps/randomGradient2D.png" + } + }, DemonCustomMaterialTexture { + id: randomGradient3D + type: DemonCustomMaterialTexture.Gradient + name: "randomGradient3D" + // hidden = true + image: DemonImage { + tilingmodehorz: DemonImage.Repeat + tilingmodevert: DemonImage.Repeat + source: "maps/randomGradient3D.png" + } + }, DemonCustomMaterialTexture { + id: randomGradient4D + type: DemonCustomMaterialTexture.Gradient + name: "randomGradient4D" + // hidden = true + image: DemonImage { + tilingmodehorz: DemonImage.Repeat + tilingmodevert: DemonImage.Repeat + source: "maps/randomGradient4D.png" + } + } ] + + shaders: [ DemonCustomMaterialShader { + stage: DemonCustomMaterialShader.Fragment + shader: "frostedThinGlass.frag" + }, DemonCustomMaterialShader { + stage: DemonCustomMaterialShader.Fragment + shader: "frostedThinGlassPreBlur.frag" + }, DemonCustomMaterialShader { + stage: DemonCustomMaterialShader.Fragment + shader: "frostedThinGlassBlurX.frag" + }, DemonCustomMaterialShader { + stage: DemonCustomMaterialShader.Fragment + shader: "frostedThinGlassBlurY.frag" + } + ] + + passes: [ DemonCustomMaterialPass { + // NOOP + // output => dummy_buffer + commands: [ DemonCustomMaterialBufferBlit { + destination: "frame_buffer" + } + ] + }, DemonCustomMaterialPass { + // PREBLUR + // output => temp_buffer + commands: [ DemonCustomMaterialBufferInput { + bufferName: "frame_buffer" + param: "OriginBuffer" + } + ] + }, DemonCustomMaterialPass { + // BLURX + // output => temp_blurX + commands: [ DemonCustomMaterialBufferInput { + bufferName: "temp_buffer" + param: "BlurBuffer" + } + ] + }, DemonCustomMaterialPass { + // BLURY + // output => temp_blurY + commands: [ DemonCustomMaterialBufferInput { + bufferName: "temp_blurX" + param: "BlurBuffer" + }, DemonCustomMaterialBufferInput { + bufferName: "temp_buffer" + param: "OriginBuffer" + } + ] + }, DemonCustomMaterialPass { + // MAIN + // output => dummy_buffer + commands: [DemonCustomMaterialBufferInput { + bufferName: "temp_blurY" + param: "refractiveTexture" + }, DemonCustomMaterialBlending { + srcBlending: DemonCustomMaterialBlending.SrcAlpha + destBlending: DemonCustomMaterialBlending.OneMinusSrcAlpha + } + ] + } + ] +} diff --git a/examples/quick3d/simple/PorcelainMaterial.qml b/examples/quick3d/simple/PorcelainMaterial.qml new file mode 100644 index 0000000000000000000000000000000000000000..40a87e1f9d2f8473aafc8115e68fafbb647f0466 --- /dev/null +++ b/examples/quick3d/simple/PorcelainMaterial.qml @@ -0,0 +1,46 @@ +import QtQuick 2.12 +import QtDemon 1.0 + +DemonCustomMaterial { + // These properties names need to match the ones in the shader code! + property bool uEnvironmentMappingEnabled: true + property bool uShadowMappingEnabled: false + property real material_ior: 1.5 + property real glossy_weight: 1.0 + property real roughness: 0.15 + property vector3d porcelain_color: Qt.vector3d(0.92, 0.92, 0.92) + + shaderInfo: DemonCustomMaterialShaderInfo { + version: "330" + type: "GLSL" + shaderKey: DemonCustomMaterialShaderInfo.Glossy + layers: 1 + } + + textures: [ DemonCustomMaterialTexture { + id: uEnvironmentTexture + type: DemonCustomMaterialTexture.Environment + name: "uEnvironmentTexture" + enabled: uEnvironmentMappingEnabled + image: DemonImage { + id: envImage + tilingmodehorz: DemonImage.Repeat + tilingmodevert: DemonImage.Repeat + source: "maps/spherical_checker.png" + } + }, DemonCustomMaterialTexture { + id: uBakedShadowTexture + type: DemonCustomMaterialTexture.LightmapShadow + enabled: uShadowMappingEnabled + name: "uBakedShadowTexture" + image: DemonImage { + id: shadowImage + source: "maps/shadow.png" + } + } ] + + shaders: DemonCustomMaterialShader { + stage: DemonCustomMaterialShader.Fragment + shader: "porcelain.frag" + } +} diff --git a/examples/quick3d/simple/SimpleGlassMaterial.qml b/examples/quick3d/simple/SimpleGlassMaterial.qml new file mode 100644 index 0000000000000000000000000000000000000000..69b6638c34e3aa261c61b16d50636a6242cf8ac1 --- /dev/null +++ b/examples/quick3d/simple/SimpleGlassMaterial.qml @@ -0,0 +1,57 @@ +import QtQuick 2.12 +import QtDemon 1.0 + +DemonCustomMaterial { + // These properties names need to match the ones in the shader code! + property bool uEnvironmentMappingEnabled: false + property bool uShadowMappingEnabled: false + property real uFresnelPower: 1.0 + property real uMinOpacity: 0.5 + property real reflectivity_amount: 1.0 + property real glass_ior: 1.1 + property vector3d glass_color: Qt.vector3d(0.9, 0.9, 0.9) + hasTransparency: true +// property alias environmentTexture: envImage.source +// property alias shadowTexture: shadowImage.source + + shaderInfo: DemonCustomMaterialShaderInfo { + version: "330" + type: "GLSL" + shaderKey: DemonCustomMaterialShaderInfo.Transparent | DemonCustomMaterialShaderInfo.Glossy + layers: 1 + } + + textures: [ DemonCustomMaterialTexture { + id: uEnvironmentTexture + type: DemonCustomMaterialTexture.Environment + name: "uEnvironmentTexture" + enabled: uEnvironmentMappingEnabled + image: DemonImage { + id: envImage + source: "maps/spherical_checker.png" + } + }, DemonCustomMaterialTexture { + id: uBakedShadowTexture + type: DemonCustomMaterialTexture.LightmapShadow + name: "uBakedShadowTexture" + enabled: uShadowMappingEnabled + image: DemonImage { + id: shadowImage + source: "maps/shadow.png" + } + } ] + + shaders: DemonCustomMaterialShader { + stage: DemonCustomMaterialShader.Fragment + shader: "simpleGlass.frag" + } + + passes: [ DemonCustomMaterialPass { + commands: [ DemonCustomMaterialBlending { + srcBlending: DemonCustomMaterialBlending.SrcAlpha + destBlending: DemonCustomMaterialBlending.OneMinusSrcAlpha + }, DemonCustomMaterialRenderState { + renderState: DemonCustomMaterialRenderState.CullFace + }] + }] +} diff --git a/examples/quick3d/simple/copper.frag b/examples/quick3d/simple/copper.frag new file mode 100644 index 0000000000000000000000000000000000000000..f3b7525f5eb969b0d7b8289d8cd0bcc94c1d4b45 --- /dev/null +++ b/examples/quick3d/simple/copper.frag @@ -0,0 +1,147 @@ +// add enum defines +#define scatter_reflect 0 +#define scatter_transmit 1 +#define scatter_reflect_transmit 2 + +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 +#define QDEMON_ENABLE_BINORMAL 0 + +#include "vertexFragmentBase.glsllib" + +// set shader output +out vec4 fragColor; + +// add structure defines +struct layer_result +{ + vec4 base; + vec4 layer; + mat3 tanFrame; +}; + + +// temporary declarations + vec4 tmpShadowTerm; + +layer_result layers[1]; + +#include "SSAOCustomMaterial.glsllib" +#include "sampleLight.glsllib" +#include "sampleProbe.glsllib" +#include "sampleArea.glsllib" +#include "square.glsllib" +#include "calculateRoughness.glsllib" +#include "evalBakedShadowMap.glsllib" +#include "evalEnvironmentMap.glsllib" +#include "luminance.glsllib" +#include "microfacetBSDF.glsllib" +#include "physGlossyBSDF.glsllib" +#include "simpleGlossyBSDF.glsllib" +#include "fresnelLayer.glsllib" + +bool evalTwoSided() +{ + return( false ); +} + +vec3 computeFrontMaterialEmissive() +{ + return( vec3( 0, 0, 0 ) ); +} + +void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect ); +#endif +} + +void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness ); +#endif +} + +void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect ); +#else + layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness ); +#endif +} + +vec3 computeBackMaterialEmissive() +{ + return( vec3(0, 0, 0) ); +} + +void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#else + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +float computeIOR() +{ + return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) ); +} + +float evalCutout() +{ + return( 1.000000 ); +} + +vec3 computeNormal() +{ + return( normal ); +} + +void computeTemporaries() +{ + tmpShadowTerm = evalBakedShadowMap( texCoord0 ); +} + +vec4 computeLayerWeights( in float alpha ) +{ + vec4 color; + color = fresnelLayer( normal, vec3( 25.65, 25.65, 25.65 ), 1.000000, vec4( metal_color, 1.0).rgb, layers[0].layer, layers[0].base, alpha ); + return color; +} + + +void initializeLayerVariables(void) +{ + // clear layers + layers[0].base = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) ); +} diff --git a/examples/quick3d/simple/frostedThinGlass.frag b/examples/quick3d/simple/frostedThinGlass.frag new file mode 100644 index 0000000000000000000000000000000000000000..30781ffbe91e71c000d0a30634894173def4cfd8 --- /dev/null +++ b/examples/quick3d/simple/frostedThinGlass.frag @@ -0,0 +1,292 @@ +// add enum defines +#define mono_alpha 0 +#define mono_average 1 +#define mono_luminance 2 +#define mono_maximum 3 +#define wrap_clamp 0 +#define wrap_repeat 1 +#define wrap_mirrored_repeat 2 +#define texture_coordinate_uvw 0 +#define texture_coordinate_world 1 +#define texture_coordinate_object 2 +#define scatter_reflect 0 +#define scatter_transmit 1 +#define scatter_reflect_transmit 2 + +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 +#define QDEMON_ENABLE_BINORMAL 0 + +#include "vertexFragmentBase.glsllib" + +// set shader output +out vec4 fragColor; + +// add structure defines +struct layer_result +{ + vec4 base; + vec4 layer; + mat3 tanFrame; +}; + +// add structure defines +struct texture_coordinate_info +{ + vec3 position; + vec3 tangent_u; + vec3 tangent_v; +}; + +struct texture_return +{ + vec3 tint; + float mono; +}; + +// temporary declarations +texture_coordinate_info tmp0; +texture_coordinate_info tmp1; +vec3 ftmp0; +vec3 ftmp1; +vec3 ftmp2; +vec4 tmpShadowTerm; + +layer_result layers[1]; + +#include "SSAOCustomMaterial.glsllib" +#include "sampleLight.glsllib" +#include "sampleProbe.glsllib" +#include "sampleArea.glsllib" +#include "square.glsllib" +#include "cube.glsllib" +#include "random255.glsllib" +#include "perlinNoise.glsllib" +#include "perlinNoiseBumpTexture.glsllib" +#include "luminance.glsllib" +#include "monoChannel.glsllib" +#include "fileBumpTexture.glsllib" +#include "transformCoordinate.glsllib" +#include "rotationTranslationScale.glsllib" +#include "coordinateSource.glsllib" +#include "calculateRoughness.glsllib" +#include "evalBakedShadowMap.glsllib" +#include "evalEnvironmentMap.glsllib" +#include "microfacetBSDF.glsllib" +#include "physGlossyBSDF.glsllib" +#include "simpleGlossyBSDF.glsllib" +#include "abbeNumberIOR.glsllib" +#include "average.glsllib" +#include "perlinNoiseTexture.glsllib" +#include "fresnelLayer.glsllib" +#include "refraction.glsllib" + +uniform sampler2D refractiveTexture; + +bool evalTwoSided() +{ + return( false ); +} + +vec3 computeFrontMaterialEmissive() +{ + return( vec3( 0, 0, 0 ) ); +} + +void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect_transmit ); + +#endif +} + +void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness ); + +#endif +} + +void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect_transmit ); + +#else + layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness ); + +#endif +} + +vec3 computeBackMaterialEmissive() +{ + return( vec3(0, 0, 0) ); +} + +void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#else + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +float computeIOR() +{ + return( false ? 1.0f : luminance( vec3( abbeNumberIOR(glass_ior, 0.000000 ) ) ) ); +} + +float evalCutout() +{ + return( 1.000000 ); +} + +vec3 computeNormal() +{ + if ( glass_bfactor > 0.0 ) + { + ftmp2 = fileBumpTexture(glass_bump, glass_bfactor, mono_average, tmp0, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ); + if (!glass_binside) { normal = ftmp2; } + } + + return( perlinNoiseBumpTexture( tmp1, bumpScale, 1.000000, false, false, 0.000000, bumpBands, false, vec3( 0.000000, 0.000000, 0.000000 ), 0.5, 0.0, 1.000000, normal ) ); +} + +void computeTemporaries() +{ + //tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), refractCoords ), coordinateSource(texture_coordinate_world, 0 ) ); + //ftmp1 = perlinNoiseBumpTexture( tmp0, refractScale, 1.000000, false, false, 0.000000, 1, false, vec3( 0.000000, 0.000000, 0.000000 ), 1.0, 0.5, 1.000000, viewDir ); + tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), textureCoordinateInfo( texCoord0, tangent, binormal ) ); + tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), coordinateSource(texture_coordinate_world, 0 ) ); + ftmp1 = viewDir; + ftmp0 = vec3( reflectivity_amount ); + tmpShadowTerm = evalBakedShadowMap( texCoord0 ); +} + +vec4 computeLayerWeights( in float alpha ) +{ + vec4 color; + color = layers[0].base * vec4( ftmp0, 1.0); + return color; +} + + +void initializeLayerVariables(void) +{ + // clear layers + layers[0].base = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) ); +} + +vec3 getRefractUV( in vec2 baseUV, in vec3 normal, in float materialIOR, in float refractDepth ) +{ + // Real honest-to-goodness refraction! + vec3 refractedDir = refract( -viewDir, normal, 1.0 / materialIOR ); + float thickness = refractDepth / clamp( dot(viewDir, normal), 0.0001, 1.0 ); + + // This will do an "AA" version of that loss due to critical angle and TIR + // fakes the same effect than using the glsl refract. + float weight = smoothstep( 0.0, 1.0, abs(dot(viewDir, normal)) * 100.0 ); + + // Trace out the refracted ray and the straight view ray + refractedDir *= thickness; + vec3 rawDir = -viewDir * thickness; + + vec3 displace = refractedDir - rawDir; + vec3 newUV = vec3(baseUV + displace.xy, weight); + return newUV; +} + +vec4 doFakeInnerLight( in vec3 normal, in vec3 absorb_color ) +{ + vec3 lightColor = intLightCol * intLightBrt; + + float cosRot = cos(intLightRot * 0.01745329251); + float sinRot = sin(intLightRot * 0.01745329251); + vec2 uvDir = vec2(sinRot, cosRot); + + vec2 dvec = texCoord0.xy - intLightPos; + float dist = dot( dvec, uvDir ); + float fallRate = log2( max( abs(intLightFall), 1.01 ) ); + vec3 fallCol = exp2( -abs(dist) * fallRate / absorb_color ); + + vec3 projDir = (tangent * uvDir.x + binormal * uvDir.y) * dist * intLightFall - surfNormal * refract_depth; + projDir = normalize(projDir); + + vec4 retVal = vec4(lightColor * fallCol, 1.0); + retVal *= abs(dot( projDir, -ftmp2 )); + retVal.a = pow( retVal.a, uFresnelPower ); + retVal.a *= clamp( intLightBrt * exp2(-dist * fallRate), 0.0, 1.0 ); + + return retVal; +} + +vec4 computeGlass(in vec3 normal, in float materialIOR, in float alpha, in vec4 color) +{ + vec4 rgba = color; + float ratio = simpleFresnel( normal, materialIOR, uFresnelPower ); + vec3 absorb_color = ( log( glass_color ) * -1.000000 ); + // prevent log(0) -> inf number issue + if ( isinf(absorb_color.r) ) absorb_color.r = 1.0; + if ( isinf(absorb_color.g) ) absorb_color.g = 1.0; + if ( isinf(absorb_color.b) ) absorb_color.b = 1.0; + rgba.rgb *= (vec3(1.0) - absorb_color); + + vec2 texSize = vec2( textureSize( refractiveTexture, 0 ) ); + vec3 newUV = vec3((gl_FragCoord.xy * 0.5) / texSize, 0.0); + vec4 value = texture( refractiveTexture, newUV.xy ); + + newUV = getRefractUV( newUV.xy, normal, materialIOR, 0.01 * refract_depth ); + vec4 refractValue = texture( refractiveTexture, newUV.xy ); + + vec3 refractColor = refractValue.a * refractValue.rgb + (1.0 - refractValue.a) * value.rgb; + refractColor = refractColor * (vec3(1.0) - absorb_color); + vec4 internalColor = doFakeInnerLight( normal, glass_color ); + refractColor += internalColor.rgb * internalColor.a; + + rgba = vec4(mix(refractColor, rgba.rgb, ratio), 1.0); + return rgba; +} + + </FragmentShader> + </Shader> + <Shader name="NOOP"> +<VertexShader> +</VertexShader> +<FragmentShader> +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 + +vec3 texCoord0; + +void main() +{ + + // This is a bit silly, but the thing is that a buffer blit takes place on this + // pass, and if you do a buffer blit on a pass that outputs to lower-resolution, + // it only blits a smaller portion of the backbuffer that occupies that number of + // pixels. So we need a dummy no-op pass that is full-res in order to blit everything. diff --git a/examples/quick3d/simple/frostedThinGlassBlurX.frag b/examples/quick3d/simple/frostedThinGlassBlurX.frag new file mode 100644 index 0000000000000000000000000000000000000000..97918501af74e58892a453e207e21f1699504da8 --- /dev/null +++ b/examples/quick3d/simple/frostedThinGlassBlurX.frag @@ -0,0 +1,34 @@ +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 + +vec3 texCoord0; + +uniform sampler2D BlurBuffer; + +void main() +{ + vec2 texSize = vec2( textureSize( BlurBuffer, 0 ) ); + texSize = vec2(1.0) / texSize; + texCoord0.z = 0.0; + texCoord0.xy = vec2(gl_FragCoord.xy * texSize); + + float sigma = clamp(blur_size * 0.5, 0.5, 100.0); + int smpCount = int(ceil( sigma )); + vec4 value = texture(BlurBuffer, texCoord0.xy); + float wtsum = 1.0; + for (int i = 1; i <= smpCount; ++i) + { + // Base 2 Gaussian blur + float wt = float(i) / (sigma * 0.5); + wt = exp2( -wt*wt ); + vec2 texOfs = vec2(i, 0) * texSize; + value += wt * texture(BlurBuffer, texCoord0.xy+texOfs); + value += wt * texture(BlurBuffer, texCoord0.xy-texOfs); + wtsum += wt * 2.0; + } + + gl_FragColor = value / wtsum; + gl_FragColor.a = 1.0; + + // No close paren because the generator adds it for us. diff --git a/examples/quick3d/simple/frostedThinGlassBlurY.frag b/examples/quick3d/simple/frostedThinGlassBlurY.frag new file mode 100644 index 0000000000000000000000000000000000000000..5a9c5f8366577e1b2444b95974289da8771b2003 --- /dev/null +++ b/examples/quick3d/simple/frostedThinGlassBlurY.frag @@ -0,0 +1,41 @@ +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 + +vec3 texCoord0; + +uniform sampler2D BlurBuffer; +uniform sampler2D OriginBuffer; + +void main() +{ + vec2 texSize = vec2( textureSize( BlurBuffer, 0 ) ); + texSize = vec2(1.0) / texSize; + texCoord0.z = 0.0; + texCoord0.xy = vec2(gl_FragCoord.xy * texSize); + + float sigma = clamp(blur_size * 0.5, 0.5, 100.0); + int smpCount = int(ceil( sigma )); + vec4 value = texture(BlurBuffer, texCoord0.xy); + + float wtsum = 1.0; + for (int i = 1; i <= smpCount; ++i) + { + // Base 2 Gaussian blur + float wt = float(i) / (sigma * 0.5); + wt = exp2( -wt*wt ); + vec2 texOfs = vec2(0, i) * texSize; + vec4 posValue = texture(BlurBuffer, texCoord0.xy+texOfs); + vec4 negValue = texture(BlurBuffer, texCoord0.xy-texOfs); + posValue = posValue.a * posValue + (1.0 - posValue.a) * texture(OriginBuffer, texCoord0.xy+texOfs); + negValue = negValue.a * negValue + (1.0 - negValue.a) * texture(OriginBuffer, texCoord0.xy-texOfs); + + value += wt * posValue; + value += wt * negValue; + wtsum += wt * 2.0; + } + + gl_FragColor = (value / wtsum); + gl_FragColor.a = 1.0; + + // No close paren because the generator adds it for us. diff --git a/examples/quick3d/simple/frostedThinGlassPreBlur.frag b/examples/quick3d/simple/frostedThinGlassPreBlur.frag new file mode 100644 index 0000000000000000000000000000000000000000..ac656bb56ee88a064db5960dbec0c79910554b5c --- /dev/null +++ b/examples/quick3d/simple/frostedThinGlassPreBlur.frag @@ -0,0 +1,32 @@ +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 + +vec3 texCoord0; + +uniform sampler2D OriginBuffer; + +void main() +{ + vec2 texSize = vec2( textureSize( OriginBuffer, 0 ) ); + texSize = vec2(1.0) / texSize; + texCoord0.z = 0.0; + texCoord0.xy = vec2(gl_FragCoord.xy * 2.0 * texSize); + + float wtSum = 0.0; + vec4 totSum = vec4(0.0); + for (int ix = -1; ix <= 1; ++ix) + { + for (int iy = -1; iy <= 1; ++iy) + { + float wt = float(ix*ix + iy*iy) * 4.0; + wt = exp2( -wt ); + vec2 texOfs = vec2(ix, iy) * texSize; + totSum += wt * texture( OriginBuffer, texCoord0.xy + texOfs ); + wtSum += wt; + } + } + + totSum /= wtSum; + gl_FragColor = totSum; + // No close paren because the generator adds it for us. diff --git a/examples/quick3d/simple/main.qml b/examples/quick3d/simple/main.qml index aa9526bcccb19081639b5d2b61140d8e17afdf19..da5bc0113ed2d9b59beb4c3a30945dff44c6b9af 100644 --- a/examples/quick3d/simple/main.qml +++ b/examples/quick3d/simple/main.qml @@ -15,17 +15,23 @@ Window { camera: camera // Light always points the same direction as camera - DemonLight { - id: directionalLight - lightType: DemonLight.Directional - rotation: Qt.vector3d(0, 0, 0) - SequentialAnimation on rotation { - loops: Animation.Infinite - PropertyAnimation { duration: 5000; to: Qt.vector3d(0, 360, 0); from: Qt.vector3d(0, 0, 0) } +// DemonLight { +// id: directionalLight +// lightType: DemonLight.Directional +// rotation: Qt.vector3d(0, 0, 0) +// SequentialAnimation on rotation { +// loops: Animation.Infinite +// PropertyAnimation { duration: 5000; to: Qt.vector3d(0, 360, 0); from: Qt.vector3d(0, 0, 0) } +// } +// } + + environment: DemonSceneEnvironment { + probeBrightness: 1000 + lightProbe: DemonImage { + source: ":/maps/OpenfootageNET_garage-1024.hdr" } } - DemonNode { id: cameraSpinner position: Qt.vector3d(0, 0, 0); @@ -99,5 +105,22 @@ Window { x: -300 } + CopperCube { + id: copperCube + SequentialAnimation on metalColor { + loops: Animation.Infinite + PropertyAnimation { duration: 2000; to: Qt.vector3d(0.805, 0.0, 0.305) } + PropertyAnimation { duration: 2000; to: Qt.vector3d(0.805, 1.0, 0.305) } + } + } + + DemonModel { + position: Qt.vector3d(300, 0, 0) + source: "#Cube" + materials: [ SimpleGlassMaterial { + id: texturedCubeMaterial + } + ] + } } } diff --git a/examples/quick3d/simple/maps/OpenfootageNET_garage-1024.hdr b/examples/quick3d/simple/maps/OpenfootageNET_garage-1024.hdr new file mode 100644 index 0000000000000000000000000000000000000000..01e9e38ac2eb48679de45be85aca47f658da44d6 Binary files /dev/null and b/examples/quick3d/simple/maps/OpenfootageNET_garage-1024.hdr differ diff --git a/examples/quick3d/simple/maps/shadow.png b/examples/quick3d/simple/maps/shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..599b1cccae8fef146df32ed5a8f0897e3b6a2dba Binary files /dev/null and b/examples/quick3d/simple/maps/shadow.png differ diff --git a/examples/quick3d/simple/maps/spherical_checker.png b/examples/quick3d/simple/maps/spherical_checker.png new file mode 100644 index 0000000000000000000000000000000000000000..e42394dd0e197df98d57042a71dea8949e7c5e66 Binary files /dev/null and b/examples/quick3d/simple/maps/spherical_checker.png differ diff --git a/examples/quick3d/simple/materials.qrc b/examples/quick3d/simple/materials.qrc new file mode 100644 index 0000000000000000000000000000000000000000..54e013406e250dd44f2c73754a00b5465500c0a0 --- /dev/null +++ b/examples/quick3d/simple/materials.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>maps/shadow.png</file> + <file>maps/spherical_checker.png</file> + <file>maps/OpenfootageNET_garage-1024.hdr</file> + </qresource> +</RCC> diff --git a/examples/quick3d/simple/porcelain.frag b/examples/quick3d/simple/porcelain.frag new file mode 100644 index 0000000000000000000000000000000000000000..81357a99113d1acee2eadf71cff61da9f835704c --- /dev/null +++ b/examples/quick3d/simple/porcelain.frag @@ -0,0 +1,149 @@ +// add enum defines +#define scatter_reflect 0 +#define scatter_transmit 1 +#define scatter_reflect_transmit 2 + +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 +#define QDEMON_ENABLE_BINORMAL 0 + +#include "vertexFragmentBase.glsllib" + +// set shader output +out vec4 fragColor; + +// add structure defines +struct layer_result +{ + vec4 base; + vec4 layer; + mat3 tanFrame; +}; + + +// temporary declarations +vec4 tmpShadowTerm; + +layer_result layers[1]; + +#include "SSAOCustomMaterial.glsllib" +#include "sampleLight.glsllib" +#include "sampleProbe.glsllib" +#include "sampleArea.glsllib" +#include "square.glsllib" +#include "calculateRoughness.glsllib" +#include "evalBakedShadowMap.glsllib" +#include "evalEnvironmentMap.glsllib" +#include "luminance.glsllib" +#include "microfacetBSDF.glsllib" +#include "physGlossyBSDF.glsllib" +#include "simpleGlossyBSDF.glsllib" +#include "diffuseReflectionBSDF.glsllib" +#include "fresnelLayer.glsllib" + +bool evalTwoSided() +{ + return( false ); +} + +vec3 computeFrontMaterialEmissive() +{ + return( vec3( 0, 0, 0 ) ); +} + +void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 ); + layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect ); +#endif +} + +void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx ); + layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness ); +#endif +} + +void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor; + layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect ); + +#else + layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor; + layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness ); +#endif +} + +vec3 computeBackMaterialEmissive() +{ + return( vec3(0, 0, 0) ); +} + +void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#else + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +float computeIOR() +{ + return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) ); +} + +float evalCutout() +{ + return( 1.000000 ); +} + +vec3 computeNormal() +{ + return( normal ); +} + +void computeTemporaries() +{ + tmpShadowTerm = evalBakedShadowMap( texCoord0 ); +} + +vec4 computeLayerWeights( in float alpha ) +{ + vec4 color; + color = fresnelLayer( normal, vec3( material_ior ), glossy_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, layers[0].base * vec4( porcelain_color, 1.0), alpha ); + return color; +} + + +void initializeLayerVariables(void) +{ + // clear layers + layers[0].base = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) ); +} diff --git a/examples/quick3d/simple/qml.qrc b/examples/quick3d/simple/qml.qrc index f7b651bd9a133b13669d0745875a04a91bcc8bd5..e1838058e26698956998cda1cc243db89bbab4f8 100644 --- a/examples/quick3d/simple/qml.qrc +++ b/examples/quick3d/simple/qml.qrc @@ -6,5 +6,17 @@ <file>WeirdShape.qml</file> <file>texture.png</file> <file>TexturedCube.qml</file> + <file>CopperCube.qml</file> + <file>CopperMaterial.qml</file> + <file>copper.frag</file> + <file>SimpleGlassMaterial.qml</file> + <file>PorcelainMaterial.qml</file> + <file>porcelain.frag</file> + <file>simpleGlass.frag</file> + <file>frostedThinGlass.frag</file> + <file>FrostedThinGlassMaterial.qml</file> + <file>frostedThinGlassPreBlur.frag</file> + <file>frostedThinGlassBlurX.frag</file> + <file>frostedThinGlassBlurY.frag</file> </qresource> </RCC> diff --git a/examples/quick3d/simple/simple.pro b/examples/quick3d/simple/simple.pro index 23378a076d133442a1a8eb5722130064074d5f97..ee48a6d33249cbc1f982091fb3ec5945c2e7c34d 100644 --- a/examples/quick3d/simple/simple.pro +++ b/examples/quick3d/simple/simple.pro @@ -8,4 +8,5 @@ SOURCES += \ main.cpp RESOURCES += \ - qml.qrc + qml.qrc \ + materials.qrc diff --git a/examples/quick3d/simple/simpleGlass.frag b/examples/quick3d/simple/simpleGlass.frag new file mode 100644 index 0000000000000000000000000000000000000000..1406c2451150ce580dd57b16bb16a54f4b76b396 --- /dev/null +++ b/examples/quick3d/simple/simpleGlass.frag @@ -0,0 +1,161 @@ +// add enum defines +#define scatter_reflect 0 +#define scatter_transmit 1 +#define scatter_reflect_transmit 2 + +#define QDEMON_ENABLE_UV0 1 +#define QDEMON_ENABLE_WORLD_POSITION 1 +#define QDEMON_ENABLE_TEXTAN 1 +#define QDEMON_ENABLE_BINORMAL 0 + +#include "vertexFragmentBase.glsllib" + +// set shader output +out vec4 fragColor; + +// add structure defines +struct layer_result +{ + vec4 base; + vec4 layer; + mat3 tanFrame; +}; + + +// temporary declarations +vec3 ftmp0; + vec4 tmpShadowTerm; + +layer_result layers[1]; + +#include "SSAOCustomMaterial.glsllib" +#include "sampleLight.glsllib" +#include "sampleProbe.glsllib" +#include "sampleArea.glsllib" +#include "square.glsllib" +#include "calculateRoughness.glsllib" +#include "evalBakedShadowMap.glsllib" +#include "evalEnvironmentMap.glsllib" +#include "luminance.glsllib" +#include "microfacetBSDF.glsllib" +#include "physGlossyBSDF.glsllib" +#include "simpleGlossyBSDF.glsllib" +#include "abbeNumberIOR.glsllib" +#include "fresnelLayer.glsllib" +#include "refraction.glsllib" + +bool evalTwoSided() +{ + return( true ); +} + +vec3 computeFrontMaterialEmissive() +{ + return( vec3( 0, 0, 0 ) ); +} + +void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.000000, 0.000000, scatter_reflect_transmit ); +#endif +} + +void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, 0.000000, 0.000000 ); +#endif +} + +void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, 0.000000, 0.000000, scatter_reflect_transmit ); +#else + layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 ); +#endif +} + +vec3 computeBackMaterialEmissive() +{ + return( vec3(0, 0, 0) ); +} + +void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular ) +{ +#if QDEMON_ENABLE_CG_LIGHTING + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor ) +{ +#if !QDEMON_ENABLE_LIGHT_PROBE + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#else + layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 ); + layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 ); +#endif +} + +float computeIOR() +{ + return( true ? 1.0f : luminance( vec3( abbeNumberIOR(glass_ior, 0.000000 ) ) ) ); +} + +float evalCutout() +{ + return( 1.000000 ); +} + +vec3 computeNormal() +{ + return( normal ); +} + +void computeTemporaries() +{ + ftmp0 = vec3( reflectivity_amount ); + tmpShadowTerm = evalBakedShadowMap( texCoord0 ); +} + +vec4 computeLayerWeights( in float alpha ) +{ + vec4 color; + color = layers[0].base * vec4( ftmp0, 1.0); + return color; +} + + +void initializeLayerVariables(void) +{ + // clear layers + layers[0].base = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0); + layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) ); +} + +vec4 computeGlass(in vec3 normal, in float materialIOR, in float alpha, in vec4 color) +{ + vec4 rgba = color; + float ratio = simpleFresnel( normal, materialIOR, uFresnelPower ); + vec3 absorb_color = ( log( glass_color )/-1.000000 ); + // prevent log(0) -> inf number issue + if ( isinf(absorb_color.r) ) absorb_color.r = 1.0; + if ( isinf(absorb_color.g) ) absorb_color.g = 1.0; + if ( isinf(absorb_color.b) ) absorb_color.b = 1.0; + rgba.rgb = mix(vec3(1.0) - absorb_color, rgba.rgb * (vec3(1.0) - absorb_color), ratio); + rgba.a = mix(uMinOpacity, alpha, ratio); + return rgba; +} diff --git a/src/imports/demon/plugin.cpp b/src/imports/demon/plugin.cpp index 426abd5ff8458fdb935de7994c8371b75bea32f9..f904ad8c53793932b12eaa54c2d8cda25f2c049f 100644 --- a/src/imports/demon/plugin.cpp +++ b/src/imports/demon/plugin.cpp @@ -86,6 +86,15 @@ public: qmlRegisterType<QDemonCamera>(uri, 1, 0, "DemonCamera"); qmlRegisterType<QDemonCustomMaterial>(uri, 1, 0, "DemonCustomMaterial"); + qmlRegisterType<QDemonCustomMaterialShader>(uri, 1, 0, "DemonCustomMaterialShader"); + qmlRegisterType<QDemonCustomMaterialShaderInfo>(uri, 1, 0, "DemonCustomMaterialShaderInfo"); + qmlRegisterType<QDemonCustomMaterialTexture>(uri, 1, 0, "DemonCustomMaterialTexture"); + qmlRegisterType<QDemonCustomMaterialRenderPass>(uri, 1, 0, "DemonCustomMaterialPass"); + qmlRegisterType<QDemonCustomMaterialRenderCommand>(uri, 1, 0, "DemonCustomMaterialCommand"); + qmlRegisterType<QDemonCustomMaterialBufferInput>(uri, 1, 0, "DemonCustomMaterialBufferInput"); + qmlRegisterType<QDemonCustomMaterialBufferBlit>(uri, 1, 0, "DemonCustomMaterialBufferBlit"); + qmlRegisterType<QDemonCustomMaterialBlending>(uri, 1, 0, "DemonCustomMaterialBlending"); + qmlRegisterType<QDemonCustomMaterialRenderState>(uri, 1, 0, "DemonCustomMaterialRenderState"); qmlRegisterType<QDemonDefaultMaterial>(uri, 1, 0, "DemonDefaultMaterial"); qmlRegisterType<QDemonEffect>(uri, 1, 0, "DemonEffect"); qmlRegisterType<QDemonImage>(uri, 1, 0, "DemonImage"); diff --git a/src/quick3d/qdemoncustommaterial.cpp b/src/quick3d/qdemoncustommaterial.cpp index 6550e7581976a6154266cb65e0d0687205c98199..2e4e9c097cd7e3c6b5f1ea237028f6109d139840 100644 --- a/src/quick3d/qdemoncustommaterial.cpp +++ b/src/quick3d/qdemoncustommaterial.cpp @@ -1,5 +1,9 @@ #include "qdemoncustommaterial.h" #include <QtDemonRuntimeRender/qdemonrendercustommaterial.h> +#include <QtDemonRuntimeRender/qdemonrendercontextcore.h> + +#include "qdemonobject_p.h" +#include "qdemonview3d.h" QT_BEGIN_NAMESPACE @@ -32,6 +36,46 @@ QString QDemonCustomMaterial::source() const return m_source; } +QDemonCustomMaterialShaderInfo *QDemonCustomMaterial::shaderInfo() const +{ + return m_shaderInfo; +} + +QQmlListProperty<QDemonCustomMaterialShader> QDemonCustomMaterial::shaders() +{ + return QQmlListProperty<QDemonCustomMaterialShader>(this, + nullptr, + QDemonCustomMaterial::qmlAppendShader, + QDemonCustomMaterial::qmlShaderCount, + QDemonCustomMaterial::qmlShaderAt, + nullptr); +} + +QQmlListProperty<QDemonCustomMaterialTexture> QDemonCustomMaterial::textures() +{ + return QQmlListProperty<QDemonCustomMaterialTexture>(this, + nullptr, + QDemonCustomMaterial::qmlAppendTexture, + QDemonCustomMaterial::qmlTextureCount, + QDemonCustomMaterial::qmlTextureAt, + nullptr); +} + +QQmlListProperty<QDemonCustomMaterialRenderPass> QDemonCustomMaterial::passes() +{ + return QQmlListProperty<QDemonCustomMaterialRenderPass>(this, + nullptr, + QDemonCustomMaterial::qmlAppendPass, + QDemonCustomMaterial::qmlPassCount, + QDemonCustomMaterial::qmlPassAt, + nullptr); +} + +bool QDemonCustomMaterial::alwaysDirty() const +{ + return m_alwaysDirty; +} + void QDemonCustomMaterial::setHasTransparency(bool hasTransparency) { if (m_hasTransparency == hasTransparency) @@ -68,11 +112,375 @@ void QDemonCustomMaterial::setSource(QString source) emit sourceChanged(m_source); } +void QDemonCustomMaterial::setShaderInfo(QDemonCustomMaterialShaderInfo *shaderInfo) +{ + m_shaderInfo = shaderInfo; +} + +void QDemonCustomMaterial::setAlwaysDirty(bool alwaysDirty) +{ + if (m_alwaysDirty == alwaysDirty) + return; + + m_alwaysDirty = alwaysDirty; + emit alwaysDirtyChanged(m_alwaysDirty); +} + QDemonRenderGraphObject *QDemonCustomMaterial::updateSpatialNode(QDemonRenderGraphObject *node) { - // TODO: Create and update customer material (special) + static const auto updateShaderPrefix = [](QByteArray &shaderPrefix, const QByteArray &name) { + const char *filter = "linear"; + const char *clamp = "clamp"; + // Output macro so we can change the set of variables used for this + // independent of the + // meta data system. + shaderPrefix.append("SNAPPER_SAMPLER2D("); + shaderPrefix.append(name); + shaderPrefix.append(", "); + shaderPrefix.append(name); + shaderPrefix.append(", "); + shaderPrefix.append(filter); + shaderPrefix.append(", "); + shaderPrefix.append(clamp); + shaderPrefix.append(", "); + shaderPrefix.append("false )\n"); + }; + + static const auto appendShaderUniform = [](const QString &type, const QByteArray &name, QByteArray *shaderPrefix, const QString &value = QString()) { + shaderPrefix->append(QStringLiteral("uniform %1 %2 %3;\n").arg(type).arg(QString::fromLatin1(name)).arg(value.isEmpty() ? QString() : QString("= %1").arg(value)).toLatin1()); + }; + + static const auto resolveShader = [](const QByteArray &shader) -> QByteArray { + int offset = -1; + if (shader.startsWith("qrc")) + offset = 3; + else if (shader.startsWith("file:/")) + offset = 0; + else if (shader.startsWith(":/")) + offset = 0; + + QString path; + if (offset == -1) { + QUrl u(QString::fromUtf8(shader)); + if (u.isLocalFile()) + path = u.toLocalFile(); + } - return node; + if (offset == -1 && path.isEmpty()) + path = QString::fromLatin1(":/") + QString::fromUtf8(shader); + else + path = QString::fromUtf8(shader.constData() + offset); + + QFile f(path); + if (f.open(QIODevice::ReadOnly | QIODevice::Text)) + return f.readAll(); + + return shader; + }; + + + // Sanity check(s) + if (!m_shaderInfo->isValid()) { + qWarning("ShaderInfo is not valid!"); + return node; + } + + if (node) + QDemonMaterial::updateSpatialNode(node); + + QDemonRenderCustomMaterial *customMaterial = static_cast<QDemonRenderCustomMaterial *>(node); + if (!customMaterial) { + customMaterial = new QDemonRenderCustomMaterial; + customMaterial->m_layerCount = m_shaderInfo->layers; + customMaterial->m_shaderKeyValues = static_cast<QDemonRenderCustomMaterial::MaterialShaderKeyFlags>(m_shaderInfo->shaderKey); + customMaterial->className = metaObject()->className(); + customMaterial->m_alwaysDirty = m_alwaysDirty; + customMaterial->m_hasTransparency = m_hasTransparency; + customMaterial->m_hasRefraction = m_hasRefraction; + customMaterial->m_hasVolumetricDF = m_hasVolumetricDF; + + // Shader info + auto &shaderInfo = customMaterial->shaderInfo; + shaderInfo.type = m_shaderInfo->type; + shaderInfo.version = m_shaderInfo->version; + shaderInfo.shaderPrefix = m_shaderInfo->shaderPrefix; + + QMetaMethod propertyDirtyMethod; + const int idx = metaObject()->indexOfSlot("onPropertyDirty()"); + if (idx != -1) + propertyDirtyMethod = metaObject()->method(idx); + + // Properties + const int propCount = metaObject()->propertyCount(); + const int propOffset = metaObject()->propertyOffset(); + for (int i = propOffset; i != propCount; ++i) { + const auto property = metaObject()->property(i); + if (Q_UNLIKELY(!property.isValid())) + continue; + + // Track the property changes + if (property.hasNotifySignal() && propertyDirtyMethod.isValid()) + connect(this, property.notifySignal(), this, propertyDirtyMethod); + + const QVariant value = property.read(this); + if (Q_UNLIKELY(!value.isValid())) + continue; + + QDemonRenderCustomMaterial::Property demonProp; + demonProp.name = property.name(); + demonProp.value = value; + demonProp.pid = i; + QString type; + // TODO: Only types for copper are vec3, bool and float + if (value.type() == QVariant::Double) { + type = QStringLiteral("float"); + demonProp.shaderDataType = QDemonRenderShaderDataType::Float; + } else if (value.type() == QVariant::Bool) { + type = QStringLiteral("bool"); + demonProp.shaderDataType = QDemonRenderShaderDataType::Boolean; + } else if (value.type() == QVariant::Vector2D) { + type = QStringLiteral("vec2"); + demonProp.shaderDataType = QDemonRenderShaderDataType::Vec2; + } else if (value.type() == QVariant::Vector3D) { + type = QStringLiteral("vec3"); + demonProp.shaderDataType = QDemonRenderShaderDataType::Vec3; + } else if (value.type() == QVariant::Vector4D) { + type = QStringLiteral("vec4"); + demonProp.shaderDataType = QDemonRenderShaderDataType::Vec4; + } else if (value.type() == QVariant::Int) { + type = QStringLiteral("int"); + demonProp.shaderDataType = QDemonRenderShaderDataType::Integer; + } else { + Q_ASSERT(0); + } + + appendShaderUniform(type, demonProp.name, &shaderInfo.shaderPrefix); + customMaterial->properties.push_back(demonProp); + } + + // Textures + for (const auto &texture : qAsConst(m_textures)) { + QDemonRenderCustomMaterial::TextureProperty textureData; + const QByteArray &name = texture->name; + if (name.isEmpty()) // Warnings here will just drown in the shader error messages + continue; + QDemonImage *image = texture->image(); // + connect(texture, &QDemonCustomMaterialTexture::textureDirty, this, &QDemonCustomMaterial::onTextureDirty); + textureData.name = name; + if (texture->enabled) + textureData.texImage = image->getRenderImage(); + textureData.usageType = QDemonRenderTextureTypeValue(texture->type); + textureData.shaderDataType = QDemonRenderShaderDataType::Texture2D; + textureData.clampType = image->horizontalTiling() == QDemonImage::Repeat ? QDemonRenderTextureCoordOp::Repeat + : (image->horizontalTiling() == QDemonImage::ClampToEdge) ? QDemonRenderTextureCoordOp::ClampToEdge + : QDemonRenderTextureCoordOp::MirroredRepeat; + updateShaderPrefix(shaderInfo.shaderPrefix, textureData.name); + customMaterial->textureProperties.push_back(textureData); + } + + // Shaders + QByteArray shaderCode = shaderInfo.shaderPrefix; + QByteArray shared, vertex, geometry, fragment; + for (const auto &shader : qAsConst(m_shaders)) { + const QByteArray code = resolveShader(shader->shader); + switch (shader->stage) { + case QDemonCustomMaterialShader::Stage::Shared: + if (!code.isEmpty()) + shared.append(code); + break; + case QDemonCustomMaterialShader::Stage::Geometry: + if (!code.isEmpty()) { + geometry.append(QByteArrayLiteral("\n#ifdef USER_GEOMETRY_SHADER\n")); + geometry.append(code); + geometry.append(QByteArrayLiteral("\n#endif\n")); + // TODO: Set m_HasGeomShader to true + } + break; + case QDemonCustomMaterialShader::Stage::Vertex: + vertex.append(QByteArrayLiteral("\n#ifdef VERTEX_SHADER\n")); + if (code.isEmpty()) + vertex.append(QByteArrayLiteral("void vert(){}")); + else + vertex.append(code); + vertex.append(QByteArrayLiteral("\n#endif\n")); + break; + case QDemonCustomMaterialShader::Stage::Fragment: + fragment.append(QByteArrayLiteral("\n#ifdef FRAGMENT_SHADER\n")); + if (code.isEmpty()) + fragment.append(QByteArrayLiteral("void frag(){}")); + else + fragment.append(code); + fragment.append(QByteArrayLiteral("\n#endif\n")); + break; + } + } + + if (!shared.isEmpty()) + shaderCode.append(shared); + if (!vertex.isEmpty()) + shaderCode.append(vertex); + if (!geometry.isEmpty()) + shaderCode.append(geometry); + if (!fragment.isEmpty()) + shaderCode.append(fragment); + + if (!m_shaders.isEmpty()) { + // Find the parent view + QObject *p = this; + QDemonView3D *view = nullptr; + while (p != nullptr && view == nullptr) { + p = p->parent(); + if ((view = qobject_cast<QDemonView3D *>(p))) + break; + } + + Q_ASSERT(view); + + customMaterial->commands.push_back(new dynamic::QDemonBindShader(metaObject()->className())); + customMaterial->commands.push_back(new dynamic::QDemonApplyInstanceValue()); + + QDemonRenderContextInterface::QDemonRenderContextInterfacePtr renderContext = QDemonRenderContextInterface::getRenderContextInterface(quintptr(view->window())); + renderContext->customMaterialSystem()->setMaterialClassShader(QString::fromLatin1(customMaterial->className), shaderInfo.type, shaderInfo.version, shaderCode, false, false); + } + + for (const auto &pass : qAsConst(m_passes)) { + QDemonRenderCustomMaterial::Pass demonPass; + for (const auto &command : pass->m_commands) + customMaterial->commands.push_back(command->getCommand()); + customMaterial->passes.push_back(demonPass); + } + + customMaterial->commands.push_back(new dynamic::QDemonRender(false)); + } + + if (m_dirtyAttributes & Dirty::PropertyDirty) { + for (const auto &prop : qAsConst(customMaterial->properties)) { + auto p = metaObject()->property(prop.pid); + if (Q_LIKELY(p.isValid())) + prop.value = p.read(this); + } + } + + if (m_dirtyAttributes & Dirty::TextureDirty) { + // TODO: + for (const auto &texture : qAsConst(m_textures)); + } + + return customMaterial; +} + +void QDemonCustomMaterial::onPropertyDirty() +{ + markDirty(Dirty::PropertyDirty); + update(); +} + +void QDemonCustomMaterial::onTextureDirty(QDemonCustomMaterialTexture *texture) +{ + Q_UNUSED(texture) + markDirty(Dirty::TextureDirty); + update(); +} + +void QDemonCustomMaterial::qmlAppendShader(QQmlListProperty<QDemonCustomMaterialShader> *list, QDemonCustomMaterialShader *shader) +{ + if (!shader) + return; + + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + that->m_shaders.push_back(shader); +} + +QDemonCustomMaterialShader *QDemonCustomMaterial::qmlShaderAt(QQmlListProperty<QDemonCustomMaterialShader> *list, int index) +{ + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + return that->m_shaders.at(index); +} + +int QDemonCustomMaterial::qmlShaderCount(QQmlListProperty<QDemonCustomMaterialShader> *list) +{ + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + return that->m_shaders.size(); +} + +void QDemonCustomMaterial::qmlAppendTexture(QQmlListProperty<QDemonCustomMaterialTexture> *textures, QDemonCustomMaterialTexture *texture) +{ + if (!texture) + return; + + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(textures->object); + if (texture->type == QDemonCustomMaterialTexture::TextureType::Displace) + that->setDisplacementMap(texture->image()); + else if (texture->type == QDemonCustomMaterialTexture::TextureType::Emissive2) + that->setEmissiveMap2(texture->image()); + else + that->setDynamicTextureMap(texture->image()); + that->m_textures.push_back(texture); + that->markDirty(Dirty::TextureDirty); +} + +QDemonCustomMaterialTexture *QDemonCustomMaterial::qmlTextureAt(QQmlListProperty<QDemonCustomMaterialTexture> *list, int index) +{ + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + return that->m_textures.at(index); +} + +int QDemonCustomMaterial::qmlTextureCount(QQmlListProperty<QDemonCustomMaterialTexture> *list) +{ + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + return that->m_textures.size(); +} + +void QDemonCustomMaterial::qmlAppendPass(QQmlListProperty<QDemonCustomMaterialRenderPass> *list, QDemonCustomMaterialRenderPass *pass) +{ + if (!pass) + return; + + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + that->m_passes.push_back(pass); +} + +QDemonCustomMaterialRenderPass *QDemonCustomMaterial::qmlPassAt(QQmlListProperty<QDemonCustomMaterialRenderPass> *list, int index) +{ + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + return that->m_passes.at(index); +} + +int QDemonCustomMaterial::qmlPassCount(QQmlListProperty<QDemonCustomMaterialRenderPass> *list) +{ + QDemonCustomMaterial *that = qobject_cast<QDemonCustomMaterial *>(list->object); + return that->m_textures.count(); +} + +void QDemonCustomMaterialRenderPass::qmlAppendCommand(QQmlListProperty<QDemonCustomMaterialRenderCommand> *list, QDemonCustomMaterialRenderCommand *command) +{ + if (!command) + return; + + QDemonCustomMaterialRenderPass *that = qobject_cast<QDemonCustomMaterialRenderPass *>(list->object); + that->m_commands.push_back(command); +} + +QDemonCustomMaterialRenderCommand *QDemonCustomMaterialRenderPass::qmlCommandAt(QQmlListProperty<QDemonCustomMaterialRenderCommand> *list, int index) +{ + QDemonCustomMaterialRenderPass *that = qobject_cast<QDemonCustomMaterialRenderPass *>(list->object); + return that->m_commands.at(index); +} + +int QDemonCustomMaterialRenderPass::qmlCommandCount(QQmlListProperty<QDemonCustomMaterialRenderCommand> *list) +{ + QDemonCustomMaterialRenderPass *that = qobject_cast<QDemonCustomMaterialRenderPass *>(list->object); + return that->m_commands.count(); +} + +QQmlListProperty<QDemonCustomMaterialRenderCommand> QDemonCustomMaterialRenderPass::commands() +{ + return QQmlListProperty<QDemonCustomMaterialRenderCommand>(this, + nullptr, + QDemonCustomMaterialRenderPass::qmlAppendCommand, + QDemonCustomMaterialRenderPass::qmlCommandCount, + QDemonCustomMaterialRenderPass::qmlCommandAt, + nullptr); } QT_END_NAMESPACE diff --git a/src/quick3d/qdemoncustommaterial.h b/src/quick3d/qdemoncustommaterial.h index ad409927cb26dbfc6a60251d1bed35070ec0c4b1..63f3f6aeb1ced759ee84f5be393e452f206e1d24 100644 --- a/src/quick3d/qdemoncustommaterial.h +++ b/src/quick3d/qdemoncustommaterial.h @@ -2,16 +2,300 @@ #define QDEMONCUSTOMMATERIAL_H #include <QtQuick3d/qdemonmaterial.h> +#include <QtCore/qvector.h> + +#include <QtDemonRender/qdemonrenderbasetypes.h> + +#include <QtDemonRuntimeRender/qdemonrenderdynamicobjectsystemcommands.h> QT_BEGIN_NAMESPACE + +class Q_QUICK3D_EXPORT QDemonCustomMaterialTexture : public QObject +{ + Q_OBJECT + Q_PROPERTY(QDemonImage * image READ image WRITE setImage) + Q_PROPERTY(QByteArray name MEMBER name) + Q_PROPERTY(TextureType type MEMBER type) + Q_PROPERTY(bool enabled MEMBER enabled) + +public: + enum class TextureType + { + Unknown = 0, + Diffuse, + Specular, + Environment, + Bump, + Normal, + Displace, + Emissive, + Emissive2, + Anisotropy, + Translucent, + LightmapIndirect, + LightmapRadiosity, + LightmapShadow + }; + Q_ENUM(TextureType) + + QDemonCustomMaterialTexture() = default; + virtual ~QDemonCustomMaterialTexture() = default; + QDemonImage *m_image; + QByteArray name; + TextureType type; + bool enabled = true; + QDemonImage *image() const + { + return m_image; + } + +public Q_SLOTS: + void setImage(QDemonImage * image) + { + if (m_image == image) + return; + + m_image = image; + Q_EMIT textureDirty(this); + } + +Q_SIGNALS: + void textureDirty(QDemonCustomMaterialTexture * texture); +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialRenderCommand : public QObject +{ + Q_OBJECT +public: + QDemonCustomMaterialRenderCommand() = default; + ~QDemonCustomMaterialRenderCommand() override = default; + virtual dynamic::QDemonCommand *getCommand() { Q_ASSERT(0); return nullptr; } +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialBufferInput : public QDemonCustomMaterialRenderCommand +{ + Q_OBJECT + Q_PROPERTY(QByteArray bufferName MEMBER bufferName) + Q_PROPERTY(QByteArray param MEMBER param) +public: + QDemonCustomMaterialBufferInput() = default; + ~QDemonCustomMaterialBufferInput() override = default; + dynamic::QDemonApplyBufferValue command { QByteArray(), QByteArray() }; + QByteArray &bufferName = command.m_bufferName; + QByteArray ¶m = command.m_paramName; + dynamic::QDemonCommand *getCommand() override { return &command; } +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialBufferBlit : public QDemonCustomMaterialRenderCommand +{ + Q_OBJECT + Q_PROPERTY(QByteArray source MEMBER source) + Q_PROPERTY(QByteArray destination MEMBER destination) +public: + QDemonCustomMaterialBufferBlit() = default; + ~QDemonCustomMaterialBufferBlit() override = default; + dynamic::QDemonApplyBlitFramebuffer command { QByteArray(), QByteArray() }; + QByteArray &source = command.m_sourceBufferName; + QByteArray &destination = command.m_destBufferName; + dynamic::QDemonCommand *getCommand() override { return &command; } +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialBlending : public QDemonCustomMaterialRenderCommand +{ + Q_OBJECT + Q_PROPERTY(SrcBlending srcBlending READ srcBlending WRITE setSrcBlending) + Q_PROPERTY(DestBlending destBlending READ destBlending WRITE setDestBlending) + +public: + enum class SrcBlending + { + Unknown = 0, + Zero, + One, + SrcColor, + OneMinusSrcColor, + DstColor, + OneMinusDstColor, + SrcAlpha, + OneMinusSrcAlpha, + DstAlpha, + OneMinusDstAlpha, + ConstantColor, + OneMinusConstantColor, + ConstantAlpha, + OneMinusConstantAlpha, + SrcAlphaSaturate + }; + Q_ENUM(SrcBlending) + + enum class DestBlending + { + Unknown = 0, + Zero, + One, + SrcColor, + OneMinusSrcColor, + DstColor, + OneMinusDstColor, + SrcAlpha, + OneMinusSrcAlpha, + DstAlpha, + OneMinusDstAlpha, + ConstantColor, + OneMinusConstantColor, + ConstantAlpha, + OneMinusConstantAlpha + }; + Q_ENUM(DestBlending) + + QDemonCustomMaterialBlending() = default; + ~QDemonCustomMaterialBlending() override = default; + dynamic::QDemonApplyBlending command { QDemonRenderSrcBlendFunc::Unknown, QDemonRenderDstBlendFunc::Unknown }; + DestBlending destBlending() const + { + return DestBlending(command.m_dstBlendFunc); + } + SrcBlending srcBlending() const + { + return SrcBlending(command.m_srcBlendFunc); + } + + dynamic::QDemonCommand *getCommand() override { return &command; } + +public Q_SLOTS: + void setDestBlending(DestBlending destBlending) + { + command.m_dstBlendFunc = QDemonRenderDstBlendFunc(destBlending); + } + void setSrcBlending(SrcBlending srcBlending) + { + command.m_srcBlendFunc= QDemonRenderSrcBlendFunc(srcBlending); + } +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialRenderState : public QDemonCustomMaterialRenderCommand +{ + Q_OBJECT + Q_PROPERTY(RenderState renderState READ renderState WRITE setRenderState) + Q_PROPERTY(bool enabled MEMBER enabled) + +public: + enum class RenderState + { + Unknown = 0, + Blend, + CullFace, + DepthTest, + StencilTest, + ScissorTest, + DepthWrite, + Multisample + }; + Q_ENUM(RenderState) + + QDemonCustomMaterialRenderState() = default; + ~QDemonCustomMaterialRenderState() override = default; + dynamic::QDemonApplyRenderState command { QDemonRenderState::Unknown, false }; + bool &enabled = command.m_enabled; + RenderState renderState() const + { + return RenderState(command.m_renderState); + } + + dynamic::QDemonCommand *getCommand() override { return &command; } +public Q_SLOTS: + void setRenderState(RenderState renderState) + { + command.m_renderState = QDemonRenderState(renderState); + } +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialRenderPass : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty<QDemonCustomMaterialRenderCommand> commands READ commands) +public: + QDemonCustomMaterialRenderPass() = default; + ~QDemonCustomMaterialRenderPass() override = default; + + static void qmlAppendCommand(QQmlListProperty<QDemonCustomMaterialRenderCommand> *list, QDemonCustomMaterialRenderCommand *command); + static QDemonCustomMaterialRenderCommand *qmlCommandAt(QQmlListProperty<QDemonCustomMaterialRenderCommand> *list, int index); + static int qmlCommandCount(QQmlListProperty<QDemonCustomMaterialRenderCommand> *list); + + QQmlListProperty<QDemonCustomMaterialRenderCommand> commands(); + QVector<QDemonCustomMaterialRenderCommand *> m_commands; +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialShaderInfo : public QObject +{ + Q_OBJECT + Q_PROPERTY(QByteArray version MEMBER version) + Q_PROPERTY(QByteArray type MEMBER type) + Q_PROPERTY(qint32 shaderKey MEMBER shaderKey) + Q_PROPERTY(qint32 layers MEMBER layers) +public: + QDemonCustomMaterialShaderInfo() = default; + ~QDemonCustomMaterialShaderInfo() override = default; + QByteArray version; + QByteArray type; // I.e., GLSL + QByteArray shaderPrefix = QByteArrayLiteral("#include \"customMaterial.glsllib\"\n"); + + enum class MaterialShaderKeyValues + { + Diffuse = 1 << 0, + Specular = 1 << 1, + Glossy = 1 << 2, + Cutout = 1 << 3, + Refraction = 1 << 4, + Transparent = 1 << 5, + Displace = 1 << 6, + Volumetric = 1 << 7, + Transmissive = 1 << 8, + }; + Q_ENUM(MaterialShaderKeyValues) + Q_DECLARE_FLAGS(MaterialShaderKeyFlags, MaterialShaderKeyValues) + + qint32 shaderKey {0}; + qint32 layers {0}; + bool isValid() const { return !(version.isEmpty() && type.isEmpty() && shaderPrefix.isEmpty()); } +}; + +class Q_QUICK3D_EXPORT QDemonCustomMaterialShader : public QObject +{ + Q_OBJECT + Q_PROPERTY(QByteArray shader MEMBER shader) + Q_PROPERTY(Stage stage MEMBER stage) +public: + QDemonCustomMaterialShader() = default; + virtual ~QDemonCustomMaterialShader() = default; + enum class Stage : quint8 + { + Shared, + Vertex, + Fragment, + Geometry + }; + Q_ENUM(Stage) + + QByteArray shader; + Stage stage; +}; + class Q_QUICK3D_EXPORT QDemonCustomMaterial : public QDemonMaterial { Q_OBJECT - Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) // NOT NEEDED Q_PROPERTY(bool hasTransparency READ hasTransparency WRITE setHasTransparency NOTIFY hasTransparencyChanged) Q_PROPERTY(bool hasRefraction READ hasRefraction WRITE setHasRefraction NOTIFY hasRefractionChanged) Q_PROPERTY(bool hasVolumetricDF READ hasVolumetricDF WRITE setHasVolumetricDF NOTIFY hasVolumetricDFChanged) + Q_PROPERTY(bool alwaysDirty READ alwaysDirty WRITE setAlwaysDirty NOTIFY alwaysDirtyChanged) + + Q_PROPERTY(QDemonCustomMaterialShaderInfo *shaderInfo READ shaderInfo WRITE setShaderInfo) + Q_PROPERTY(QQmlListProperty<QDemonCustomMaterialShader> shaders READ shaders) + Q_PROPERTY(QQmlListProperty<QDemonCustomMaterialTexture> textures READ textures) + Q_PROPERTY(QQmlListProperty<QDemonCustomMaterialRenderPass> passes READ passes) + public: QDemonCustomMaterial(); @@ -25,12 +309,23 @@ public: QString source() const; + QDemonCustomMaterialShaderInfo *shaderInfo() const; + + QQmlListProperty<QDemonCustomMaterialShader> shaders(); + QQmlListProperty<QDemonCustomMaterialTexture> textures(); + QQmlListProperty<QDemonCustomMaterialRenderPass> passes(); + + bool alwaysDirty() const; + public Q_SLOTS: void setHasTransparency(bool hasTransparency); void setHasRefraction(bool hasRefraction); void setHasVolumetricDF(bool hasVolumetricDF); void setSource(QString source); + void setShaderInfo(QDemonCustomMaterialShaderInfo *shaderInfo); + + void setAlwaysDirty(bool alwaysDirty); Q_SIGNALS: void hasTransparencyChanged(bool hasTransparency); @@ -39,14 +334,54 @@ Q_SIGNALS: void sourceChanged(QString source); + void alwaysDirtyChanged(bool alwaysDirty); + protected: QDemonRenderGraphObject *updateSpatialNode(QDemonRenderGraphObject *node) override; +private Q_SLOTS: + void onPropertyDirty(); + void onTextureDirty(QDemonCustomMaterialTexture *texture); + private: + enum Dirty { + TextureDirty = 0x1, + PropertyDirty = 0x2 + }; + + // Shader + static void qmlAppendShader(QQmlListProperty<QDemonCustomMaterialShader> *list, QDemonCustomMaterialShader *shader); + static QDemonCustomMaterialShader *qmlShaderAt(QQmlListProperty<QDemonCustomMaterialShader> *list, int index); + static int qmlShaderCount(QQmlListProperty<QDemonCustomMaterialShader> *list); + + // Texture + static void qmlAppendTexture(QQmlListProperty<QDemonCustomMaterialTexture> *textures, QDemonCustomMaterialTexture *texture); + static QDemonCustomMaterialTexture *qmlTextureAt(QQmlListProperty<QDemonCustomMaterialTexture> *list, int index); + static int qmlTextureCount(QQmlListProperty<QDemonCustomMaterialTexture> *list); + + // Passes + static void qmlAppendPass(QQmlListProperty<QDemonCustomMaterialRenderPass> *list, QDemonCustomMaterialRenderPass *pass); + static QDemonCustomMaterialRenderPass *qmlPassAt(QQmlListProperty<QDemonCustomMaterialRenderPass> *list, int index); + static int qmlPassCount(QQmlListProperty<QDemonCustomMaterialRenderPass> *list); + + void markDirty(QDemonCustomMaterial::Dirty type) + { + if (!(m_dirtyAttributes & quint32(type))) { + m_dirtyAttributes |= quint32(type); + update(); + } + } + + quint32 m_dirtyAttributes = 0xffffffff; bool m_hasTransparency; bool m_hasRefraction; bool m_hasVolumetricDF; QString m_source; + QDemonCustomMaterialShaderInfo *m_shaderInfo; + QVector<QDemonCustomMaterialShader *> m_shaders; + QVector<QDemonCustomMaterialTexture *> m_textures; + QVector<QDemonCustomMaterialRenderPass *> m_passes; + bool m_alwaysDirty = false; }; QT_END_NAMESPACE diff --git a/src/quick3d/qdemonmaterial.cpp b/src/quick3d/qdemonmaterial.cpp index 17f7cc48935bfb709896de95794d113ee0175843..65d7125685c562550e443506a186a94084f77cb5 100644 --- a/src/quick3d/qdemonmaterial.cpp +++ b/src/quick3d/qdemonmaterial.cpp @@ -253,6 +253,29 @@ void QDemonMaterial::itemChange(QDemonObject::ItemChange change, const QDemonObj updateSceneRenderer(value.sceneRenderer); } +void QDemonMaterial::setDynamicTextureMap(QDemonImage *textureMap) +{ + if (!textureMap) + return; + + auto it = m_dynamicTextureMaps.begin(); + const auto end = m_dynamicTextureMaps.end(); + for (; it != end; ++it) { + if (*it == textureMap) + break; + } + + if (it != end) + return; + + updateProperyListener(textureMap, nullptr, sceneRenderer(), m_connections, [this](QDemonObject *n) { + setDynamicTextureMap(qobject_cast<QDemonImage *>(n)); + }); + + m_dynamicTextureMaps.push_back(textureMap); + update(); +} + void QDemonMaterial::updateSceneRenderer(QDemonSceneManager *window) { if (window) { @@ -274,6 +297,8 @@ void QDemonMaterial::updateSceneRenderer(QDemonSceneManager *window) if (m_displacementMap) { QDemonObjectPrivate::get(m_displacementMap)->refSceneRenderer(window); } + for (auto it : m_dynamicTextureMaps) + QDemonObjectPrivate::get(it)->refSceneRenderer(window); } else { if (m_lightmapIndirect) { QDemonObjectPrivate::get(m_lightmapIndirect)->derefSceneRenderer(); @@ -293,6 +318,8 @@ void QDemonMaterial::updateSceneRenderer(QDemonSceneManager *window) if (m_displacementMap) { QDemonObjectPrivate::get(m_displacementMap)->derefSceneRenderer(); } + for (auto it : m_dynamicTextureMaps) + QDemonObjectPrivate::get(it)->derefSceneRenderer(); } } diff --git a/src/quick3d/qdemonmaterial.h b/src/quick3d/qdemonmaterial.h index f9ce35a07464189ab229b86b1692827e49aa2891..b3d63c2051f4e21699f0ba0273489590bbc57509 100644 --- a/src/quick3d/qdemonmaterial.h +++ b/src/quick3d/qdemonmaterial.h @@ -4,6 +4,8 @@ #include <QtQuick3d/qdemonobject.h> #include <QtQuick3d/qdemonimage.h> +#include <QtCore/qvector.h> + QT_BEGIN_NAMESPACE class QDemonSceneManager; @@ -61,6 +63,8 @@ Q_SIGNALS: protected: QDemonRenderGraphObject *updateSpatialNode(QDemonRenderGraphObject *node) override; void itemChange(ItemChange, const ItemChangeData &) override; + + void setDynamicTextureMap(QDemonImage *textureMap); private: void updateSceneRenderer(QDemonSceneManager *sceneRenderer); QDemonImage *m_lightmapIndirect = nullptr; @@ -74,6 +78,7 @@ private: float m_displacementAmount = 0.0f; QHash<QObject*, QMetaObject::Connection> m_connections; + QVector<QDemonImage *> m_dynamicTextureMaps; }; QT_END_NAMESPACE diff --git a/src/quick3d/qdemonobject_p.h b/src/quick3d/qdemonobject_p.h index a9750201bd0b749fcb88828899dfb7e51254b79b..dcca865746e9744b5b24d657ed4da0fdf1feba39 100644 --- a/src/quick3d/qdemonobject_p.h +++ b/src/quick3d/qdemonobject_p.h @@ -176,8 +176,8 @@ public: QDemonSceneManager *sceneManager; int windowRefCount; -// inline QDemonRenderContextInterface *sceneGraphContext() const; -// inline QDemonRenderContext *sceneGraphRenderContext() const; +// QDemonRenderContextInterface *sceneGraphContext() const; +// QDemonRenderContext *sceneGraphRenderContext() const; QDemonObject *parentItem; diff --git a/src/quick3d/qdemonscenerenderer.cpp b/src/quick3d/qdemonscenerenderer.cpp index f6dcdd45b14c250459aa4f3d3ff92acbbea9bc03..8b48a7fc3a9906d431870eb4c9da7ce79c9f9f36 100644 --- a/src/quick3d/qdemonscenerenderer.cpp +++ b/src/quick3d/qdemonscenerenderer.cpp @@ -240,7 +240,7 @@ QDemonSceneRenderer::QDemonSceneRenderer(QWindow *window) if (m_renderContext.isNull()) m_renderContext = QDemonRenderContext::createGl(m_openGLContext->format()); if (m_sgContext.isNull()) - m_sgContext = new QDemonRenderContextInterface(m_renderContext, QString::fromLatin1("./")); + m_sgContext = QDemonRenderContextInterface::getRenderContextInterface(m_renderContext, QString::fromLatin1("./"), quintptr(window)); m_openGLContext->doneCurrent(); oldContext->makeCurrent(window); } diff --git a/src/quick3d/qdemonscenerenderer.h b/src/quick3d/qdemonscenerenderer.h index 1eea51d93c0850b9f2fca992e10facd9b8a64ee4..ec0f687bf4faf13caaf2a7c3db0b652fb8d3e544 100644 --- a/src/quick3d/qdemonscenerenderer.h +++ b/src/quick3d/qdemonscenerenderer.h @@ -44,7 +44,7 @@ private: void removeNodeFromLayer(QDemonRenderNode *node); QDemonSceneManager *m_sceneManager = nullptr; QDemonRenderLayer *m_layer = nullptr; - QDemonRef<QDemonRenderContextInterface> m_sgContext; + QDemonRenderContextInterface::QDemonRenderContextInterfacePtr m_sgContext; QDemonRef<QDemonRenderContext> m_renderContext; QSize m_surfaceSize; void *data = nullptr; diff --git a/src/render/qdemonrenderbasetypes.h b/src/render/qdemonrenderbasetypes.h index 6208bb70dc52dbad3fd2a07d0857ac35f0ad7b59..3a18778308ce7e49f131f91b380f23d9e126a444 100644 --- a/src/render/qdemonrenderbasetypes.h +++ b/src/render/qdemonrenderbasetypes.h @@ -1690,6 +1690,17 @@ typedef QDemonRenderGenericVec2<qint32> qint32_2; typedef QDemonRenderGenericVec3<qint32> qint32_3; typedef QDemonRenderGenericVec4<qint32> qint32_4; +Q_DECLARE_METATYPE(bool_2) +Q_DECLARE_METATYPE(bool_3) +Q_DECLARE_METATYPE(bool_4) +Q_DECLARE_METATYPE(quint32_2) +Q_DECLARE_METATYPE(quint32_3) +Q_DECLARE_METATYPE(quint32_4) +Q_DECLARE_METATYPE(qint32_2) +Q_DECLARE_METATYPE(qint32_3) +Q_DECLARE_METATYPE(qint32_4) + + enum class QDemonRenderShaderDataType : quint32 { Unknown = 0, diff --git a/src/runtimerender/graphobjects/graphobjects.pri b/src/runtimerender/graphobjects/graphobjects.pri index 9c13f094556324b1575649b3b9d18ad75fcce8a6..1e1c5e8afe711ff6ea77e93714f39995d3179a3a 100644 --- a/src/runtimerender/graphobjects/graphobjects.pri +++ b/src/runtimerender/graphobjects/graphobjects.pri @@ -2,7 +2,6 @@ HEADERS += \ $$PWD/qdemonrendercamera.h \ $$PWD/qdemonrendercustommaterial.h \ $$PWD/qdemonrenderdefaultmaterial.h \ - $$PWD/qdemonrenderdynamicobject.h \ $$PWD/qdemonrendereffect.h \ $$PWD/qdemonrendergraphobject.h \ $$PWD/qdemonrenderimage.h \ @@ -19,7 +18,6 @@ HEADERS += \ SOURCES += \ $$PWD/qdemonrendercamera.cpp \ $$PWD/qdemonrenderdefaultmaterial.cpp \ - $$PWD/qdemonrenderdynamicobject.cpp \ $$PWD/qdemonrendereffect.cpp \ $$PWD/qdemonrenderimage.cpp \ $$PWD/qdemonrenderlayer.cpp \ diff --git a/src/runtimerender/graphobjects/qdemonrendercustommaterial.h b/src/runtimerender/graphobjects/qdemonrendercustommaterial.h index 7314b5554e4add4039754d720b25b9922abdf969..8185490cb9744cbb9efeb69aded2cbe1e7cc1101 100644 --- a/src/runtimerender/graphobjects/qdemonrendercustommaterial.h +++ b/src/runtimerender/graphobjects/qdemonrendercustommaterial.h @@ -30,21 +30,115 @@ #ifndef QDEMON_RENDER_CUSTOM_MATERIAL_H #define QDEMON_RENDER_CUSTOM_MATERIAL_H -#include <QtDemonRuntimeRender/qdemonrenderdynamicobject.h> #include <QtDemonRuntimeRender/qdemonrenderimage.h> #include <QtDemonRuntimeRender/qdemonrenderlightmaps.h> +#include <QtCore/qurl.h> +#include <QtCore/qvector.h> +#include <QtDemonRuntimeRender/qdemonrenderdynamicobjectsystemcommands.h> + QT_BEGIN_NAMESPACE -struct Q_DEMONRUNTIMERENDER_EXPORT QDemonRenderCustomMaterial : public QDemonRenderDynamicGraphObject +struct Q_DEMONRUNTIMERENDER_EXPORT QDemonRenderCustomMaterial : public QDemonRenderGraphObject { -private: - // These objects are only created via the dynamic object system. - QDemonRenderCustomMaterial(const QDemonRenderCustomMaterial &); - QDemonRenderCustomMaterial &operator=(const QDemonRenderCustomMaterial &); - QDemonRenderCustomMaterial(); + QDemonRenderCustomMaterial() : QDemonRenderGraphObject(Type::CustomMaterial) {} + + struct TextureProperty + { + QDemonRenderImage *texImage = nullptr; + QByteArray name; + QDemonRenderShaderDataType shaderDataType; + // TODO: Note needed? + QDemonRenderTextureMagnifyingOp magFilterType = QDemonRenderTextureMagnifyingOp::Linear; + QDemonRenderTextureMinifyingOp minFilterType = QDemonRenderTextureMinifyingOp::Linear; + QDemonRenderTextureCoordOp clampType = QDemonRenderTextureCoordOp::ClampToEdge; + QDemonRenderTextureTypeValue usageType; + }; + + QVector<TextureProperty> textureProperties; + + struct Property + { + QByteArray name; + mutable QVariant value; + QDemonRenderShaderDataType shaderDataType; + int pid = -1; + }; + + QVector<Property> properties; + + struct ShaderInfo + { + QByteArray version; + QByteArray type; // I.e., GLSL + QByteArray shaderPrefix; + }; + + ShaderInfo shaderInfo; + + struct Shader + { + enum class Stage : quint8 + { + Shared, + Vertex, + Fragment + }; + + QString code; + Stage stage; + }; + + QVector<Shader> shaders; + + struct Pass + { + struct BufferInput + { + QString bufferName; + QString shaderParam; + // dynamic::QDemonApplyBufferValue(bufferName, shaderParam) + }; + + struct BufferBlit + { + QString source; + QString dest; + // dynamic::QDemonApplyBlitFramebuffer(source, dest) + }; + + struct Blending + { + QDemonRenderSrcBlendFunc source = QDemonRenderSrcBlendFunc::One; + QDemonRenderDstBlendFunc dest = QDemonRenderDstBlendFunc::One; + // hasBlending = true; when used + // dynamic::QDemonApplyBlending(source, dest) + }; + + struct RenderState + { + QDemonRenderState renderState = QDemonRenderState::Unknown; + bool enabled; + // dynamic::QDemonApplyRenderState(renderState, enabled) + }; + + QString shaderName; + QString input; + QString output; + QDemonRenderTextureFormat::Format outputFormat; + bool needsClear; + + Pass() + : input(QLatin1String("[source]")) + , output(QLatin1String("[dest]")) + , outputFormat(QDemonRenderTextureFormat::RGBA8) + , needsClear(false) + {} + }; + + QVector<Pass> passes; + QVector<dynamic::QDemonCommand *> commands; -public: // IMPORTANT: These flags matches the key produced by a MDL export file enum class MaterialShaderKeyValues { @@ -60,41 +154,29 @@ public: }; Q_DECLARE_FLAGS(MaterialShaderKeyFlags, MaterialShaderKeyValues) - const char *imagePath = nullptr; + using Flag = QDemonRenderNode::Flag; + Q_DECLARE_FLAGS(Flags, Flag) + + const char *className = nullptr; // lightmap section QDemonRenderLightmaps m_lightmaps; // material section - bool m_hasTransparency; - bool m_hasRefraction; - bool m_hasVolumetricDF; - QDemonRenderImage *m_iblProbe; - QDemonRenderImage *m_emissiveMap2; - QDemonRenderImage *m_displacementMap; - float m_displaceAmount; ///< depends on the object size + bool m_hasTransparency = false; + bool m_hasRefraction = false; + bool m_hasVolumetricDF = false; + QDemonRenderImage *m_iblProbe = nullptr; + QDemonRenderImage *m_emissiveMap2 = nullptr; + QDemonRenderImage *m_displacementMap = nullptr; + float m_displaceAmount = 0.0f; ///< depends on the object size - QDemonRenderGraphObject *m_nextSibling; + QDemonRenderGraphObject *m_nextSibling = nullptr; MaterialShaderKeyFlags m_shaderKeyValues; ///< input from MDL files - quint32 m_layerCount; ///< input from MDL files + quint32 m_layerCount = 0; ///< input from MDL files - void initialize(quint32 inKey, quint32 inLayerCount) - { - m_lightmaps.m_lightmapIndirect = nullptr; - m_lightmaps.m_lightmapRadiosity = nullptr; - m_lightmaps.m_lightmapShadow = nullptr; - m_hasTransparency = false; - m_hasRefraction = false; - m_hasVolumetricDF = false; - m_nextSibling = nullptr; - m_dirtyFlagWithInFrame = flags.testFlag(Flag::Dirty); - m_iblProbe = nullptr; - m_emissiveMap2 = nullptr; - m_displacementMap = nullptr; - m_displaceAmount = 0.0; - m_shaderKeyValues = static_cast<MaterialShaderKeyFlags>(inKey); - m_layerCount = inLayerCount; - } + Flags flags; + bool m_alwaysDirty = false; bool isDielectric() const { return m_shaderKeyValues & MaterialShaderKeyValues::diffuse; } bool isSpecularEnabled() const { return m_shaderKeyValues & MaterialShaderKeyValues::specular; } @@ -105,7 +187,7 @@ public: // Dirty bool m_dirtyFlagWithInFrame; - bool isDirty() const { return flags.testFlag(Flag::Dirty) || m_dirtyFlagWithInFrame; } + bool isDirty() const { return flags.testFlag(Flag::Dirty) || m_dirtyFlagWithInFrame || m_alwaysDirty; } void updateDirtyForFrame() { m_dirtyFlagWithInFrame = flags.testFlag(Flag::Dirty); diff --git a/src/runtimerender/graphobjects/qdemonrenderdynamicobject.cpp b/src/runtimerender/graphobjects/qdemonrenderdynamicobject.cpp deleted file mode 100644 index 27ed46ccb5da89a1a9c30210fed9feadcb339a3d..0000000000000000000000000000000000000000 --- a/src/runtimerender/graphobjects/qdemonrenderdynamicobject.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008-2012 NVIDIA Corporation. -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt 3D Studio. -** -** $QT_BEGIN_LICENSE:GPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 or (at your option) any later version -** approved by the KDE Free Qt Foundation. The licenses are as published by -** the Free Software Foundation and appearing in the file LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdemonrenderdynamicobject.h" - -#include <QtDemonRuntimeRender/qdemonrenderdynamicobjectsystem.h> - -#include <QtCore/qdir.h> - -QT_BEGIN_NAMESPACE - -QDemonRenderDynamicGraphObject::QDemonRenderDynamicGraphObject(Type inType, const QString &inObjName, quint32 inDSByteSize, quint32 thisObjSize) - : QDemonRenderGraphObject(inType), className(inObjName), dataSectionByteSize(inDSByteSize), thisObjectSize(thisObjSize) -{ -} - -template<typename TDataType> -void QDemonRenderDynamicGraphObject::setPropertyValueT(const dynamic::QDemonPropertyDefinition &inDefinition, const TDataType &inValue) -{ - if (sizeof(inValue) != inDefinition.byteSize) { - Q_ASSERT(false); - return; - } - ::memcpy(getDataSectionBegin() + inDefinition.offset, &inValue, sizeof(inValue)); -} - -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, bool inValue) -{ - setPropertyValueT(inDefinition, inValue); -} - -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, float inValue) -{ - setPropertyValueT(inDefinition, inValue); -} -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, float inValue, quint32 inOffset) -{ - if (sizeof(float) > (inDefinition.byteSize - inOffset)) { - Q_ASSERT(false); - return; - } - ::memcpy(getDataSectionBegin() + inDefinition.offset + inOffset, &inValue, sizeof(inValue)); -} -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QVector2D &inValue) -{ - setPropertyValueT(inDefinition, inValue); -} -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QVector3D &inValue) -{ - setPropertyValueT(inDefinition, inValue); -} -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QVector4D &inValue) -{ - setPropertyValueT(inDefinition, inValue); -} -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, qint32 inValue) -{ - setPropertyValueT(inDefinition, inValue); -} -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QString &inValue) -{ - Q_ASSERT(inDefinition.dataType == QDemonRenderShaderDataType::Texture2D); - setPropertyValueT(inDefinition, inValue); -} -template<typename TStrType> -void QDemonRenderDynamicGraphObject::setStrPropertyValueT(dynamic::QDemonPropertyDefinition &inDefinition, - const char *inValue, - const char *inProjectDir, - TStrType &ioWorkspace) -{ - if (inValue == nullptr) - inValue = ""; - if (inDefinition.dataType == QDemonRenderShaderDataType::Integer) { - // TODO: Can the enum values be anything but 8bit chars? - QDemonDataView<QString> theEnumValues = inDefinition.enumValueNames; - for (int idx = 0, end = theEnumValues.size(); idx < end; ++idx) { - if (theEnumValues[idx].compare(QString::fromLocal8Bit(inValue)) == 0) { - setPropertyValueT(inDefinition, idx); - break; - } - } - } else if (inDefinition.dataType == QDemonRenderShaderDataType::Texture2D) { - if (inProjectDir == nullptr) - inProjectDir = ""; - - const bool RequiresCombineBaseAndRelative = inValue && (::strncmp(inValue, ".", 1) == 0); - if (RequiresCombineBaseAndRelative) { - const QString absolute = QDir(QString::fromLocal8Bit(inProjectDir)).filePath(QString::fromLocal8Bit(inValue)); - ioWorkspace = absolute; - setPropertyValueT(inDefinition, ioWorkspace); - // We also adjust the image path in the definition - // I could not find a better place - QByteArray *data = new QByteArray(ioWorkspace.toLatin1()); - inDefinition.imagePath = data->constData(); //ioWorkspace.toLatin1().constData(); // TODO: Life time - } else { - setPropertyValueT(inDefinition, inValue); - } - } else if (inDefinition.dataType == QDemonRenderShaderDataType::Image2D) { - setPropertyValueT(inDefinition, inValue); - } else if (inDefinition.dataType == QDemonRenderShaderDataType::DataBuffer) { - setPropertyValueT(inDefinition, inValue); - } else { - Q_ASSERT(false); - } -} - -void QDemonRenderDynamicGraphObject::setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, - const char *inValue, - const char *inProjectDir, - QString &ioWorkspace) -{ - setStrPropertyValueT(const_cast<dynamic::QDemonPropertyDefinition &>(inDefinition), inValue, inProjectDir, ioWorkspace); -} - -// void QDemonDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, -// const char *inValue, const char *inProjectDir, -// QString &ioWorkspace) -//{ -// SetStrPropertyValueT(const_cast<dynamic::SPropertyDefinition &>(inDefinition), inValue, -// inProjectDir, ioWorkspace); -//} - -QT_END_NAMESPACE diff --git a/src/runtimerender/graphobjects/qdemonrenderdynamicobject.h b/src/runtimerender/graphobjects/qdemonrenderdynamicobject.h deleted file mode 100644 index c8fa062f04a7836c57834b2aabb0af3e302c59b7..0000000000000000000000000000000000000000 --- a/src/runtimerender/graphobjects/qdemonrenderdynamicobject.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008-2012 NVIDIA Corporation. -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt 3D Studio. -** -** $QT_BEGIN_LICENSE:GPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 or (at your option) any later version -** approved by the KDE Free Qt Foundation. The licenses are as published by -** the Free Software Foundation and appearing in the file LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QDEMON_RENDER_DYNAMIC_OBJECT_H -#define QDEMON_RENDER_DYNAMIC_OBJECT_H - -#include <QtDemonRuntimeRender/qdemonrendergraphobject.h> -#include <QtDemonRuntimeRender/qdemonrendernode.h> - -#include <QtCore/QString> - -QT_BEGIN_NAMESPACE - -namespace dynamic { -struct QDemonPropertyDefinition; -} - -// Dynamic objects are objects that have variable number of properties during runtime. -struct Q_DEMONRUNTIMERENDER_EXPORT QDemonRenderDynamicGraphObject : public QDemonRenderGraphObject -{ - using Flag = QDemonRenderNode::Flag; - Q_DECLARE_FLAGS(Flags, Flag) - - QString className; - Flags flags; - quint32 dataSectionByteSize; - quint32 thisObjectSize; - - QDemonRenderDynamicGraphObject(Type inType, const QString &inClassName, quint32 inDSByteSize, quint32 thisObjSize); - - quint8 *getDataSectionBegin() - { - quint8 *thisObjectStart = reinterpret_cast<quint8 *>(this); - quint8 *retval = thisObjectStart + thisObjectSize; - Q_ASSERT((reinterpret_cast<size_t>(retval) % 4 == 0)); - return retval; - } - - const quint8 *getDataSectionBegin() const { return const_cast<QDemonRenderDynamicGraphObject *>(this)->getDataSectionBegin(); } - - quint8 *getDataSectionEnd() { return getDataSectionBegin() + dataSectionByteSize; } - - template<typename TDataType> - void setPropertyValueT(const dynamic::QDemonPropertyDefinition &inDefinition, const TDataType &inType); - template<typename TStrType> - void setStrPropertyValueT(dynamic::QDemonPropertyDefinition &inDefinition, const char *inValue, const char *inProjectDir, TStrType &ioWorkspace); - - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, bool inValue); - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, float inValue); - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, float inValue, quint32 inOffset); - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QVector2D &inValue); - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QVector3D &inValue); - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QVector4D &inValue); - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, qint32 inValue); - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const QString &inValue); - - void setPropertyValue(const dynamic::QDemonPropertyDefinition &inDefinition, const char *inValue, const char *inProjectDir, QString &ioWorkspace); -}; - -QT_END_NAMESPACE -#endif diff --git a/src/runtimerender/graphobjects/qdemonrendereffect.h b/src/runtimerender/graphobjects/qdemonrendereffect.h index 8a8f2fee84f17efa1a5dc71da5c797dd31bac28c..69269cddff1bd3d0aedd3b2ca86053167650e4c3 100644 --- a/src/runtimerender/graphobjects/qdemonrendereffect.h +++ b/src/runtimerender/graphobjects/qdemonrendereffect.h @@ -32,7 +32,6 @@ #include <QtDemonRuntimeRender/qdemonrendergraphobject.h> #include <QtDemonRuntimeRender/qdemonrendernode.h> -#include <QtDemonRuntimeRender/qdemonrenderdynamicobject.h> QT_BEGIN_NAMESPACE struct QDemonRenderLayer; @@ -43,22 +42,17 @@ class QDemonEffectSystemInterface; // them and they have completely variable properties. // see IEffectManager in order to create these effects. // The data for the effect immediately follows the effect -struct Q_DEMONRUNTIMERENDER_EXPORT QDemonRenderEffect : public QDemonRenderDynamicGraphObject +struct Q_DEMONRUNTIMERENDER_EXPORT QDemonRenderEffect : public QDemonRenderGraphObject { -private: - // These objects are only created via the dynamic object system. - QDemonRenderEffect(const QDemonRenderEffect &) = delete; - QDemonRenderEffect &operator=(const QDemonRenderEffect &) = delete; - QDemonRenderEffect() = delete; + QDemonRenderEffect() : QDemonRenderGraphObject(Type::Effect) {} ~QDemonRenderEffect(); -public: QDemonRenderLayer *m_layer; QDemonRenderEffect *m_nextEffect; // Opaque pointer to context type implemented by the effect system. // May be null in which case the effect system will generate a new context // the first time it needs to render this effect. - QDemonRef<QDemonEffectContext> m_context; + QDemonEffectContext *m_context = nullptr; void initialize(); @@ -67,6 +61,12 @@ public: void setActive(bool inActive, QDemonEffectSystemInterface &inSystem); void reset(QDemonEffectSystemInterface &inSystem); + + using Flag = QDemonRenderNode::Flag; + Q_DECLARE_FLAGS(Flags, Flag) + + Flags flags; + const char *className = nullptr; }; QT_END_NAMESPACE diff --git a/src/runtimerender/qdemonrendercontextcore.cpp b/src/runtimerender/qdemonrendercontextcore.cpp index d4910eb3f4c9a8ab1f0163bd6e04ad4fb934f4cb..ef091fe8b2e2208225412c1a254762fa73ba39b9 100644 --- a/src/runtimerender/qdemonrendercontextcore.cpp +++ b/src/runtimerender/qdemonrendercontextcore.cpp @@ -136,6 +136,54 @@ QDemonRenderContextInterface::QDemonRenderContextInterface(const QDemonRef<QDemo #endif } +Q_GLOBAL_STATIC(QVector<QDemonRenderContextInterface::QDemonRenderContextInterfacePtr>, g_renderContexts) + +void QDemonRenderContextInterface::releaseRenderContextInterface(quintptr wid) +{ + auto it = g_renderContexts->cbegin(); + const auto end = g_renderContexts->cend(); + for (; it != end; ++it) { + if (it->m_wid == wid) + break; + } + + if (it != end) + g_renderContexts->remove(int(end - it)); +} + +QDemonRenderContextInterface::QDemonRenderContextInterfacePtr QDemonRenderContextInterface::getRenderContextInterface(const QDemonRef<QDemonRenderContext> &ctx, const QString &inApplicationDirectory, quintptr wid) +{ + auto it = g_renderContexts->cbegin(); + const auto end = g_renderContexts->cend(); + for (; it != end; ++it) { + if (it->m_wid == wid) + break; + } + + if (it != end) + return *it; + + QDemonRenderContextInterfacePtr ptr { new QDemonRenderContextInterface(ctx, inApplicationDirectory), wid }; + g_renderContexts->push_back(ptr); + + return ptr; +} + +QDemonRenderContextInterface::QDemonRenderContextInterfacePtr QDemonRenderContextInterface::getRenderContextInterface(quintptr wid) +{ + auto it = g_renderContexts->cbegin(); + const auto end = g_renderContexts->cend(); + for (; it != end; ++it) { + if (it->m_wid == wid) + break; + } + + if (it != end) + return *it; + + return QDemonRenderContextInterfacePtr(); +} + QDemonRef<QDemonRendererInterface> QDemonRenderContextInterface::renderer() { return m_renderer; } QDemonRef<QDemonBufferManager> QDemonRenderContextInterface::bufferManager() { return m_bufferManager; } diff --git a/src/runtimerender/qdemonrendercontextcore.h b/src/runtimerender/qdemonrendercontextcore.h index fee8f4224862edbc0a8400c360cb5d90d6c08df6..805f24efbe36ab99ff229f1ee688df63786babe4 100644 --- a/src/runtimerender/qdemonrendercontextcore.h +++ b/src/runtimerender/qdemonrendercontextcore.h @@ -140,9 +140,28 @@ private: QRect presentationViewport(const QRect &inViewerViewport, ScaleModes inScaleToFit, const QSize &inPresDimensions) const; void setupRenderTarget(); void teardownRenderTarget(); + QDemonRenderContextInterface(const QDemonRef<QDemonRenderContext> &ctx, const QString &inApplicationDirectory); + + static void releaseRenderContextInterface(quintptr wid); public: - QDemonRenderContextInterface(const QDemonRef<QDemonRenderContext> &ctx, const QString &inApplicationDirectory); + // TODO: temp workaround for now + struct QDemonRenderContextInterfacePtr + { + QDemonRenderContextInterfacePtr() = default; + QDemonRenderContextInterfacePtr(QDemonRenderContextInterface *ptr, quintptr wid) : m_ptr(ptr), m_wid(wid) {} + QDemonRenderContextInterface * operator-> () const { return m_ptr.data(); } + ~QDemonRenderContextInterfacePtr() { if (!m_ptr.isNull() && m_ptr->ref == 0) QDemonRenderContextInterface::releaseRenderContextInterface(m_wid); } + bool isNull() const { return m_ptr.data() == nullptr; } + private: + friend QDemonRenderContextInterface; + QDemonRef<QDemonRenderContextInterface> m_ptr; + quintptr m_wid = 0; + }; + + static QDemonRenderContextInterface::QDemonRenderContextInterfacePtr getRenderContextInterface(const QDemonRef<QDemonRenderContext> &ctx, const QString &inApplicationDirectory, quintptr wid); + static QDemonRenderContextInterface::QDemonRenderContextInterfacePtr getRenderContextInterface(quintptr wid); + ~QDemonRenderContextInterface(); QDemonRef<QDemonRendererInterface> renderer(); QDemonRef<QDemonRendererImpl> renderWidgetContext(); diff --git a/src/runtimerender/qdemonrendercustommaterialsystem.cpp b/src/runtimerender/qdemonrendercustommaterialsystem.cpp index 0c075ea525c27686dffe6e40336a32164db276b7..83c1d60433f83f2fd0460659f6d947233edcc6e3 100644 --- a/src/runtimerender/qdemonrendercustommaterialsystem.cpp +++ b/src/runtimerender/qdemonrendercustommaterialsystem.cpp @@ -36,7 +36,7 @@ #include <QtDemonRuntimeRender/qdemonrendercustommaterialrendercontext.h> #include <QtDemonRuntimeRender/qdemonrendercontextcore.h> -#include <QtDemonRuntimeRender/qdemonrendercustommaterial.h> +//#include <QtDemonRuntimeRender/qdemonrendercustommaterial.h> #include <QtDemonRuntimeRender/qdemonrenderdynamicobjectsystemcommands.h> #include <QtDemonRuntimeRender/qdemonrenderbuffermanager.h> #include <QtDemonRuntimeRender/qdemonrenderresourcemanager.h> @@ -480,23 +480,6 @@ void QDemonCustomMaterialVertexPipeline::doGenerateVertexColor() vertex().append("\tvarColor = attr_color;"); } -struct QDemonMaterialClass -{ - QAtomicInt ref; - QDemonDynamicObjectClass *m_class; - bool m_hasTransparency = false; - bool m_hasRefraction = false; - bool m_hasDisplacement = false; - bool m_alwaysDirty = false; - quint32 m_shaderKey = 0; - quint32 m_layerCount = 0; - QDemonMaterialClass(QDemonDynamicObjectClass &inCls) : m_class(&inCls) {} - - void afterWrite() { m_class = nullptr; } - - void afterRead(QDemonDynamicObjectClass &inCls) { m_class = &inCls; } -}; - struct QDemonShaderMapKey { TStrStrPair m_name; @@ -543,13 +526,13 @@ struct QDemonCustomMaterialTextureData { } - void set(const dynamic::QDemonPropertyDefinition *inDefinition) + void set(const QDemonRenderCustomMaterial::TextureProperty *inDefinition) { if (texture && inDefinition) { - texture->setMagFilter(inDefinition->magFilterOp); - texture->setMinFilter(inDefinition->minFilterOp); - texture->setTextureWrapS(inDefinition->coordOp); - texture->setTextureWrapT(inDefinition->coordOp); + texture->setMagFilter(inDefinition->magFilterType); + texture->setMinFilter(inDefinition->minFilterType); + texture->setTextureWrapS(inDefinition->clampType); + texture->setTextureWrapT(inDefinition->clampType); } else if (texture) { // set some defaults texture->setMinFilter(QDemonRenderTextureMinifyingOp::Linear); @@ -761,12 +744,6 @@ QDemonMaterialSystem::~QDemonMaterialSystem() allocatedBuffers[0] = allocatedBuffers.back(); allocatedBuffers.pop_back(); } - - for (qint32 idx = 0; idx < allocatedImages.size(); ++idx) { - QDemonRenderImage *pImage = allocatedImages[idx].second; - ::free(pImage); - } - allocatedImages.clear(); } void QDemonMaterialSystem::releaseBuffer(qint32 inIdx) @@ -786,51 +763,6 @@ void QDemonMaterialSystem::releaseBuffer(qint32 inIdx) } } -bool QDemonMaterialSystem::isMaterialRegistered(const QString &inStr) -{ - return stringMaterialMap.find(inStr) != stringMaterialMap.end(); -} - -bool QDemonMaterialSystem::registerMaterialClass(const QString &inName, const QDemonDataView<dynamic::QDemonPropertyDeclaration> &inProperties) -{ - if (isMaterialRegistered(inName)) - return false; - context->dynamicObjectSystem()->doRegister(inName, - inProperties, - sizeof(QDemonRenderCustomMaterial), - QDemonRenderGraphObject::Type::CustomMaterial); - QDemonDynamicObjectClass *theClass = context->dynamicObjectSystem()->dynamicObjectClass(inName); - if (theClass == nullptr) { - Q_ASSERT(false); - return false; - } - QDemonRef<QDemonMaterialClass> theNewClass(new QDemonMaterialClass(*theClass)); - stringMaterialMap.insert(inName, theNewClass); - return true; -} - -QDemonMaterialClass *QDemonMaterialSystem::getMaterialClass(const QString &inStr) -{ - auto theIter = stringMaterialMap.constFind(inStr); - if (theIter != stringMaterialMap.constEnd()) - return theIter.value().data(); - return nullptr; -} - -const QDemonMaterialClass *QDemonMaterialSystem::getMaterialClass(const QString &inStr) const -{ - return const_cast<QDemonMaterialSystem *>(this)->getMaterialClass(inStr); -} - -QDemonDataView<dynamic::QDemonPropertyDefinition> QDemonMaterialSystem::getCustomMaterialProperties(const QString &inCustomMaterialName) const -{ - QDemonDynamicObjectClass *theMaterialClass = context->dynamicObjectSystem()->dynamicObjectClass(inCustomMaterialName); - if (theMaterialClass) - return theMaterialClass->getProperties(); - - return QDemonDataView<dynamic::QDemonPropertyDefinition>(); -} - qint32 QDemonMaterialSystem::findBuffer(const QString &inName) { for (qint32 idx = 0, end = allocatedBuffers.size(); idx < end; ++idx) @@ -839,26 +771,20 @@ qint32 QDemonMaterialSystem::findBuffer(const QString &inName) return allocatedBuffers.size(); } -qint32 QDemonMaterialSystem::findAllocatedImage(const QString &inName) -{ - for (qint32 idx = 0, end = allocatedImages.size(); idx < end; ++idx) - if (allocatedImages[idx].first == inName) - return idx; - return -1; -} - -bool QDemonMaterialSystem::textureNeedsMips(const dynamic::QDemonPropertyDefinition *inPropDec, QDemonRenderTexture2D *inTexture) +bool QDemonMaterialSystem::textureNeedsMips(const QDemonRenderCustomMaterial::TextureProperty *inPropDec, QDemonRenderTexture2D *inTexture) { if (inPropDec && inTexture) { - return bool((inPropDec->minFilterOp == QDemonRenderTextureMinifyingOp::LinearMipmapLinear) + return bool((inPropDec->minFilterType == QDemonRenderTextureMinifyingOp::LinearMipmapLinear) && (inTexture->numMipmaps() == 0)); } return false; } -void QDemonMaterialSystem::setTexture(const QDemonRef<QDemonRenderShaderProgram> &inShader, const QString &inPropName, - const QDemonRef<QDemonRenderTexture2D> &inTexture, const dynamic::QDemonPropertyDefinition *inPropDec, +void QDemonMaterialSystem::setTexture(const QDemonRef<QDemonRenderShaderProgram> &inShader, + const QString &inPropName, + const QDemonRef<QDemonRenderTexture2D> &inTexture, + const QDemonRenderCustomMaterial::TextureProperty *inPropDec, bool needMips) { QDemonRef<QDemonCustomMaterialTextureData> theTextureEntry; @@ -878,110 +804,18 @@ void QDemonMaterialSystem::setTexture(const QDemonRef<QDemonRenderShaderProgram> theTextureEntry->set(inPropDec); } -void QDemonMaterialSystem::setPropertyEnumNames(const QString &inName, const QString &inPropName, const QDemonDataView<QString> &inNames) -{ - context->dynamicObjectSystem()->setPropertyEnumNames(inName, inPropName, inNames); -} - -void QDemonMaterialSystem::setPropertyTextureSettings(const QString &inName, const QString &inPropName, const QString &inPropPath, QDemonRenderTextureTypeValue inTexType, QDemonRenderTextureCoordOp inCoordOp, QDemonRenderTextureMagnifyingOp inMagFilterOp, QDemonRenderTextureMinifyingOp inMinFilterOp) -{ - QDemonMaterialClass *theClass = getMaterialClass(inName); - if (theClass && inTexType == QDemonRenderTextureTypeValue::Displace) { - theClass->m_hasDisplacement = true; - } - context->dynamicObjectSystem() - ->setPropertyTextureSettings(inName, inPropName, inPropPath, inTexType, inCoordOp, inMagFilterOp, inMinFilterOp); -} - // TODO: Use an enum for the shader type? +// Remove and call the setShaderData func directly? void QDemonMaterialSystem::setMaterialClassShader(QString inName, const QByteArray &inShaderType, const QByteArray &inShaderVersion, const QByteArray &inShaderData, bool inHasGeomShader, bool inIsComputeShader) { context->dynamicObjectSystem()->setShaderData(inName, inShaderData, inShaderType, inShaderVersion, inHasGeomShader, inIsComputeShader); } -QDemonRenderCustomMaterial *QDemonMaterialSystem::createCustomMaterial(const QString &inName) -{ - QDemonRenderCustomMaterial *theMaterial = static_cast<QDemonRenderCustomMaterial *>( - context->dynamicObjectSystem()->createInstance(inName)); - QDemonMaterialClass *theClass = getMaterialClass(inName); - - if (theMaterial) { - quint32 key = 0, count = 0; - if (theClass) { - key = theClass->m_shaderKey; - count = theClass->m_layerCount; - } - theMaterial->initialize(key, count); - } - - return theMaterial; -} - -void QDemonMaterialSystem::setCustomMaterialTransparency(const QString &inName, bool inHasTransparency) -{ - QDemonMaterialClass *theClass = getMaterialClass(inName); - - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - - theClass->m_hasTransparency = inHasTransparency; -} - -void QDemonMaterialSystem::setCustomMaterialRefraction(const QString &inName, bool inHasRefraction) -{ - QDemonMaterialClass *theClass = getMaterialClass(inName); - - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - - theClass->m_hasRefraction = inHasRefraction; -} - -void QDemonMaterialSystem::setCustomMaterialAlwaysDirty(const QString &inName, bool inIsAlwaysDirty) -{ - QDemonMaterialClass *theClass = getMaterialClass(inName); - - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - - theClass->m_alwaysDirty = inIsAlwaysDirty; -} - -void QDemonMaterialSystem::setCustomMaterialShaderKey(const QString &inName, quint32 inShaderKey) -{ - QDemonMaterialClass *theClass = getMaterialClass(inName); - - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - - theClass->m_shaderKey = inShaderKey; -} - -void QDemonMaterialSystem::setCustomMaterialLayerCount(const QString &inName, quint32 inLayerCount) -{ - QDemonMaterialClass *theClass = getMaterialClass(inName); - - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - - theClass->m_layerCount = inLayerCount; -} - -void QDemonMaterialSystem::setCustomMaterialCommands(QString inName, QDemonDataView<dynamic::QDemonCommand *> inCommands) -{ - context->dynamicObjectSystem()->setRenderCommands(inName, inCommands); -} +//void QDemonMaterialSystem::setCustomMaterialCommands(QString inName, QDemonDataView<dynamic::QDemonCommand *> inCommands) +//{ +// context->dynamicObjectSystem()->setRenderCommands(inName, inCommands); +//} QDemonRef<QDemonRenderShaderProgram> QDemonMaterialSystem::getShader(QDemonCustomMaterialRenderContext &inRenderContext, const QDemonRenderCustomMaterial &inMaterial, const dynamic::QDemonBindShader &inCommand, const TShaderFeatureSet &inFeatureSet, const dynamic::QDemonDynamicShaderProgramFlags &inFlags) { @@ -1054,108 +888,117 @@ QDemonMaterialOrComputeShader QDemonMaterialSystem::bindShader(QDemonCustomMater return QDemonMaterialOrComputeShader(); } -void QDemonMaterialSystem::doApplyInstanceValue(QDemonRenderCustomMaterial &inMaterial, quint8 *inDataPtr, const QString &inPropertyName, QDemonRenderShaderDataType inPropertyType, const QDemonRef<QDemonRenderShaderProgram> &inShader, const dynamic::QDemonPropertyDefinition &inDefinition) +void QDemonMaterialSystem::doApplyInstanceValue(QDemonRenderCustomMaterial &inMaterial, + const QString &inPropertyName, + const QVariant &propertyValue, + QDemonRenderShaderDataType inPropertyType, + const QDemonRef<QDemonRenderShaderProgram> &inShader) { QDemonRef<QDemonRenderShaderConstantBase> theConstant = inShader->shaderConstant(inPropertyName.toLocal8Bit()); if (theConstant) { if (theConstant->getShaderConstantType() == inPropertyType) { if (inPropertyType == QDemonRenderShaderDataType::Texture2D) { // StaticAssert<sizeof(QString) == sizeof(QDemonRenderTexture2DPtr)>::valid_expression(); - const char *theStrPtr = inMaterial.imagePath; - const char *theStrPtrTst = reinterpret_cast<const char *>(inDataPtr); // TODO: - QDemonRef<QDemonBufferManager> theBufferManager(context->bufferManager()); - QDemonRef<QDemonRenderTexture2D> theTexture; - - if (theStrPtr) { - QDemonRenderImageTextureData theTextureData = theBufferManager->loadRenderImage(QString::fromLocal8Bit(theStrPtr)); - if (theTextureData.m_texture) { - theTexture = theTextureData.m_texture; - setTexture(inShader, - inPropertyName, - theTexture, - &inDefinition, - textureNeedsMips(&inDefinition, theTexture.data())); + QDemonRenderCustomMaterial::TextureProperty *textureProperty = reinterpret_cast<QDemonRenderCustomMaterial::TextureProperty *>(propertyValue.value<void *>()); + QDemonRenderImage *image = textureProperty->texImage; + if (image) { + const QString imageSource = image->m_imagePath; + QDemonRef<QDemonBufferManager> theBufferManager(context->bufferManager()); + QDemonRef<QDemonRenderTexture2D> theTexture; + + if (!imageSource.isEmpty()) { + QDemonRenderImageTextureData theTextureData = theBufferManager->loadRenderImage(imageSource); + if (theTextureData.m_texture) { + theTexture = theTextureData.m_texture; + dynamic::QDemonPropertyDefinition def; + setTexture(inShader, + inPropertyName, + theTexture, + textureProperty, // TODO: Should not be null! + textureNeedsMips(textureProperty /* TODO: Should not be null! */, theTexture.data())); + } } } } else { + // TODO: switch (inPropertyType) { case QDemonRenderShaderDataType::Integer: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<qint32 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.toInt()); break; case QDemonRenderShaderDataType::IntegerVec2: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<qint32_2 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<qint32_2>()); break; case QDemonRenderShaderDataType::IntegerVec3: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<qint32_3 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<qint32_3>()); break; case QDemonRenderShaderDataType::IntegerVec4: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<qint32_4 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<qint32_4>()); break; case QDemonRenderShaderDataType::Boolean: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<bool *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<bool>()); break; case QDemonRenderShaderDataType::BooleanVec2: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<bool_2 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<bool_2>()); break; case QDemonRenderShaderDataType::BooleanVec3: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<bool_3 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<bool_3>()); break; case QDemonRenderShaderDataType::BooleanVec4: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<bool_4 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<bool_4>()); break; case QDemonRenderShaderDataType::Float: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<float *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<float>()); break; case QDemonRenderShaderDataType::Vec2: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QVector2D *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<QVector2D>()); break; case QDemonRenderShaderDataType::Vec3: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QVector3D *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<QVector3D>()); break; case QDemonRenderShaderDataType::Vec4: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QVector4D *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<QVector4D>()); break; case QDemonRenderShaderDataType::UnsignedInteger: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<quint32 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<quint32>()); break; case QDemonRenderShaderDataType::UnsignedIntegerVec2: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<quint32_2 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<quint32_2>()); break; case QDemonRenderShaderDataType::UnsignedIntegerVec3: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<quint32_3 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<quint32_3>()); break; case QDemonRenderShaderDataType::UnsignedIntegerVec4: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<quint32_4 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<quint32_4>()); break; case QDemonRenderShaderDataType::Matrix3x3: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QMatrix3x3 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<QMatrix3x3>()); break; case QDemonRenderShaderDataType::Matrix4x4: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QMatrix4x4 *>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), propertyValue.value<QMatrix4x4>()); break; case QDemonRenderShaderDataType::Texture2D: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderTexture2D **>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderTexture2D **>(propertyValue.value<void *>()))); break; case QDemonRenderShaderDataType::Texture2DHandle: inShader->setPropertyValue(theConstant.data(), - *(reinterpret_cast<QDemonRenderTexture2D ***>(inDataPtr))); + *(reinterpret_cast<QDemonRenderTexture2D ***>(propertyValue.value<void *>()))); break; case QDemonRenderShaderDataType::Texture2DArray: inShader->setPropertyValue(theConstant.data(), - *(reinterpret_cast<QDemonRenderTexture2DArray **>(inDataPtr))); + *(reinterpret_cast<QDemonRenderTexture2DArray **>(propertyValue.value<void *>()))); break; case QDemonRenderShaderDataType::TextureCube: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderTextureCube **>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderTextureCube **>(propertyValue.value<void *>()))); break; case QDemonRenderShaderDataType::TextureCubeHandle: inShader->setPropertyValue(theConstant.data(), - *(reinterpret_cast<QDemonRenderTextureCube ***>(inDataPtr))); + *(reinterpret_cast<QDemonRenderTextureCube ***>(propertyValue.value<void *>()))); break; case QDemonRenderShaderDataType::Image2D: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderImage2D **>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderImage2D **>(propertyValue.value<void *>()))); break; case QDemonRenderShaderDataType::DataBuffer: - inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderDataBuffer **>(inDataPtr))); + inShader->setPropertyValue(theConstant.data(), *(reinterpret_cast<QDemonRenderDataBuffer **>(propertyValue.value<void *>()))); break; default: Q_UNREACHABLE(); @@ -1171,33 +1014,24 @@ void QDemonMaterialSystem::doApplyInstanceValue(QDemonRenderCustomMaterial &inMa } } -void QDemonMaterialSystem::applyInstanceValue(QDemonRenderCustomMaterial &inMaterial, QDemonMaterialClass &inClass, const QDemonRef<QDemonRenderShaderProgram> &inShader, const dynamic::QDemonApplyInstanceValue &inCommand) +void QDemonMaterialSystem::applyInstanceValue(QDemonRenderCustomMaterial &inMaterial, + const QDemonRef<QDemonRenderShaderProgram> &inShader, + const dynamic::QDemonApplyInstanceValue &inCommand) { // sanity check if (!inCommand.m_propertyName.isNull()) { - bool canGetData = inCommand.m_valueOffset + dynamic::getSizeofShaderDataType(inCommand.m_valueType) - <= inMaterial.dataSectionByteSize; - if (canGetData == false) { - Q_ASSERT(false); - return; - } - quint8 *dataPtr = inMaterial.getDataSectionBegin() + inCommand.m_valueOffset; - const dynamic::QDemonPropertyDefinition *theDefinition = inClass.m_class->findPropertyByName(inCommand.m_propertyName); - if (theDefinition) - doApplyInstanceValue(inMaterial, dataPtr, inCommand.m_propertyName, inCommand.m_valueType, inShader, *theDefinition); + const auto &properties = inMaterial.properties; + const auto foundIt = std::find_if(properties.cbegin(), properties.cend(), [&inCommand](const QDemonRenderCustomMaterial::Property &prop) { return (prop.name == inCommand.m_propertyName); }); + if (foundIt != properties.cend()) + doApplyInstanceValue(inMaterial, foundIt->name, foundIt->value, foundIt->shaderDataType, inShader); } else { - QDemonDataView<dynamic::QDemonPropertyDefinition> theDefs = inClass.m_class->getProperties(); - for (quint32 idx = 0, end = theDefs.size(); idx < end; ++idx) { - const dynamic::QDemonPropertyDefinition &theDefinition(theDefs[idx]); - QDemonRef<QDemonRenderShaderConstantBase> theConstant = inShader->shaderConstant(theDefinition.name); - - // This is fine, the property wasn't found and we continue, no problem. - if (!theConstant) - continue; - quint8 *dataPtr = inMaterial.getDataSectionBegin() + theDefinition.offset; - inMaterial.imagePath = theDefinition.imagePath; - doApplyInstanceValue(inMaterial, dataPtr, theDefinition.name, theDefinition.dataType, inShader, theDefinition); - } + const auto &properties = inMaterial.properties; + for (const auto &prop : properties) + doApplyInstanceValue(inMaterial, prop.name, prop.value, prop.shaderDataType, inShader); + + const auto textProps = inMaterial.textureProperties; + for (const auto &prop : textProps) + doApplyInstanceValue(inMaterial, prop.name, QVariant::fromValue((void *)&prop), prop.shaderDataType, inShader); } } @@ -1218,6 +1052,38 @@ void QDemonMaterialSystem::applyBlending(const dynamic::QDemonApplyBlending &inC theContext->setBlendEquation(blendEqu); } +void QDemonMaterialSystem::applyRenderStateValue(const dynamic::QDemonApplyRenderState &inCommand) +{ + QDemonRef<QDemonRenderContext> theContext(context->renderContext()); + + switch (inCommand.m_renderState) { + case QDemonRenderState::Blend: + theContext->setBlendingEnabled(inCommand.m_enabled); + break; + case QDemonRenderState::CullFace: + theContext->setCullingEnabled(inCommand.m_enabled); + break; + case QDemonRenderState::DepthTest: + theContext->setDepthTestEnabled(inCommand.m_enabled); + break; + case QDemonRenderState::StencilTest: + theContext->setStencilTestEnabled(inCommand.m_enabled); + break; + case QDemonRenderState::ScissorTest: + theContext->setScissorTestEnabled(inCommand.m_enabled); + break; + case QDemonRenderState::DepthWrite: + theContext->setDepthWriteEnabled(inCommand.m_enabled); + break; + case QDemonRenderState::Multisample: + theContext->setMultisampleEnabled(inCommand.m_enabled); + break; + case QDemonRenderState::Unknown: + break; + } + +} + const QDemonRef<QDemonRenderTexture2D> QDemonMaterialSystem::applyBufferValue(const QDemonRenderCustomMaterial &inMaterial, const QDemonRef<QDemonRenderShaderProgram> &inShader, const dynamic::QDemonApplyBufferValue &inCommand, const QDemonRef<QDemonRenderTexture2D> inSourceTexture) { QDemonRef<QDemonRenderTexture2D> theTexture = nullptr; @@ -1236,15 +1102,14 @@ const QDemonRef<QDemonRenderTexture2D> QDemonMaterialSystem::applyBufferValue(co theTexture = inSourceTexture; if (!inCommand.m_paramName.isNull()) { - QDemonRef<QDemonRenderShaderConstantBase> theConstant = inShader->shaderConstant( - inCommand.m_paramName.toLocal8Bit().constData()); + QDemonRef<QDemonRenderShaderConstantBase> theConstant = inShader->shaderConstant(inCommand.m_paramName.constData()); if (theConstant) { if (theConstant->getShaderConstantType() != QDemonRenderShaderDataType::Texture2D) { qCCritical(INVALID_OPERATION, "CustomMaterial %s: Binding buffer to parameter %s that is not a texture", - qPrintable(inMaterial.className), - qPrintable(inCommand.m_paramName)); + inMaterial.className, + inCommand.m_paramName.constData()); Q_ASSERT(false); } else { setTexture(inShader, inCommand.m_paramName, theTexture); @@ -1564,7 +1429,10 @@ void QDemonMaterialSystem::renderPass(QDemonCustomMaterialRenderContext &inRende theContext->draw(theDrawMode, count, offset); } -void QDemonMaterialSystem::doRenderCustomMaterial(QDemonCustomMaterialRenderContext &inRenderContext, const QDemonRenderCustomMaterial &inMaterial, QDemonMaterialClass &inClass, const QDemonRef<QDemonRenderFrameBuffer> &inTarget, const TShaderFeatureSet &inFeatureSet) +void QDemonMaterialSystem::doRenderCustomMaterial(QDemonCustomMaterialRenderContext &inRenderContext, + const QDemonRenderCustomMaterial &inMaterial, + const QDemonRef<QDemonRenderFrameBuffer> &inTarget, + const TShaderFeatureSet &inFeatureSet) { QDemonRef<QDemonRenderContext> theContext = context->renderContext(); QDemonRef<QDemonCustomMaterialShader> theCurrentShader(nullptr); @@ -1587,7 +1455,7 @@ void QDemonMaterialSystem::doRenderCustomMaterial(QDemonCustomMaterialRenderCont QVector2D theDestSize; bool theRenderTargetNeedsClear = false; - QDemonDataView<dynamic::QDemonCommand *> theCommands(inClass.m_class->getRenderCommands()); + QDemonDataView<dynamic::QDemonCommand *> theCommands = toDataView(inMaterial.commands.cbegin(), inMaterial.commands.size()); for (qint32 commandIdx = 0, commandEnd = theCommands.size(); commandIdx < commandEnd; ++commandIdx) { const dynamic::QDemonCommand &theCommand(*theCommands[commandIdx]); @@ -1646,7 +1514,9 @@ void QDemonMaterialSystem::doRenderCustomMaterial(QDemonCustomMaterialRenderCont blitFramebuffer(inRenderContext, static_cast<const dynamic::QDemonApplyBlitFramebuffer &>(theCommand), inTarget); break; case dynamic::CommandType::ApplyRenderState: - break; // TODO: "simple_glass.material + // TODO: The applyRenderStateValue() function is a very naive implementation + applyRenderStateValue(static_cast<const dynamic::QDemonApplyRenderState &>(theCommand)); + break; default: Q_ASSERT(false); break; @@ -1667,17 +1537,12 @@ void QDemonMaterialSystem::doRenderCustomMaterial(QDemonCustomMaterialRenderCont QString QDemonMaterialSystem::getShaderName(const QDemonRenderCustomMaterial &inMaterial) { - QDemonMaterialClass *theClass = getMaterialClass(inMaterial.className); - if (!theClass) - return QString(); - - QDemonDataView<dynamic::QDemonCommand *> theCommands = theClass->m_class->getRenderCommands(); - TShaderAndFlags thePrepassShader; - for (qint32 idx = 0, end = theCommands.size(); idx < end && thePrepassShader.first == nullptr; ++idx) { - const dynamic::QDemonCommand &theCommand = *theCommands[idx]; - if (theCommand.m_type == dynamic::CommandType::BindShader) { - const dynamic::QDemonBindShader &theBindCommand = static_cast<const dynamic::QDemonBindShader &>(theCommand); - return theBindCommand.m_shaderPath; + auto it = inMaterial.commands.cbegin(); + const auto end = inMaterial.commands.cend(); + for (; it != end; ++it) { + if ((*it)->m_type == dynamic::CommandType::BindShader) { + dynamic::QDemonBindShader *bindCommand = static_cast<dynamic::QDemonBindShader *>(*it); + return bindCommand->m_shaderPath; } } @@ -1687,89 +1552,28 @@ QString QDemonMaterialSystem::getShaderName(const QDemonRenderCustomMaterial &in void QDemonMaterialSystem::applyShaderPropertyValues(const QDemonRenderCustomMaterial &inMaterial, const QDemonRef<QDemonRenderShaderProgram> &inProgram) { - QDemonMaterialClass *theClass = getMaterialClass(inMaterial.className); - if (!theClass) - return; - dynamic::QDemonApplyInstanceValue applier; - applyInstanceValue(const_cast<QDemonRenderCustomMaterial &>(inMaterial), *theClass, inProgram, applier); -} - -void QDemonMaterialSystem::prepareTextureForRender(QDemonMaterialClass &inClass, QDemonRenderCustomMaterial &inMaterial) -{ - QDemonDataView<dynamic::QDemonPropertyDefinition> thePropDefs = inClass.m_class->getProperties(); - for (qint32 idx = 0, end = thePropDefs.size(); idx < end; ++idx) { - if (thePropDefs[idx].dataType == QDemonRenderShaderDataType::Texture2D) { - if (thePropDefs[idx].texUsageType == QDemonRenderTextureTypeValue::Displace) { - QDemonRenderImage *pImage = nullptr; - - // we only do this to not miss if "None" is selected - QString theStrPtr = *reinterpret_cast<QString *>(inMaterial.getDataSectionBegin() + thePropDefs[idx].offset); - - if (!theStrPtr.isNull()) { - - const qint32 index = findAllocatedImage(thePropDefs[idx].imagePath); - if (index == -1) { - pImage = new QDemonRenderImage(); - allocatedImages.push_back(QPair<QString, QDemonRenderImage *>(thePropDefs[idx].imagePath, pImage)); - } else - pImage = allocatedImages[index].second; - - if (inMaterial.m_displacementMap != pImage) { - inMaterial.m_displacementMap = pImage; - inMaterial.m_displacementMap->m_imagePath = thePropDefs[idx].imagePath; - inMaterial.m_displacementMap->m_imageShaderName = thePropDefs[idx].name; // this is our name in the shader - inMaterial.m_displacementMap->m_verticalTilingMode = thePropDefs[idx].coordOp; - inMaterial.m_displacementMap->m_horizontalTilingMode = thePropDefs[idx].coordOp; - } - } else { - inMaterial.m_displacementMap = nullptr; - } - } else if (thePropDefs[idx].texUsageType == QDemonRenderTextureTypeValue::Emissive2) { - QDemonRenderImage *pImage = nullptr; - - // we only do this to not miss if "None" is selected - QString theStrPtr = *reinterpret_cast<QString *>(inMaterial.getDataSectionBegin() + thePropDefs[idx].offset); - - if (!theStrPtr.isNull()) { - const qint32 index = findAllocatedImage(thePropDefs[idx].imagePath); - if (index == -1) { - pImage = new QDemonRenderImage(); - allocatedImages.push_back(QPair<QString, QDemonRenderImage *>(thePropDefs[idx].imagePath, pImage)); - } else - pImage = allocatedImages[index].second; - - if (inMaterial.m_emissiveMap2 != pImage) { - inMaterial.m_emissiveMap2 = pImage; - inMaterial.m_emissiveMap2->m_imagePath = thePropDefs[idx].imagePath; - inMaterial.m_emissiveMap2->m_imageShaderName = thePropDefs[idx].name; // this is our name in the shader - inMaterial.m_emissiveMap2->m_verticalTilingMode = thePropDefs[idx].coordOp; - inMaterial.m_emissiveMap2->m_horizontalTilingMode = thePropDefs[idx].coordOp; - } - } else { - inMaterial.m_emissiveMap2 = nullptr; - } - } - } - } + applyInstanceValue(const_cast<QDemonRenderCustomMaterial &>(inMaterial), inProgram, applier); } -void QDemonMaterialSystem::prepareDisplacementForRender(QDemonMaterialClass &inClass, QDemonRenderCustomMaterial &inMaterial) +void QDemonMaterialSystem::prepareDisplacementForRender(QDemonRenderCustomMaterial &inMaterial) { + // TODO: Shouldn't be needed anymore, as there's only one place where the values are updated if (inMaterial.m_displacementMap == nullptr) return; // our displacement mappin in MDL has fixed naming - QDemonDataView<dynamic::QDemonPropertyDefinition> thePropDefs = inClass.m_class->getProperties(); - for (qint32 idx = 0, end = thePropDefs.size(); idx < end; ++idx) { - if (thePropDefs[idx].dataType == QDemonRenderShaderDataType::Float && (thePropDefs[idx].name == "displaceAmount")) { - float theValue = *reinterpret_cast<const float *>(inMaterial.getDataSectionBegin() + thePropDefs[idx].offset); - inMaterial.m_displaceAmount = theValue; - } else if (thePropDefs[idx].dataType == QDemonRenderShaderDataType::Vec3 && (thePropDefs[idx].name == "displace_tiling")) { - QVector3D theValue = *reinterpret_cast<const QVector3D *>(inMaterial.getDataSectionBegin() - + thePropDefs[idx].offset); + const auto &props = inMaterial.properties; + for (const auto &prop : props) { + if (prop.shaderDataType == QDemonRenderShaderDataType::Float && prop.name == QByteArrayLiteral("displaceAmount")) { + bool ok = false; + const float theValue = prop.value.toFloat(&ok); //*reinterpret_cast<const float *>(inMaterial.getDataSectionBegin() + thePropDefs[idx].offset); + if (ok) + inMaterial.m_displaceAmount = theValue; + } else if (prop.shaderDataType == QDemonRenderShaderDataType::Vec3 && prop.name == QByteArrayLiteral("displace_tiling")) { + const QVector3D theValue = prop.value.value<QVector3D>(); // = *reinterpret_cast<const QVector3D *>(inMaterial.getDataSectionBegin() + thePropDefs[idx].offset); if (theValue.x() != inMaterial.m_displacementMap->m_scale.x() - || theValue.y() != inMaterial.m_displacementMap->m_scale.y()) { + || theValue.y() != inMaterial.m_displacementMap->m_scale.y()) { inMaterial.m_displacementMap->m_scale = QVector2D(theValue.x(), theValue.y()); inMaterial.m_displacementMap->m_flags.setFlag(QDemonRenderImage::Flag::TransformDirty); } @@ -1777,12 +1581,10 @@ void QDemonMaterialSystem::prepareDisplacementForRender(QDemonMaterialClass &inC } } -void QDemonMaterialSystem::prepareMaterialForRender(QDemonMaterialClass &inClass, QDemonRenderCustomMaterial &inMaterial) +void QDemonMaterialSystem::prepareMaterialForRender(QDemonRenderCustomMaterial &inMaterial) { - prepareTextureForRender(inClass, inMaterial); - - if (inClass.m_hasDisplacement) - prepareDisplacementForRender(inClass, inMaterial); + if (inMaterial.m_displacementMap) // inClass->m_hasDisplacement + prepareDisplacementForRender(inMaterial); } // Returns true if the material is dirty and thus will produce a different render result @@ -1791,19 +1593,8 @@ void QDemonMaterialSystem::prepareMaterialForRender(QDemonMaterialClass &inClass // object is completely transparent bool QDemonMaterialSystem::prepareForRender(const QDemonRenderModel &, const QDemonRenderSubset &, QDemonRenderCustomMaterial &inMaterial, bool clearMaterialDirtyFlags) { - QDemonMaterialClass *theMaterialClass = getMaterialClass(inMaterial.className); - if (theMaterialClass == nullptr) { - Q_ASSERT(false); - return false; - } - - prepareMaterialForRender(*theMaterialClass, inMaterial); - - inMaterial.m_hasTransparency = theMaterialClass->m_hasTransparency; - inMaterial.m_hasRefraction = theMaterialClass->m_hasRefraction; - inMaterial.m_hasVolumetricDF = false; - - bool wasDirty = inMaterial.isDirty() || theMaterialClass->m_alwaysDirty; + prepareMaterialForRender(inMaterial); + const bool wasDirty = inMaterial.isDirty(); // TODO: Always dirty flag? if (clearMaterialDirtyFlags) inMaterial.updateDirtyForFrame(); @@ -1813,8 +1604,6 @@ bool QDemonMaterialSystem::prepareForRender(const QDemonRenderModel &, const QDe // TODO - handle UIC specific features such as vertex offsets for prog-aa and opacity. void QDemonMaterialSystem::renderSubset(QDemonCustomMaterialRenderContext &inRenderContext, const TShaderFeatureSet &inFeatureSet) { - QDemonMaterialClass *theClass = getMaterialClass(inRenderContext.material.className); - // Ensure that our overall render context comes back no matter what the client does. QDemonRenderContextScopedProperty<QDemonRenderBlendFunctionArgument> __blendFunction(*context->renderContext(), &QDemonRenderContext::blendFunction, @@ -1829,13 +1618,12 @@ void QDemonMaterialSystem::renderSubset(QDemonCustomMaterialRenderContext &inRen &QDemonRenderContext::isBlendingEnabled, &QDemonRenderContext::setBlendingEnabled); - doRenderCustomMaterial(inRenderContext, inRenderContext.material, *theClass, context->renderContext()->renderTarget(), inFeatureSet); + doRenderCustomMaterial(inRenderContext, inRenderContext.material, context->renderContext()->renderTarget(), inFeatureSet); } bool QDemonMaterialSystem::renderDepthPrepass(const QMatrix4x4 &inMVP, const QDemonRenderCustomMaterial &inMaterial, const QDemonRenderSubset &inSubset) { - QDemonMaterialClass *theClass = getMaterialClass(inMaterial.className); - QDemonDataView<dynamic::QDemonCommand *> theCommands = theClass->m_class->getRenderCommands(); + QDemonDataView<dynamic::QDemonCommand *> theCommands = toDataView(inMaterial.commands.cbegin(), inMaterial.commands.size()); TShaderAndFlags thePrepassShader; for (qint32 idx = 0, end = theCommands.size(); idx < end && thePrepassShader.first == nullptr; ++idx) { const dynamic::QDemonCommand &theCommand = *theCommands[idx]; @@ -1859,12 +1647,6 @@ bool QDemonMaterialSystem::renderDepthPrepass(const QMatrix4x4 &inMVP, const QDe return true; } -void QDemonMaterialSystem::onMaterialActivationChange(const QDemonRenderCustomMaterial &inMaterial, bool inActive) -{ - Q_UNUSED(inMaterial) - Q_UNUSED(inActive) -} - void QDemonMaterialSystem::endFrame() { if (lastFrameTime.elapsed() != 0) diff --git a/src/runtimerender/qdemonrendercustommaterialsystem.h b/src/runtimerender/qdemonrendercustommaterialsystem.h index 4bc1ded7cdf95bafb5a03baa8098b84ea249e63f..8c122935326deb78e46333b68787c07e0b0a7d28 100644 --- a/src/runtimerender/qdemonrendercustommaterialsystem.h +++ b/src/runtimerender/qdemonrendercustommaterialsystem.h @@ -37,6 +37,8 @@ #include <QtCore/qhash.h> +#include <QtDemonRuntimeRender/qdemonrendercustommaterial.h> // Make it possible to forward declare the nested TextureProperty + QT_BEGIN_NAMESPACE namespace dynamic { @@ -61,6 +63,7 @@ struct QDemonAllocateBuffer; struct QDemonApplyBufferValue; struct QDemonBindBuffer; struct QDemonApplyBlitFramebuffer; +struct QDemonApplyRenderState; } // How to handle blend modes? @@ -75,24 +78,19 @@ public: private: typedef QHash<QDemonShaderMapKey, QDemonRef<QDemonCustomMaterialShader>> ShaderMap; typedef QPair<QString, QDemonRenderImage *> AllocatedImageEntry; - typedef QHash<QString, QDemonRef<QDemonMaterialClass>> StringMaterialMap; typedef QPair<QString, QString> TStrStrPair; typedef QPair<QString, QDemonRef<QDemonCustomMaterialTextureData>> CustomMaterialTextureEntry; QDemonRenderContextInterface *context = nullptr; - StringMaterialMap stringMaterialMap; ShaderMap shaderMap; QVector<CustomMaterialTextureEntry> textureEntries; QVector<QDemonCustomMaterialBuffer> allocatedBuffers; - QVector<AllocatedImageEntry> allocatedImages; bool useFastBlits = true; QString shaderNameBuilder; QElapsedTimer lastFrameTime; float msSinceLastFrame = 0; void releaseBuffer(qint32 inIdx); - QDemonMaterialClass *getMaterialClass(const QString &inStr); - const QDemonMaterialClass *getMaterialClass(const QString &inStr) const; QDemonRef<QDemonRenderShaderProgram> getShader(QDemonCustomMaterialRenderContext &inRenderContext, const QDemonRenderCustomMaterial &inMaterial, @@ -105,20 +103,20 @@ private: const dynamic::QDemonBindShader &inCommand, const TShaderFeatureSet &inFeatureSet); - void doApplyInstanceValue(QDemonRenderCustomMaterial & /* inMaterial */, - quint8 *inDataPtr, - const QString &inPropertyName, + void doApplyInstanceValue(QDemonRenderCustomMaterial &inMaterial, + const QString &propertyName, + const QVariant &propertyValue, QDemonRenderShaderDataType inPropertyType, - const QDemonRef<QDemonRenderShaderProgram> &inShader, - const dynamic::QDemonPropertyDefinition &inDefinition); + const QDemonRef<QDemonRenderShaderProgram> &inShader); void applyInstanceValue(QDemonRenderCustomMaterial &inMaterial, - QDemonMaterialClass &inClass, const QDemonRef<QDemonRenderShaderProgram> &inShader, const dynamic::QDemonApplyInstanceValue &inCommand); void applyBlending(const dynamic::QDemonApplyBlending &inCommand); + void applyRenderStateValue(const dynamic::QDemonApplyRenderState &inCommand); + // we currently only bind a source texture const QDemonRef<QDemonRenderTexture2D> applyBufferValue(const QDemonRenderCustomMaterial &inMaterial, const QDemonRef<QDemonRenderShaderProgram> &inShader, @@ -146,44 +144,31 @@ private: quint32 inOffset); void doRenderCustomMaterial(QDemonCustomMaterialRenderContext &inRenderContext, const QDemonRenderCustomMaterial &inMaterial, - QDemonMaterialClass &inClass, const QDemonRef<QDemonRenderFrameBuffer> &inTarget, const TShaderFeatureSet &inFeatureSet); - void prepareTextureForRender(QDemonMaterialClass &inClass, QDemonRenderCustomMaterial &inMaterial); - void prepareDisplacementForRender(QDemonMaterialClass &inClass, QDemonRenderCustomMaterial &inMaterial); - void prepareMaterialForRender(QDemonMaterialClass &inClass, QDemonRenderCustomMaterial &inMaterial); + void prepareDisplacementForRender(QDemonRenderCustomMaterial &inMaterial); + void prepareMaterialForRender(QDemonRenderCustomMaterial &inMaterial); qint32 findBuffer(const QString &inName); - qint32 findAllocatedImage(const QString &inName); - bool textureNeedsMips(const dynamic::QDemonPropertyDefinition *inPropDec, QDemonRenderTexture2D *inTexture); + bool textureNeedsMips(const QDemonRenderCustomMaterial::TextureProperty *inPropDec, QDemonRenderTexture2D *inTexture); void setTexture(const QDemonRef<QDemonRenderShaderProgram> &inShader, const QString &inPropName, const QDemonRef<QDemonRenderTexture2D> &inTexture, - const dynamic::QDemonPropertyDefinition *inPropDec = nullptr, + const QDemonRenderCustomMaterial::TextureProperty *inPropDec = nullptr, bool needMips = false); public: QDemonMaterialSystem(QDemonRenderContextInterface *ct); ~QDemonMaterialSystem(); - bool isMaterialRegistered(const QString &inStr); - - bool registerMaterialClass(const QString &inName, const QDemonDataView<dynamic::QDemonPropertyDeclaration> &inProperties); - - QDemonDataView<dynamic::QDemonPropertyDefinition> getCustomMaterialProperties(const QString &inCustomMaterialName) const; - void setCustomMaterialRefraction(const QString &inName, bool inHasRefraction); - void setCustomMaterialTransparency(const QString &inName, bool inHasTransparency); - void setCustomMaterialAlwaysDirty(const QString &inName, bool inIsAlwaysDirty); - void setCustomMaterialShaderKey(const QString &inName, quint32 inShaderKey); - void setCustomMaterialLayerCount(const QString &inName, quint32 inLayerCount); // The custom material commands are the actual commands that run for a given material // effect. The tell the system exactly // explicitly things like bind this shader, bind this render target, apply this property, // run this shader // See UICRenderEffectCommands.h for the list of commands. // These commands are copied into the effect. - void setCustomMaterialCommands(QString inName, QDemonDataView<dynamic::QDemonCommand *> inCommands); +// void setCustomMaterialCommands(QString inName, QDemonDataView<dynamic::QDemonCommand *> inCommands); void setMaterialClassShader(QString inName, const QByteArray &inShaderType, @@ -192,18 +177,6 @@ public: bool inHasGeomShader, bool inIsComputeShader); - QDemonRenderCustomMaterial *createCustomMaterial(const QString &inName); - - void setPropertyEnumNames(const QString &inName, const QString &inPropName, const QDemonDataView<QString> &inNames); - - void setPropertyTextureSettings(const QString &inEffectName, - const QString &inPropName, - const QString &inPropPath, - QDemonRenderTextureTypeValue inTexType, - QDemonRenderTextureCoordOp inCoordOp, - QDemonRenderTextureMagnifyingOp inMagFilterOp, - QDemonRenderTextureMinifyingOp inMinFilterOp); - void setRenderContextInterface(QDemonRenderContextInterface *inContext); // Returns true if the material is dirty and thus will produce a different render result @@ -215,7 +188,6 @@ public: bool renderDepthPrepass(const QMatrix4x4 &inMVP, const QDemonRenderCustomMaterial &inMaterial, const QDemonRenderSubset &inSubset); void renderSubset(QDemonCustomMaterialRenderContext &inRenderContext, const TShaderFeatureSet &inFeatureSet); - void onMaterialActivationChange(const QDemonRenderCustomMaterial &inMaterial, bool inActive); // get shader name QString getShaderName(const QDemonRenderCustomMaterial &inMaterial); diff --git a/src/runtimerender/qdemonrenderdynamicobjectsystem.cpp b/src/runtimerender/qdemonrenderdynamicobjectsystem.cpp index 9a7fbde646589c147cf17ba6e9175414e85017a0..ecdc554930892b97156aa4fb69933a0621db5f58 100644 --- a/src/runtimerender/qdemonrenderdynamicobjectsystem.cpp +++ b/src/runtimerender/qdemonrenderdynamicobjectsystem.cpp @@ -30,7 +30,6 @@ #include "qdemonrenderdynamicobjectsystem.h" #include <QtDemonRuntimeRender/qdemonrendercontextcore.h> -#include <QtDemonRuntimeRender/qdemonrenderdynamicobject.h> #include <QtDemonRuntimeRender/qdemonrendershadercache.h> #include <QtDemonRuntimeRender/qdemonrenderinputstreamfactory.h> #include <QtDemonRuntimeRender/qdemonrenderer.h> @@ -178,197 +177,6 @@ void QDemonCommand::copyConstructCommand(quint8 *inDataBuffer, const QDemonComma } } -namespace { - -quint32 align(quint32 inValue) -{ - if (inValue % 4) - return inValue + (4 - (inValue % 4)); - return inValue; -} - -quint32 align8(quint32 inValue) -{ - if (inValue % 8) - return inValue + (8 - (inValue % 8)); - return inValue; -} - -inline const char *getShaderDatatypeName(QDemonRenderShaderDataType inValue) -{ - switch (inValue) { - case QDemonRenderShaderDataType::Unknown: - return ""; - case QDemonRenderShaderDataType::Integer: - return "qint32"; - case QDemonRenderShaderDataType::IntegerVec2: - return "qint32_2"; - case QDemonRenderShaderDataType::IntegerVec3: - return "qint32_3"; - case QDemonRenderShaderDataType::IntegerVec4: - return "qint32_4"; - case QDemonRenderShaderDataType::Boolean: - return "bool"; - case QDemonRenderShaderDataType::BooleanVec2: - return "bool_2"; - case QDemonRenderShaderDataType::BooleanVec3: - return "bool_3"; - case QDemonRenderShaderDataType::BooleanVec4: - return "bool_4"; - case QDemonRenderShaderDataType::Float: - return "float"; - case QDemonRenderShaderDataType::Vec2: - return "QVector2D"; - case QDemonRenderShaderDataType::Vec3: - return "QVector3D"; - case QDemonRenderShaderDataType::Vec4: - return "QVector4D"; - case QDemonRenderShaderDataType::UnsignedInteger: - return "quint32"; - case QDemonRenderShaderDataType::UnsignedIntegerVec2: - return "quint32_2"; - case QDemonRenderShaderDataType::UnsignedIntegerVec3: - return "quint32_3"; - case QDemonRenderShaderDataType::UnsignedIntegerVec4: - return "quint32_4"; - case QDemonRenderShaderDataType::Matrix3x3: - return "QMatrix3x3"; - case QDemonRenderShaderDataType::Matrix4x4: - return "QMatrix4x4"; - case QDemonRenderShaderDataType::Texture2D: - return "QDemonRenderTexture2DPtr"; - case QDemonRenderShaderDataType::Texture2DHandle: - return "QDemonRenderTexture2DHandle"; - case QDemonRenderShaderDataType::Texture2DArray: - return "QDemonRenderTexture2DArrayPtr"; - case QDemonRenderShaderDataType::TextureCube: - return "QDemonRenderTextureCubePtr"; - case QDemonRenderShaderDataType::TextureCubeHandle: - return "QDemonRenderTextureCubeHandle"; - case QDemonRenderShaderDataType::Image2D: - return "QDemonRenderImage2DPtr"; - case QDemonRenderShaderDataType::DataBuffer: - return "QDemonRenderDataBufferPtr"; - } - Q_ASSERT(false); - return ""; -} -} - -QDemonDynamicObjectClass::QDemonDynamicObjectClass(QString id, - QDemonDataView<dynamic::QDemonPropertyDefinition> definitions, - quint32 propertySectionByteSize, - quint32 baseObjectSize, - QDemonRenderGraphObject::Type objectType, - quint8 *propDefaultData, - bool inRequiresDepthTexture, - QDemonRenderTextureFormat inOutputFormat) - : m_id(id) - , m_propertyDefinitions(definitions) - , m_propertySectionByteSize(propertySectionByteSize) - , m_baseObjectSize(baseObjectSize) - , m_graphObjectType(objectType) - , m_propertyDefaultData(propDefaultData) - , m_requiresDepthTexture(inRequiresDepthTexture) - , m_requiresCompilation(false) - , m_outputFormat(inOutputFormat) -{ -} - -QDemonDynamicObjectClass::~QDemonDynamicObjectClass() -{ - if (m_propertyDefinitions.size()) { - for (quint32 idx = 0, end = m_propertyDefinitions.size(); idx < end; ++idx) { - if (m_propertyDefinitions[idx].enumValueNames.size()) // ### You can't free a QString like this! - ::free((void *)m_propertyDefinitions[idx].enumValueNames.begin()); - } - } - releaseCommands(); -} - -void QDemonDynamicObjectClass::releaseCommands() -{ - if (m_renderCommands.size()) { - ::free(const_cast<dynamic::QDemonCommand *>(*m_renderCommands.begin())); - m_renderCommands = QDemonDataView<dynamic::QDemonCommand *>(); - } -} - -QString QDemonDynamicObjectClass::getId() const -{ - return m_id; -} - -QDemonDataView<dynamic::QDemonPropertyDefinition> QDemonDynamicObjectClass::getProperties() const -{ - return m_propertyDefinitions; -} - -quint32 QDemonDynamicObjectClass::getPropertySectionByteSize() const -{ - return m_propertySectionByteSize; -} - -const quint8 *QDemonDynamicObjectClass::getDefaultValueBuffer() const -{ - return m_propertyDefaultData; -} - -quint32 QDemonDynamicObjectClass::getBaseObjectSize() const -{ - return m_baseObjectSize; -} - -QDemonRenderGraphObject::Type QDemonDynamicObjectClass::graphObjectType() const -{ - return m_graphObjectType; -} - -const dynamic::QDemonPropertyDefinition *QDemonDynamicObjectClass::findDefinition(QString &str) const -{ - for (quint32 idx = 0, end = m_propertyDefinitions.size(); idx < end; ++idx) { - const dynamic::QDemonPropertyDefinition &def(m_propertyDefinitions[idx]); - if (def.name == str) - return &def; - } - return nullptr; -} - -const dynamic::QDemonPropertyDefinition *QDemonDynamicObjectClass::findPropertyByName(QString inName) const -{ - return findDefinition(inName); -} - -QDemonDataView<dynamic::QDemonCommand *> QDemonDynamicObjectClass::getRenderCommands() const -{ - return m_renderCommands; -} - -bool QDemonDynamicObjectClass::requiresDepthTexture() const -{ - return m_requiresDepthTexture; -} - -void QDemonDynamicObjectClass::setRequiresDepthTexture(bool inVal) -{ - m_requiresDepthTexture = inVal; -} - -bool QDemonDynamicObjectClass::requiresCompilation() const -{ - return m_requiresCompilation; -} - -void QDemonDynamicObjectClass::setRequiresCompilation(bool inVal) -{ - m_requiresCompilation = inVal; -} - -QDemonRenderTextureFormat QDemonDynamicObjectClass::getOutputTextureFormat() const -{ - return m_outputFormat; -} - QString QDemonDynamicObjectSystem::getShaderCodeLibraryDirectory() { return QStringLiteral("res/effectlib"); @@ -385,226 +193,59 @@ QDemonDynamicObjectSystem::QDemonDynamicObjectSystem(QDemonRenderContextInterfac QDemonDynamicObjectSystem::~QDemonDynamicObjectSystem() {} -bool QDemonDynamicObjectSystem::isRegistered(QString inStr) -{ - return m_classes.find(inStr) != m_classes.end(); -} - -bool QDemonDynamicObjectSystem::doRegister(QString inName, - QDemonDataView<dynamic::QDemonPropertyDeclaration> inProperties, - quint32 inBaseObjectSize, - QDemonRenderGraphObject::Type inGraphObjectType) -{ - if (isRegistered(inName)) { - Q_ASSERT(false); - return false; - } - QVector<dynamic::QDemonPropertyDefinition> definitions; - quint32 theCurrentOffset = 0; - for (quint32 idx = 0, end = inProperties.size(); idx < end; ++idx) { - const dynamic::QDemonPropertyDeclaration &thePropDec = inProperties[idx]; - quint32 propSize = dynamic::getSizeofShaderDataType(thePropDec.dataType); - definitions.push_back(dynamic::QDemonPropertyDefinition(thePropDec.name, thePropDec.dataType, theCurrentOffset, propSize)); - theCurrentOffset += propSize; - theCurrentOffset = align(theCurrentOffset); - } - quint32 dataSectionSize = theCurrentOffset; - quint32 clsSize = align(sizeof(QDemonDynamicObjectClass)); - quint32 defSize = align(sizeof(dynamic::QDemonPropertyDefinition) * inProperties.size()); - quint32 defaultSize = dataSectionSize; - quint32 allocSize = clsSize + defSize + defaultSize; - quint8 *allocData = reinterpret_cast<quint8 *>(::malloc(allocSize)); - quint8 *defData = allocData + clsSize; - quint8 *defaultData = defData + defSize; - dynamic::QDemonPropertyDefinition *defPtr = reinterpret_cast<dynamic::QDemonPropertyDefinition *>(defData); - if (defSize) - ::memcpy(defPtr, definitions.data(), defSize); - if (defaultSize) - memset(defaultData, 0, defaultSize); - QDemonRef<QDemonDynamicObjectClass> theClass( - new (allocData) - QDemonDynamicObjectClass(inName, toDataView(defPtr, inProperties.size()), dataSectionSize, inBaseObjectSize, inGraphObjectType, defaultData)); - m_classes.insert(inName, theClass); - return true; -} - -bool QDemonDynamicObjectSystem::unregister(QString inName) -{ - if (!isRegistered(inName)) { - Q_ASSERT(false); - return false; - } - TStringClassMap::iterator iter = m_classes.find(inName); - if (iter != m_classes.end()) - m_classes.erase(iter); - return true; -} - -QDemonRef<QDemonDynamicObjectClass> QDemonDynamicObjectSystem::findClass(QString inName) -{ - TStringClassMap::iterator iter = m_classes.find(inName); - if (iter != m_classes.end()) - return iter.value(); - return nullptr; -} - -QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>> QDemonDynamicObjectSystem::findProperty(QString inName, QString inPropName) -{ - QDemonRef<QDemonDynamicObjectClass> cls = findClass(inName); - if (cls) { - const dynamic::QDemonPropertyDefinition *def = cls->findDefinition(inPropName); - if (def) - return QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>>(def, cls); - } - return QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>>(nullptr, nullptr); -} - -void QDemonDynamicObjectSystem::setPropertyDefaultValue(const QString &inName, const QString &inPropName, const QDemonByteView &inDefaultData) -{ - QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>> def = findProperty(inName, inPropName); - if (def.first && inDefaultData.size() >= qint32(def.first->byteSize)) { - ::memcpy(def.second->m_propertyDefaultData + def.first->offset, inDefaultData.begin(), def.first->byteSize); - } else { - Q_ASSERT(false); - } -} - -void QDemonDynamicObjectSystem::setPropertyEnumNames(const QString &inName, const QString &inPropName, const QDemonDataView<QString> &inNames) -{ - - QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>> def = findProperty(inName, inPropName); - dynamic::QDemonPropertyDefinition *theDefinitionPtr = const_cast<dynamic::QDemonPropertyDefinition *>(def.first); - if (theDefinitionPtr == nullptr) { - Q_ASSERT(false); - return; - } - if (theDefinitionPtr->enumValueNames.size()) { - ::free((void *)theDefinitionPtr->enumValueNames.begin()); - theDefinitionPtr->enumValueNames = QDemonDataView<QString>(); - } - theDefinitionPtr->isEnumProperty = true; - if (inNames.size()) { - // TODO: - QString *theNameValues = new QString[inName.size()]; - ::memcpy(theNameValues, inNames.begin(), inNames.size() * sizeof(QString)); - theDefinitionPtr->enumValueNames = QDemonDataView<QString>(theNameValues, inNames.size()); - } -} - -QDemonDataView<QString> QDemonDynamicObjectSystem::getPropertyEnumNames(const QString &inName, const QString &inPropName) const -{ - QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>> - def = const_cast<QDemonDynamicObjectSystem &>(*this).findProperty(inName, inPropName); - if (def.first) - return def.first->enumValueNames; - return QDemonDataView<QString>(); -} - -QDemonDataView<dynamic::QDemonPropertyDefinition> QDemonDynamicObjectSystem::getProperties(const QString &inName) const -{ - QMutexLocker locker(&m_propertyLoadMutex); - QDemonRef<QDemonDynamicObjectClass> cls = const_cast<QDemonDynamicObjectSystem &>(*this).findClass(inName); - if (cls) - return cls->m_propertyDefinitions; - return QDemonDataView<dynamic::QDemonPropertyDefinition>(); -} - -void QDemonDynamicObjectSystem::setPropertyTextureSettings(const QString &inName, - const QString &inPropName, - const QString &inPropPath, - QDemonRenderTextureTypeValue inTexType, - QDemonRenderTextureCoordOp inCoordOp, - QDemonRenderTextureMagnifyingOp inMagFilterOp, - QDemonRenderTextureMinifyingOp inMinFilterOp) -{ - QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>> def = findProperty(inName, inPropName); - dynamic::QDemonPropertyDefinition *theDefinitionPtr = const_cast<dynamic::QDemonPropertyDefinition *>(def.first); - if (theDefinitionPtr == nullptr) { - Q_ASSERT(false); - return; - } - QByteArray *data = new QByteArray(inPropPath.toLatin1()); - theDefinitionPtr->imagePath = data->constData(); // inPropPath.toLatin1().constData(); // TODO: Lifetime - theDefinitionPtr->texUsageType = inTexType; - theDefinitionPtr->coordOp = inCoordOp; - theDefinitionPtr->magFilterOp = inMagFilterOp; - theDefinitionPtr->minFilterOp = inMinFilterOp; -} - -QDemonDynamicObjectClass *QDemonDynamicObjectSystem::dynamicObjectClass(const QString &inName) -{ - // TODO: Should probably shared pointer - return findClass(inName).data(); -} - void QDemonDynamicObjectSystem::setRenderCommands(const QString &inClassName, const QDemonDataView<dynamic::QDemonCommand *> &inCommands) { - QDemonRef<QDemonDynamicObjectClass> theClass = const_cast<QDemonDynamicObjectSystem &>(*this).findClass(inClassName); - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - theClass->releaseCommands(); - quint32 commandAllocationSize = 0; - for (quint32 idx = 0, end = inCommands.size(); idx < end; ++idx) { - quint32 commandSize = align(dynamic::QDemonCommand::getSizeofCommand(*inCommands[idx])); - commandAllocationSize += commandSize; - } - quint32 commandPtrSize = inCommands.size() * sizeof(dynamic::QDemonCommand *); - quint32 totalAllocationSize = align8(commandAllocationSize) + commandPtrSize; - quint8 *theCommandDataBegin = (quint8 *)::malloc(totalAllocationSize); - quint8 *theCurrentCommandData(theCommandDataBegin); - dynamic::QDemonCommand **theCommandPtrBegin = reinterpret_cast<dynamic::QDemonCommand **>( - theCommandDataBegin + align8(commandAllocationSize)); - dynamic::QDemonCommand **theCurrentCommandPtr = theCommandPtrBegin; - memset(theCommandDataBegin, 0, totalAllocationSize); - - theClass->m_requiresDepthTexture = false; - for (quint32 idx = 0, end = inCommands.size(); idx < end; ++idx) { - dynamic::QDemonCommand &theCommand(*inCommands[idx]); - quint32 theCommandSize = dynamic::QDemonCommand::getSizeofCommand(theCommand); - dynamic::QDemonCommand::copyConstructCommand(theCurrentCommandData, theCommand); - if (theCommand.m_type == dynamic::CommandType::ApplyDepthValue) - theClass->m_requiresDepthTexture = true; - if (theCommand.m_type == dynamic::CommandType::BindTarget) { - dynamic::QDemonBindTarget *bt = reinterpret_cast<dynamic::QDemonBindTarget *>(&theCommand); - theClass->m_outputFormat = bt->m_outputFormat; - } - - *theCurrentCommandPtr = reinterpret_cast<dynamic::QDemonCommand *>(theCurrentCommandData); - ++theCurrentCommandPtr; - theCurrentCommandData += align(theCommandSize); - } - Q_ASSERT(theCurrentCommandData - theCommandDataBegin == (int)commandAllocationSize); - Q_ASSERT((quint8 *)theCurrentCommandPtr - theCommandDataBegin == (int)totalAllocationSize); - theClass->m_renderCommands = QDemonDataView<dynamic::QDemonCommand *>(theCommandPtrBegin, inCommands.size()); + Q_UNUSED(inClassName) + Q_UNUSED(inCommands) +// QDemonRef<QDemonDynamicObjectClass> theClass = nullptr;// = const_cast<QDemonDynamicObjectSystem &>(*this).findClass(inClassName); +// if (theClass == nullptr) { +// Q_ASSERT(false); +// return; +// } +// theClass->releaseCommands(); +// quint32 commandAllocationSize = 0; +// for (quint32 idx = 0, end = inCommands.size(); idx < end; ++idx) { +// quint32 commandSize = align(dynamic::QDemonCommand::getSizeofCommand(*inCommands[idx])); +// commandAllocationSize += commandSize; +// } +// quint32 commandPtrSize = inCommands.size() * sizeof(dynamic::QDemonCommand *); +// quint32 totalAllocationSize = align8(commandAllocationSize) + commandPtrSize; +// quint8 *theCommandDataBegin = (quint8 *)::malloc(totalAllocationSize); +// quint8 *theCurrentCommandData(theCommandDataBegin); +// dynamic::QDemonCommand **theCommandPtrBegin = reinterpret_cast<dynamic::QDemonCommand **>( +// theCommandDataBegin + align8(commandAllocationSize)); +// dynamic::QDemonCommand **theCurrentCommandPtr = theCommandPtrBegin; +// memset(theCommandDataBegin, 0, totalAllocationSize); + +// theClass->m_requiresDepthTexture = false; +// for (quint32 idx = 0, end = inCommands.size(); idx < end; ++idx) { +// dynamic::QDemonCommand &theCommand(*inCommands[idx]); +// quint32 theCommandSize = dynamic::QDemonCommand::getSizeofCommand(theCommand); +// dynamic::QDemonCommand::copyConstructCommand(theCurrentCommandData, theCommand); +// if (theCommand.m_type == dynamic::CommandType::ApplyDepthValue) +// theClass->m_requiresDepthTexture = true; +// if (theCommand.m_type == dynamic::CommandType::BindTarget) { +// dynamic::QDemonBindTarget *bt = reinterpret_cast<dynamic::QDemonBindTarget *>(&theCommand); +// theClass->m_outputFormat = bt->m_outputFormat; +// } + +// *theCurrentCommandPtr = reinterpret_cast<dynamic::QDemonCommand *>(theCurrentCommandData); +// ++theCurrentCommandPtr; +// theCurrentCommandData += align(theCommandSize); +// } +// Q_ASSERT(theCurrentCommandData - theCommandDataBegin == (int)commandAllocationSize); +// Q_ASSERT((quint8 *)theCurrentCommandPtr - theCommandDataBegin == (int)totalAllocationSize); +// theClass->m_renderCommands = QDemonDataView<dynamic::QDemonCommand *>(theCommandPtrBegin, inCommands.size()); } QDemonDataView<dynamic::QDemonCommand *> QDemonDynamicObjectSystem::getRenderCommands(const QString &inClassName) const { - QDemonRef<QDemonDynamicObjectClass> cls = const_cast<QDemonDynamicObjectSystem &>(*this).findClass(inClassName); - if (cls) - return cls->m_renderCommands; +// QDemonRef<QDemonDynamicObjectClass> cls = nullptr; //const_cast<QDemonDynamicObjectSystem &>(*this).findClass(inClassName); +// if (cls) +// return cls->m_renderCommands; return QDemonDataView<dynamic::QDemonCommand *>(); } -QDemonRenderDynamicGraphObject *QDemonDynamicObjectSystem::createInstance(const QString &inClassName) -{ - QDemonRef<QDemonDynamicObjectClass> theClass = findClass(inClassName); - if (!theClass) { - Q_ASSERT(false); - return nullptr; - } - quint32 totalObjectSize = theClass->m_baseObjectSize + theClass->m_propertySectionByteSize; - QDemonRenderDynamicGraphObject *retval = reinterpret_cast<QDemonRenderDynamicGraphObject *>(::malloc(totalObjectSize)); - new (retval) QDemonRenderDynamicGraphObject(theClass->m_graphObjectType, - inClassName, - theClass->m_propertySectionByteSize, - theClass->m_baseObjectSize); - ::memcpy(retval->getDataSectionBegin(), theClass->m_propertyDefaultData, theClass->m_propertySectionByteSize); - return retval; -} - void QDemonDynamicObjectSystem::setShaderData(const QString &inPath, const QByteArray &inData, const QByteArray &inShaderType, diff --git a/src/runtimerender/qdemonrenderdynamicobjectsystem.h b/src/runtimerender/qdemonrenderdynamicobjectsystem.h index 2b27dfb7bbf03b47103c1a1bd91ffbd64a5a706d..3f39f14854f3897e85596c22c7e1ccc91c480b94 100644 --- a/src/runtimerender/qdemonrenderdynamicobjectsystem.h +++ b/src/runtimerender/qdemonrenderdynamicobjectsystem.h @@ -170,61 +170,18 @@ struct QDemonDynamicObjectShaderInfo } }; -struct QDemonDynamicObjectClass -{ - QAtomicInt ref; - QString m_id; - QDemonDataView<dynamic::QDemonPropertyDefinition> m_propertyDefinitions; - quint32 m_propertySectionByteSize; - quint32 m_baseObjectSize; - QDemonRenderGraphObject::Type m_graphObjectType; - quint8 *m_propertyDefaultData; - QDemonDataView<dynamic::QDemonCommand *> m_renderCommands; - bool m_requiresDepthTexture; - bool m_requiresCompilation; - QDemonRenderTextureFormat m_outputFormat; - - QDemonDynamicObjectClass(QString id, - QDemonDataView<dynamic::QDemonPropertyDefinition> definitions, - quint32 propertySectionByteSize, - quint32 baseObjectSize, - QDemonRenderGraphObject::Type objectType, - quint8 *propDefaultData, - bool inRequiresDepthTexture = false, - QDemonRenderTextureFormat inOutputFormat = QDemonRenderTextureFormat::RGBA8); - - ~QDemonDynamicObjectClass(); - - void releaseCommands(); - - QString getId() const; - QDemonDataView<dynamic::QDemonPropertyDefinition> getProperties() const; - quint32 getPropertySectionByteSize() const; - const quint8 *getDefaultValueBuffer() const; - quint32 getBaseObjectSize() const; - QDemonRenderGraphObject::Type graphObjectType() const; - const dynamic::QDemonPropertyDefinition *findDefinition(QString &str) const; - const dynamic::QDemonPropertyDefinition *findPropertyByName(QString inName) const; - QDemonDataView<dynamic::QDemonCommand *> getRenderCommands() const; - bool requiresDepthTexture() const; - void setRequiresDepthTexture(bool inVal); - bool requiresCompilation() const; - void setRequiresCompilation(bool inVal); - QDemonRenderTextureFormat getOutputTextureFormat() const; -}; - typedef QPair<QDemonRef<QDemonRenderShaderProgram>, dynamic::QDemonDynamicShaderProgramFlags> TShaderAndFlags; struct QDemonDynamicObjectSystem { - typedef QHash<QString, QDemonRef<QDemonDynamicObjectClass>> TStringClassMap; +// typedef QHash<QString, QDemonRef<QDemonDynamicObjectClass>> TStringClassMap; typedef QHash<QString, QByteArray> TPathDataMap; typedef QHash<QString, QDemonDynamicObjectShaderInfo> TShaderInfoMap; typedef QSet<QString> TPathSet; typedef QHash<dynamic::QDemonDynamicShaderMapKey, TShaderAndFlags> TShaderMap; QDemonRenderContextInterface *m_context; - TStringClassMap m_classes; +// TStringClassMap m_classes; TPathDataMap m_expandedFiles; TShaderMap m_shaderMap; TShaderInfoMap m_shaderInfoMap; @@ -242,44 +199,10 @@ struct QDemonDynamicObjectSystem ~QDemonDynamicObjectSystem(); - bool isRegistered(QString inStr); - - bool doRegister(QString inName, - QDemonDataView<dynamic::QDemonPropertyDeclaration> inProperties, - quint32 inBaseObjectSize, - QDemonRenderGraphObject::Type inGraphObjectType); - - bool unregister(QString inName); - - QDemonRef<QDemonDynamicObjectClass> findClass(QString inName); - - QPair<const dynamic::QDemonPropertyDefinition *, QDemonRef<QDemonDynamicObjectClass>> findProperty(QString inName, QString inPropName); - - void setPropertyDefaultValue(const QString &inName, const QString &inPropName, const QDemonByteView &inDefaultData); - - void setPropertyEnumNames(const QString &inName, const QString &inPropName, const QDemonDataView<QString> &inNames); - - QDemonDataView<QString> getPropertyEnumNames(const QString &inName, const QString &inPropName) const; - - // Called during loading which is pretty heavily multithreaded. - QDemonDataView<dynamic::QDemonPropertyDefinition> getProperties(const QString &inName) const; - - void setPropertyTextureSettings(const QString &inName, - const QString &inPropName, - const QString &inPropPath, - QDemonRenderTextureTypeValue inTexType, - QDemonRenderTextureCoordOp inCoordOp, - QDemonRenderTextureMagnifyingOp inMagFilterOp, - QDemonRenderTextureMinifyingOp inMinFilterOp); - - QDemonDynamicObjectClass *dynamicObjectClass(const QString &inName); - void setRenderCommands(const QString &inClassName, const QDemonDataView<dynamic::QDemonCommand *> &inCommands); QDemonDataView<dynamic::QDemonCommand *> getRenderCommands(const QString &inClassName) const; - QDemonRenderDynamicGraphObject *createInstance(const QString &inClassName); - void setShaderData(const QString &inPath, const QByteArray &inData, const QByteArray &inShaderType, diff --git a/src/runtimerender/qdemonrenderdynamicobjectsystemcommands.h b/src/runtimerender/qdemonrenderdynamicobjectsystemcommands.h index c0af800f9cabbff03f51a4ecb98a27cf264c937e..89c2d997ed931441157fd4e3f8a51192fb3a3c23 100644 --- a/src/runtimerender/qdemonrenderdynamicobjectsystemcommands.h +++ b/src/runtimerender/qdemonrenderdynamicobjectsystemcommands.h @@ -291,12 +291,12 @@ struct QDemonApplyBufferValue : public QDemonCommand { // If no buffer name is given then the special buffer [source] // is assumed. - QString m_bufferName; + QByteArray m_bufferName; // If no param name is given, the buffer is bound to the // input texture parameter (texture0). - QString m_paramName; + QByteArray m_paramName; - QDemonApplyBufferValue(QString bufferName, QString shaderParam) + QDemonApplyBufferValue(const QByteArray &bufferName, const QByteArray &shaderParam) : QDemonCommand(CommandType::ApplyBufferValue), m_bufferName(bufferName), m_paramName(shaderParam) { } @@ -407,12 +407,12 @@ struct QDemonApplyBlitFramebuffer : public QDemonCommand { // If no buffer name is given then the special buffer [source] // is assumed. Which is the default render target - QString m_sourceBufferName; + QByteArray m_sourceBufferName; // If no buffer name is given then the special buffer [dest] // is assumed. Which is the default render target - QString m_destBufferName; + QByteArray m_destBufferName; - QDemonApplyBlitFramebuffer(QString inSourceBufferName, QString inDestBufferName) + QDemonApplyBlitFramebuffer(const QByteArray &inSourceBufferName, const QByteArray &inDestBufferName) : QDemonCommand(CommandType::ApplyBlitFramebuffer), m_sourceBufferName(inSourceBufferName), m_destBufferName(inDestBufferName) { } diff --git a/src/runtimerender/qdemonrendereffectsystem.cpp b/src/runtimerender/qdemonrendereffectsystem.cpp index 57cbb87f3a7483b381386fae85e95accfed9e6a9..c4c48bb6b8f64963f3ec4dfbdc844fe49b73ee4d 100644 --- a/src/runtimerender/qdemonrendereffectsystem.cpp +++ b/src/runtimerender/qdemonrendereffectsystem.cpp @@ -443,8 +443,8 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface QDemonEffectContext &getEffectContext(QDemonRenderEffect &inEffect) { if (inEffect.m_context == nullptr) { - inEffect.m_context = QDemonRef<QDemonEffectContext>(new QDemonEffectContext(inEffect.className, m_context, m_resourceManager)); - m_contexts.push_back(inEffect.m_context); +// inEffect.m_context = QDemonRef<QDemonEffectContext>(new QDemonEffectContext(inEffect.className, m_context, m_resourceManager)); +// m_contexts.push_back(inEffect.m_context); } return *inEffect.m_context; } @@ -471,129 +471,132 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface } // Registers an effect that runs via a single GLSL file. - bool registerGLSLEffect(QString inName, const char *inPathToEffect, QDemonDataView<QDemonPropertyDeclaration> inProperties) override - { - if (isEffectRegistered(inName)) - return false; - - m_context->dynamicObjectSystem()->doRegister(inName, inProperties, sizeof(QDemonRenderEffect), QDemonRenderGraphObject::Type::Effect); - QDemonDynamicObjectClass &theClass = *m_context->dynamicObjectSystem()->dynamicObjectClass(inName); - - QDemonRef<QDemonEffectClass> theEffect(new QDemonEffectClass(theClass)); - m_effectClasses.insert(inName, theEffect); - - // Setup the commands required to run this effect - // StaticAssert<(sizeof(SBindShader) % 4 == 0)>::valid_expression(); - // StaticAssert<(sizeof(SApplyInstanceValue) % 4 == 0)>::valid_expression(); - // StaticAssert<(sizeof(SRender) % 4 == 0)>::valid_expression(); - - quint32 commandAllocationSize = sizeof(QDemonBindTarget); - commandAllocationSize += sizeof(QDemonBindShader); - commandAllocationSize += sizeof(QDemonApplyInstanceValue) * inProperties.size(); - commandAllocationSize += sizeof(QDemonRender); - - quint32 commandCount = 3 + inProperties.size(); - quint32 commandPtrAllocationSize = commandCount * sizeof(QDemonCommand *); - quint32 allocationSize = align8(commandAllocationSize) + commandPtrAllocationSize; - quint8 *startBuffer = (quint8 *)::malloc(allocationSize); - quint8 *dataBuffer = startBuffer; - // Setup the command buffer such that the ptrs to the commands and the commands themselves - // are - // all in the same block of memory. This enables quicker iteration (trivially quicker, most - // likely) - // but it also enables simpler memory management (single free). - // Furthermore, for a single glsl file the effect properties map precisely into the - // glsl file itself. - QDemonCommand **theFirstCommandPtr = (reinterpret_cast<QDemonCommand **>(dataBuffer + align8(commandAllocationSize))); - QDemonCommand **theCommandPtr = theFirstCommandPtr; - memset(dataBuffer, 0, commandAllocationSize); - - new (dataBuffer) QDemonBindTarget(); - *theCommandPtr = (QDemonCommand *)dataBuffer; - ++theCommandPtr; - dataBuffer += sizeof(QDemonBindTarget); - - new (dataBuffer) QDemonBindShader(QString::fromLocal8Bit(inPathToEffect)); - *theCommandPtr = (QDemonCommand *)dataBuffer; - ++theCommandPtr; - dataBuffer += sizeof(QDemonBindShader); - - for (quint32 idx = 0, end = inProperties.size(); idx < end; ++idx) { - const QDemonPropertyDefinition &theDefinition(theEffect->dynamicClass->getProperties()[idx]); - new (dataBuffer) QDemonApplyInstanceValue(theDefinition.name, theDefinition.dataType, theDefinition.offset); - *theCommandPtr = (QDemonCommand *)dataBuffer; - ++theCommandPtr; - dataBuffer += sizeof(QDemonApplyInstanceValue); - } - new (dataBuffer) QDemonRender(false); - *theCommandPtr = (QDemonCommand *)dataBuffer; - ++theCommandPtr; - dataBuffer += sizeof(QDemonRender); - // Ensure we end up *exactly* where we expected to. - Q_ASSERT(dataBuffer == startBuffer + commandAllocationSize); - Q_ASSERT(theCommandPtr - theFirstCommandPtr == (int)inProperties.size() + 3); - m_context->dynamicObjectSystem()->setRenderCommands(inName, QDemonDataView<QDemonCommand *>(theFirstCommandPtr, commandCount)); - ::free(startBuffer); - return true; + bool registerGLSLEffect(QString /*inName*/, const char */*inPathToEffect*/, QDemonDataView<QDemonPropertyDeclaration> /*inProperties*/) override + { +// if (isEffectRegistered(inName)) +// return false; + +//// m_context->dynamicObjectSystem()->doRegister(inName, inProperties, sizeof(QDemonRenderEffect), QDemonRenderGraphObject::Type::Effect); +//// QDemonDynamicObjectClass &theClass = *m_context->dynamicObjectSystem()->dynamicObjectClass(inName); + +// QDemonRef<QDemonEffectClass> theEffect(new QDemonEffectClass(theClass)); +// m_effectClasses.insert(inName, theEffect); + +// // Setup the commands required to run this effect +// // StaticAssert<(sizeof(SBindShader) % 4 == 0)>::valid_expression(); +// // StaticAssert<(sizeof(SApplyInstanceValue) % 4 == 0)>::valid_expression(); +// // StaticAssert<(sizeof(SRender) % 4 == 0)>::valid_expression(); + +// quint32 commandAllocationSize = sizeof(QDemonBindTarget); +// commandAllocationSize += sizeof(QDemonBindShader); +// commandAllocationSize += sizeof(QDemonApplyInstanceValue) * inProperties.size(); +// commandAllocationSize += sizeof(QDemonRender); + +// quint32 commandCount = 3 + inProperties.size(); +// quint32 commandPtrAllocationSize = commandCount * sizeof(QDemonCommand *); +// quint32 allocationSize = align8(commandAllocationSize) + commandPtrAllocationSize; +// quint8 *startBuffer = (quint8 *)::malloc(allocationSize); +// quint8 *dataBuffer = startBuffer; +// // Setup the command buffer such that the ptrs to the commands and the commands themselves +// // are +// // all in the same block of memory. This enables quicker iteration (trivially quicker, most +// // likely) +// // but it also enables simpler memory management (single free). +// // Furthermore, for a single glsl file the effect properties map precisely into the +// // glsl file itself. +// QDemonCommand **theFirstCommandPtr = (reinterpret_cast<QDemonCommand **>(dataBuffer + align8(commandAllocationSize))); +// QDemonCommand **theCommandPtr = theFirstCommandPtr; +// memset(dataBuffer, 0, commandAllocationSize); + +// new (dataBuffer) QDemonBindTarget(); +// *theCommandPtr = (QDemonCommand *)dataBuffer; +// ++theCommandPtr; +// dataBuffer += sizeof(QDemonBindTarget); + +// new (dataBuffer) QDemonBindShader(QString::fromLocal8Bit(inPathToEffect)); +// *theCommandPtr = (QDemonCommand *)dataBuffer; +// ++theCommandPtr; +// dataBuffer += sizeof(QDemonBindShader); + +// for (quint32 idx = 0, end = inProperties.size(); idx < end; ++idx) { +// const QDemonPropertyDefinition &theDefinition(theEffect->dynamicClass->getProperties()[idx]); +// new (dataBuffer) QDemonApplyInstanceValue(theDefinition.name, theDefinition.dataType, theDefinition.offset); +// *theCommandPtr = (QDemonCommand *)dataBuffer; +// ++theCommandPtr; +// dataBuffer += sizeof(QDemonApplyInstanceValue); +// } +// new (dataBuffer) QDemonRender(false); +// *theCommandPtr = (QDemonCommand *)dataBuffer; +// ++theCommandPtr; +// dataBuffer += sizeof(QDemonRender); +// // Ensure we end up *exactly* where we expected to. +// Q_ASSERT(dataBuffer == startBuffer + commandAllocationSize); +// Q_ASSERT(theCommandPtr - theFirstCommandPtr == (int)inProperties.size() + 3); +// m_context->dynamicObjectSystem()->setRenderCommands(inName, QDemonDataView<QDemonCommand *>(theFirstCommandPtr, commandCount)); +// ::free(startBuffer); +// return true; + return false; } void setEffectPropertyDefaultValue(QString inName, QString inPropName, QDemonByteView inDefaultData) override { - m_context->dynamicObjectSystem()->setPropertyDefaultValue(inName, inPropName, inDefaultData); +// m_context->dynamicObjectSystem()->setPropertyDefaultValue(inName, inPropName, inDefaultData); } void setEffectPropertyEnumNames(QString inName, QString inPropName, QDemonDataView<QString> inNames) override { - m_context->dynamicObjectSystem()->setPropertyEnumNames(inName, inPropName, inNames); +// m_context->dynamicObjectSystem()->setPropertyEnumNames(inName, inPropName, inNames); } bool registerEffect(QString inName, QDemonDataView<QDemonPropertyDeclaration> inProperties) override { - if (isEffectRegistered(inName)) - return false; - m_context->dynamicObjectSystem()->doRegister(inName, inProperties, sizeof(QDemonRenderEffect), QDemonRenderGraphObject::Type::Effect); - auto theClass = m_context->dynamicObjectSystem()->dynamicObjectClass(inName); - QDemonRef<QDemonEffectClass> theEffect(new QDemonEffectClass(*theClass)); - m_effectClasses.insert(inName, theEffect); - return true; +// if (isEffectRegistered(inName)) +// return false; +// m_context->dynamicObjectSystem()->doRegister(inName, inProperties, sizeof(QDemonRenderEffect), QDemonRenderGraphObject::Type::Effect); +// auto theClass = m_context->dynamicObjectSystem()->dynamicObjectClass(inName); +// QDemonRef<QDemonEffectClass> theEffect(new QDemonEffectClass(*theClass)); +// m_effectClasses.insert(inName, theEffect); +// return true; + return false; } bool unregisterEffect(QString inName) override { - if (!isEffectRegistered(inName)) - return false; +// if (!isEffectRegistered(inName)) +// return false; - m_context->dynamicObjectSystem()->unregister(inName); +// m_context->dynamicObjectSystem()->unregister(inName); - TEffectClassMap::iterator iter = m_effectClasses.find(inName); - if (iter != m_effectClasses.end()) - m_effectClasses.erase(iter); +// TEffectClassMap::iterator iter = m_effectClasses.find(inName); +// if (iter != m_effectClasses.end()) +// m_effectClasses.erase(iter); - for (quint32 idx = 0, end = m_contexts.size(); idx < end; ++idx) { - if (m_contexts[idx]->m_className == inName) - releaseEffectContext(m_contexts[idx].data()); - } - return true; +// for (quint32 idx = 0, end = m_contexts.size(); idx < end; ++idx) { +// if (m_contexts[idx]->m_className == inName) +// releaseEffectContext(m_contexts[idx].data()); +// } +// return true; + return false; } QDemonDataView<QString> getEffectPropertyEnumNames(QString inName, QString inPropName) const override { - const auto theClass = getEffectClass(inName); - if (theClass == nullptr) { - Q_ASSERT(false); - QDemonDataView<QString>(); - } - const QDemonPropertyDefinition *theDefinitionPtr = theClass->dynamicClass->findPropertyByName(inPropName); - if (theDefinitionPtr) - return theDefinitionPtr->enumValueNames; +// const auto theClass = getEffectClass(inName); +// if (theClass == nullptr) { +// Q_ASSERT(false); +// QDemonDataView<QString>(); +// } +// const QDemonPropertyDefinition *theDefinitionPtr = theClass->dynamicClass->findPropertyByName(inPropName); +// if (theDefinitionPtr) +// return theDefinitionPtr->enumValueNames; return QDemonDataView<QString>(); } QDemonDataView<QDemonPropertyDefinition> getEffectProperties(QString inEffectName) const override { - const auto theClass = getEffectClass(inEffectName); - if (theClass) - return theClass->dynamicClass->getProperties(); +// const auto theClass = getEffectClass(inEffectName); +// if (theClass) +// return theClass->dynamicClass->getProperties(); return QDemonDataView<QDemonPropertyDefinition>(); } @@ -605,58 +608,60 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface QDemonRenderTextureMagnifyingOp inMagFilterOp, QDemonRenderTextureMinifyingOp inMinFilterOp) override { - m_context->dynamicObjectSystem() - ->setPropertyTextureSettings(inName, inPropName, inPropPath, inTexType, inCoordOp, inMagFilterOp, inMinFilterOp); +// m_context->dynamicObjectSystem() +// ->setPropertyTextureSettings(inName, inPropName, inPropPath, inTexType, inCoordOp, inMagFilterOp, inMinFilterOp); } void setEffectRequiresDepthTexture(QString inEffectName, bool inValue) override { - auto theClass = getEffectClass(inEffectName); - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - theClass->dynamicClass->setRequiresDepthTexture(inValue); +// auto theClass = getEffectClass(inEffectName); +// if (theClass == nullptr) { +// Q_ASSERT(false); +// return; +// } +// theClass->dynamicClass->setRequiresDepthTexture(inValue); } bool doesEffectRequireDepthTexture(QString inEffectName) const override { - const auto theClass = getEffectClass(inEffectName); - if (theClass == nullptr) { - Q_ASSERT(false); - return false; - } - return theClass->dynamicClass->requiresDepthTexture(); + // const auto theClass = getEffectClass(inEffectName); + // if (theClass == nullptr) { + // Q_ASSERT(false); + // return false; + // } + // return theClass->dynamicClass->requiresDepthTexture(); + return false; } void setEffectRequiresCompilation(QString inEffectName, bool inValue) override { - auto theClass = getEffectClass(inEffectName); - if (theClass == nullptr) { - Q_ASSERT(false); - return; - } - theClass->dynamicClass->setRequiresCompilation(inValue); +// auto theClass = getEffectClass(inEffectName); +// if (theClass == nullptr) { +// Q_ASSERT(false); +// return; +// } +// theClass->dynamicClass->setRequiresCompilation(inValue); } bool doesEffectRequireCompilation(QString inEffectName) const override { - const auto theClass = getEffectClass(inEffectName); - if (theClass == nullptr) { - Q_ASSERT(false); - return false; - } - return theClass->dynamicClass->requiresCompilation(); + // const auto theClass = getEffectClass(inEffectName); + // if (theClass == nullptr) { + // Q_ASSERT(false); + // return false; + // } + // return theClass->dynamicClass->requiresCompilation(); + return false; } void setEffectCommands(QString inEffectName, QDemonDataView<dynamic::QDemonCommand *> inCommands) override { - m_context->dynamicObjectSystem()->setRenderCommands(inEffectName, inCommands); +// m_context->dynamicObjectSystem()->setRenderCommands(inEffectName, inCommands); } QDemonDataView<dynamic::QDemonCommand *> getEffectCommands(QString inEffectName) const override { - return m_context->dynamicObjectSystem()->getRenderCommands(inEffectName); + return QDemonDataView<dynamic::QDemonCommand *>();/*m_context->dynamicObjectSystem()->getRenderCommands(inEffectName);*/ } QDemonRenderEffect *createEffectInstance(QString inEffectName) override @@ -666,10 +671,11 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface return nullptr; // StaticAssert<(sizeof(SEffect) % 4 == 0)>::valid_expression(); - QDemonRenderEffect *theEffect = static_cast<QDemonRenderEffect *>( - m_context->dynamicObjectSystem()->createInstance(inEffectName)); - theEffect->initialize(); - return theEffect; +// QDemonRenderEffect *theEffect = static_cast<QDemonRenderEffect *>( +// m_context->dynamicObjectSystem()->createInstance(inEffectName)); +// theEffect->initialize(); +// return theEffect; + return nullptr; } void allocateBuffer(QDemonRenderEffect &inEffect, @@ -852,7 +858,7 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface if (theBuffer == nullptr) { qCCritical(INVALID_OPERATION, "Effect %s: Failed to find buffer %s for bind", - inEffect.className.toLatin1().constData(), + inEffect.className, inCommand.m_bufferName.toLatin1().constData()); QString errorMsg = QObject::tr("Failed to compile \"%1\" effect.\nConsider" " removing it from the presentation.") @@ -873,39 +879,40 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface return theBuffer; } - QDemonRef<QDemonEffectShader> bindShader(QString &inEffectId, const QDemonBindShader &inCommand) - { - auto theClass = getEffectClass(inEffectId); - if (!theClass) { - Q_ASSERT(false); - return nullptr; - } - - bool forceCompilation = theClass->dynamicClass->requiresCompilation(); - - auto key = TStrStrPair(inCommand.m_shaderPath, inCommand.m_shaderDefine); - auto theInsertResult = m_shaderMap.find(key); - const bool found = (theInsertResult != m_shaderMap.end()); - if (!found) - theInsertResult = m_shaderMap.insert(key, QDemonRef<QDemonEffectShader>()); - - if (found || forceCompilation) { - auto theProgram = m_context->dynamicObjectSystem() - ->getShaderProgram(inCommand.m_shaderPath, - inCommand.m_shaderDefine, - TShaderFeatureSet(), - QDemonDynamicShaderProgramFlags(), - forceCompilation) - .first; - if (theProgram) - theInsertResult.value() = QDemonRef<QDemonEffectShader>(new QDemonEffectShader(theProgram)); - } - if (theInsertResult.value()) { - auto theContext(m_context->renderContext()); - theContext->setActiveShader(theInsertResult.value()->m_shader); - } - - return theInsertResult.value(); + QDemonRef<QDemonEffectShader> bindShader(const QString &inEffectId, const QDemonBindShader &inCommand) + { +// auto theClass = getEffectClass(inEffectId); +// if (!theClass) { +// Q_ASSERT(false); +// return nullptr; +// } + +// bool forceCompilation = theClass->dynamicClass->requiresCompilation(); + +// auto key = TStrStrPair(inCommand.m_shaderPath, inCommand.m_shaderDefine); +// auto theInsertResult = m_shaderMap.find(key); +// const bool found = (theInsertResult != m_shaderMap.end()); +// if (!found) +// theInsertResult = m_shaderMap.insert(key, QDemonRef<QDemonEffectShader>()); + +// if (found || forceCompilation) { +// auto theProgram = m_context->dynamicObjectSystem() +// ->getShaderProgram(inCommand.m_shaderPath, +// inCommand.m_shaderDefine, +// TShaderFeatureSet(), +// QDemonDynamicShaderProgramFlags(), +// forceCompilation) +// .first; +// if (theProgram) +// theInsertResult.value() = QDemonRef<QDemonEffectShader>(new QDemonEffectShader(theProgram)); +// } +// if (theInsertResult.value()) { +// auto theContext(m_context->renderContext()); +// theContext->setActiveShader(theInsertResult.value()->m_shader); +// } + +// return theInsertResult.value(); + return nullptr; } void doApplyInstanceValue(QDemonRenderEffect *inEffect, @@ -1054,29 +1061,29 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface const QDemonApplyInstanceValue &inCommand) { // sanity check - if (!inCommand.m_propertyName.isEmpty()) { - bool canGetData = inCommand.m_valueOffset + getSizeofShaderDataType(inCommand.m_valueType) <= inEffect->dataSectionByteSize; - if (canGetData == false) { - Q_ASSERT(false); - return; - } - quint8 *dataPtr = inEffect->getDataSectionBegin() + inCommand.m_valueOffset; - const QDemonPropertyDefinition *theDefinition = inClass->dynamicClass->findPropertyByName(inCommand.m_propertyName); - if (theDefinition) - doApplyInstanceValue(inEffect, dataPtr, inCommand.m_propertyName, inCommand.m_valueType, inShader, *theDefinition); - } else { - QDemonDataView<QDemonPropertyDefinition> theDefs = inClass->dynamicClass->getProperties(); - for (quint32 idx = 0, end = theDefs.size(); idx < end; ++idx) { - const QDemonPropertyDefinition &theDefinition(theDefs[idx]); - auto theConstant = inShader->shaderConstant(theDefinition.name); - - // This is fine, the property wasn't found and we continue, no problem. - if (!theConstant) - continue; - quint8 *dataPtr = inEffect->getDataSectionBegin() + theDefinition.offset; - doApplyInstanceValue(inEffect, dataPtr, theDefinition.name, theDefinition.dataType, inShader, theDefinition); - } - } +// if (!inCommand.m_propertyName.isEmpty()) { +// bool canGetData = inCommand.m_valueOffset + getSizeofShaderDataType(inCommand.m_valueType) <= inEffect->dataSectionByteSize; +// if (canGetData == false) { +// Q_ASSERT(false); +// return; +// } +// quint8 *dataPtr = inEffect->getDataSectionBegin() + inCommand.m_valueOffset; +// const QDemonPropertyDefinition *theDefinition = inClass->dynamicClass->findPropertyByName(inCommand.m_propertyName); +// if (theDefinition) +// doApplyInstanceValue(inEffect, dataPtr, inCommand.m_propertyName, inCommand.m_valueType, inShader, *theDefinition); +// } else { +// QDemonDataView<QDemonPropertyDefinition> theDefs = inClass->dynamicClass->getProperties(); +// for (quint32 idx = 0, end = theDefs.size(); idx < end; ++idx) { +// const QDemonPropertyDefinition &theDefinition(theDefs[idx]); +// auto theConstant = inShader->shaderConstant(theDefinition.name); + +// // This is fine, the property wasn't found and we continue, no problem. +// if (!theConstant) +// continue; +// quint8 *dataPtr = inEffect->getDataSectionBegin() + theDefinition.offset; +// doApplyInstanceValue(inEffect, dataPtr, theDefinition.name, theDefinition.dataType, inShader, theDefinition); +// } +// } } void applyValue(QDemonRenderEffect *inEffect, @@ -1084,12 +1091,12 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface const QDemonRef<QDemonRenderShaderProgram> &inShader, const QDemonApplyValue &inCommand) { - if (!inCommand.m_propertyName.isEmpty()) { - quint8 *dataPtr = inCommand.m_value.mData; - const QDemonPropertyDefinition *theDefinition = inClass->dynamicClass->findPropertyByName(inCommand.m_propertyName); - if (theDefinition) - doApplyInstanceValue(inEffect, dataPtr, inCommand.m_propertyName, inCommand.m_valueType, inShader, *theDefinition); - } +// if (!inCommand.m_propertyName.isEmpty()) { +// quint8 *dataPtr = inCommand.m_value.mData; +// const QDemonPropertyDefinition *theDefinition = inClass->dynamicClass->findPropertyByName(inCommand.m_propertyName); +// if (theDefinition) +// doApplyInstanceValue(inEffect, dataPtr, inCommand.m_propertyName, inCommand.m_valueType, inShader, *theDefinition); +// } } bool applyBlending(const QDemonApplyBlending &inCommand) @@ -1164,7 +1171,7 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface } if (!inCommand.m_paramName.isEmpty()) { - auto theConstant = inShader->shaderConstant(inCommand.m_paramName.toLatin1()); + auto theConstant = inShader->shaderConstant(inCommand.m_paramName); if (theConstant) { if (theConstant->getShaderConstantType() != QDemonRenderShaderDataType::Texture2D) { @@ -1419,204 +1426,206 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface const QDemonRef<QDemonRenderTexture2D> &inDepthStencilTexture, const QVector2D &inCameraClipRange) { - // Run through the effect commands and render the effect. - // QDemonRenderTexture2D* theCurrentTexture(&inSourceTexture); - auto theContext = m_context->renderContext(); - - // Context variables that are updated during the course of a pass. - QDemonEffectTextureData theCurrentSourceTexture(inSourceTexture, false); - QDemonRef<QDemonRenderTexture2D> theCurrentDepthStencilTexture; - QDemonRef<QDemonRenderFrameBuffer> theCurrentRenderTarget(inTarget); - QDemonRef<QDemonEffectShader> theCurrentShader; - QRect theOriginalViewport(theContext->viewport()); - bool wasScissorEnabled = theContext->isScissorTestEnabled(); - bool wasBlendingEnabled = theContext->isBlendingEnabled(); - // save current blending setup - QDemonRenderBlendFunctionArgument theBlendFunc = theContext->blendFunction(); - QDemonRenderBlendEquationArgument theBlendEqu = theContext->blendEquation(); - bool intermediateBlendingEnabled = false; - QDemonTextureDetails theDetails(inSourceTexture->textureDetails()); - quint32 theFinalWidth = (quint32)(theDetails.width); - quint32 theFinalHeight = (quint32)(theDetails.height); - QVector2D theDestSize; - { - // Ensure no matter the command run goes we replace the rendering system to some - // semblance of the approprate - // setting. - QDemonRenderContextScopedProperty<QDemonRef<QDemonRenderFrameBuffer>> __framebuffer(*theContext, - &QDemonRenderContext::renderTarget, - &QDemonRenderContext::setRenderTarget); - QDemonRenderContextScopedProperty<QRect> __viewport(*theContext, - &QDemonRenderContext::viewport, - &QDemonRenderContext::setViewport); - QDemonRenderContextScopedProperty<bool> __scissorEnabled(*theContext, - &QDemonRenderContext::isScissorTestEnabled, - &QDemonRenderContext::setScissorTestEnabled); - QDemonRenderContextScopedProperty<bool> __stencilTest(*theContext, - &QDemonRenderContext::isStencilTestEnabled, - &QDemonRenderContext::setStencilTestEnabled); - QDemonRenderContextScopedProperty<QDemonRenderBoolOp> __depthFunction(*theContext, - &QDemonRenderContext::depthFunction, - &QDemonRenderContext::setDepthFunction); - QDemonOption<QDemonDepthStencil> theCurrentDepthStencil; - - theContext->setScissorTestEnabled(false); - theContext->setBlendingEnabled(false); - theContext->setCullingEnabled(false); - theContext->setDepthTestEnabled(false); - theContext->setDepthWriteEnabled(false); - - QMatrix4x4 theMVP; - QDemonDataView<dynamic::QDemonCommand *> theCommands = inClass->dynamicClass->getRenderCommands(); - for (quint32 commandIdx = 0, commandEnd = theCommands.size(); commandIdx < commandEnd; ++commandIdx) { - const QDemonCommand &theCommand(*theCommands[commandIdx]); - switch (theCommand.m_type) { - case CommandType::AllocateBuffer: - allocateBuffer(*inEffect, - static_cast<const QDemonAllocateBuffer &>(theCommand), - theFinalWidth, - theFinalHeight, - theDetails.format); - break; - - case CommandType::AllocateImage: - allocateImage(*inEffect, static_cast<const QDemonAllocateImage &>(theCommand), theFinalWidth, theFinalHeight); - break; - - case CommandType::AllocateDataBuffer: - allocateDataBuffer(*inEffect, static_cast<const QDemonAllocateDataBuffer &>(theCommand)); - break; - - case CommandType::BindBuffer: - theCurrentRenderTarget = bindBuffer(*inEffect, static_cast<const QDemonBindBuffer &>(theCommand), theMVP, theDestSize); - break; - - case CommandType::BindTarget: { - m_context->renderContext()->setRenderTarget(inTarget); - theCurrentRenderTarget = inTarget; - theMVP = inMVP; - theContext->setViewport(theOriginalViewport); - theDestSize = QVector2D((float)theFinalWidth, (float)theFinalHeight); - // This isn't necessary if we are rendering to an offscreen buffer and not - // compositing - // with other objects. - if (inEnableBlendWhenRenderToTarget) { - theContext->setBlendingEnabled(wasBlendingEnabled); - theContext->setScissorTestEnabled(wasScissorEnabled); - // The blending setup was done before we apply the effect - theContext->setBlendFunction(theBlendFunc); - theContext->setBlendEquation(theBlendEqu); - } - } break; - case CommandType::BindShader: - theCurrentShader = bindShader(inEffect->className, static_cast<const QDemonBindShader &>(theCommand)); - break; - case CommandType::ApplyInstanceValue: - if (theCurrentShader) - applyInstanceValue(inEffect, - inClass, - theCurrentShader->m_shader, - static_cast<const QDemonApplyInstanceValue &>(theCommand)); - break; - case CommandType::ApplyValue: - if (theCurrentShader) - applyValue(inEffect, inClass, theCurrentShader->m_shader, static_cast<const QDemonApplyValue &>(theCommand)); - break; - case CommandType::ApplyBlending: - intermediateBlendingEnabled = applyBlending(static_cast<const QDemonApplyBlending &>(theCommand)); - break; - case CommandType::ApplyBufferValue: - if (theCurrentShader) - theCurrentSourceTexture = applyBufferValue(inEffect, - theCurrentShader->m_shader, - static_cast<const QDemonApplyBufferValue &>(theCommand), - inSourceTexture, - theCurrentSourceTexture); - break; - case CommandType::ApplyDepthValue: - if (theCurrentShader) - applyDepthValue(inEffect, theCurrentShader->m_shader, static_cast<const QDemonApplyDepthValue &>(theCommand), inDepthTexture); - if (!inDepthTexture) { - qCCritical(INVALID_OPERATION, - "Depth value command detected but no " - "depth buffer provided for effect %s", - qPrintable(inEffect->className)); - Q_ASSERT(false); - } - break; - case CommandType::ApplyImageValue: - if (theCurrentShader) - applyImageValue(inEffect, theCurrentShader->m_shader, static_cast<const QDemonApplyImageValue &>(theCommand)); - break; - case CommandType::ApplyDataBufferValue: - if (theCurrentShader) - applyDataBufferValue(inEffect, - theCurrentShader->m_shader, - static_cast<const QDemonApplyDataBufferValue &>(theCommand)); - break; - case CommandType::DepthStencil: { - const QDemonDepthStencil &theDepthStencil = static_cast<const QDemonDepthStencil &>(theCommand); - theCurrentDepthStencilTexture = findTexture(inEffect, theDepthStencil.m_bufferName); - if (theCurrentDepthStencilTexture) - theCurrentDepthStencil = theDepthStencil; - } break; - case CommandType::Render: - if (theCurrentShader && theCurrentSourceTexture.texture) { - renderPass(*theCurrentShader, - theMVP, - theCurrentSourceTexture, - theCurrentRenderTarget, - theDestSize, - inCameraClipRange, - theCurrentDepthStencilTexture, - theCurrentDepthStencil, - static_cast<const QDemonRender &>(theCommand).m_drawIndirect); - } - // Reset the source texture regardless - theCurrentSourceTexture = QDemonEffectTextureData(inSourceTexture, false); - theCurrentDepthStencilTexture = nullptr; - theCurrentDepthStencil = QDemonOption<QDemonDepthStencil>(); - // reset intermediate blending state - if (intermediateBlendingEnabled) { - theContext->setBlendingEnabled(false); - intermediateBlendingEnabled = false; - } - break; - case CommandType::ApplyRenderState: - applyRenderStateValue(theCurrentRenderTarget.data(), - inDepthStencilTexture, - static_cast<const QDemonApplyRenderState &>(theCommand)); - break; - default: - Q_ASSERT(false); - break; - } - } - - setEffectRequiresCompilation(inEffect->className, false); - - // reset to default stencil state - if (inDepthStencilTexture) - theContext->setDepthStencilState(m_defaultStencilState); - - // Release any per-frame buffers - if (inEffect->m_context) { - QDemonEffectContext &theContext(*inEffect->m_context); - // Query for size on every loop intentional - for (qint32 idx = 0; idx < theContext.m_allocatedBuffers.size(); ++idx) { - if (theContext.m_allocatedBuffers[idx].flags.isSceneLifetime() == false) { - theContext.releaseBuffer(idx); - --idx; - } - } - for (qint32 idx = 0; idx < theContext.m_allocatedImages.size(); ++idx) { - if (theContext.m_allocatedImages[idx].flags.isSceneLifetime() == false) { - theContext.releaseImage(idx); - --idx; - } - } - } - } + Q_ASSERT(0); + +// // Run through the effect commands and render the effect. +// // QDemonRenderTexture2D* theCurrentTexture(&inSourceTexture); +// auto theContext = m_context->renderContext(); + +// // Context variables that are updated during the course of a pass. +// QDemonEffectTextureData theCurrentSourceTexture(inSourceTexture, false); +// QDemonRef<QDemonRenderTexture2D> theCurrentDepthStencilTexture; +// QDemonRef<QDemonRenderFrameBuffer> theCurrentRenderTarget(inTarget); +// QDemonRef<QDemonEffectShader> theCurrentShader; +// QRect theOriginalViewport(theContext->viewport()); +// bool wasScissorEnabled = theContext->isScissorTestEnabled(); +// bool wasBlendingEnabled = theContext->isBlendingEnabled(); +// // save current blending setup +// QDemonRenderBlendFunctionArgument theBlendFunc = theContext->blendFunction(); +// QDemonRenderBlendEquationArgument theBlendEqu = theContext->blendEquation(); +// bool intermediateBlendingEnabled = false; +// QDemonTextureDetails theDetails(inSourceTexture->textureDetails()); +// quint32 theFinalWidth = (quint32)(theDetails.width); +// quint32 theFinalHeight = (quint32)(theDetails.height); +// QVector2D theDestSize; +// { +// // Ensure no matter the command run goes we replace the rendering system to some +// // semblance of the approprate +// // setting. +// QDemonRenderContextScopedProperty<QDemonRef<QDemonRenderFrameBuffer>> __framebuffer(*theContext, +// &QDemonRenderContext::renderTarget, +// &QDemonRenderContext::setRenderTarget); +// QDemonRenderContextScopedProperty<QRect> __viewport(*theContext, +// &QDemonRenderContext::viewport, +// &QDemonRenderContext::setViewport); +// QDemonRenderContextScopedProperty<bool> __scissorEnabled(*theContext, +// &QDemonRenderContext::isScissorTestEnabled, +// &QDemonRenderContext::setScissorTestEnabled); +// QDemonRenderContextScopedProperty<bool> __stencilTest(*theContext, +// &QDemonRenderContext::isStencilTestEnabled, +// &QDemonRenderContext::setStencilTestEnabled); +// QDemonRenderContextScopedProperty<QDemonRenderBoolOp> __depthFunction(*theContext, +// &QDemonRenderContext::depthFunction, +// &QDemonRenderContext::setDepthFunction); +// QDemonOption<QDemonDepthStencil> theCurrentDepthStencil; + +// theContext->setScissorTestEnabled(false); +// theContext->setBlendingEnabled(false); +// theContext->setCullingEnabled(false); +// theContext->setDepthTestEnabled(false); +// theContext->setDepthWriteEnabled(false); + +// QMatrix4x4 theMVP; +// QDemonDataView<dynamic::QDemonCommand *> theCommands = inClass->dynamicClass->getRenderCommands(); +// for (quint32 commandIdx = 0, commandEnd = theCommands.size(); commandIdx < commandEnd; ++commandIdx) { +// const QDemonCommand &theCommand(*theCommands[commandIdx]); +// switch (theCommand.m_type) { +// case CommandType::AllocateBuffer: +// allocateBuffer(*inEffect, +// static_cast<const QDemonAllocateBuffer &>(theCommand), +// theFinalWidth, +// theFinalHeight, +// theDetails.format); +// break; + +// case CommandType::AllocateImage: +// allocateImage(*inEffect, static_cast<const QDemonAllocateImage &>(theCommand), theFinalWidth, theFinalHeight); +// break; + +// case CommandType::AllocateDataBuffer: +// allocateDataBuffer(*inEffect, static_cast<const QDemonAllocateDataBuffer &>(theCommand)); +// break; + +// case CommandType::BindBuffer: +// theCurrentRenderTarget = bindBuffer(*inEffect, static_cast<const QDemonBindBuffer &>(theCommand), theMVP, theDestSize); +// break; + +// case CommandType::BindTarget: { +// m_context->renderContext()->setRenderTarget(inTarget); +// theCurrentRenderTarget = inTarget; +// theMVP = inMVP; +// theContext->setViewport(theOriginalViewport); +// theDestSize = QVector2D((float)theFinalWidth, (float)theFinalHeight); +// // This isn't necessary if we are rendering to an offscreen buffer and not +// // compositing +// // with other objects. +// if (inEnableBlendWhenRenderToTarget) { +// theContext->setBlendingEnabled(wasBlendingEnabled); +// theContext->setScissorTestEnabled(wasScissorEnabled); +// // The blending setup was done before we apply the effect +// theContext->setBlendFunction(theBlendFunc); +// theContext->setBlendEquation(theBlendEqu); +// } +// } break; +// case CommandType::BindShader: +// theCurrentShader = bindShader(inEffect->className, static_cast<const QDemonBindShader &>(theCommand)); +// break; +// case CommandType::ApplyInstanceValue: +// if (theCurrentShader) +// applyInstanceValue(inEffect, +// inClass, +// theCurrentShader->m_shader, +// static_cast<const QDemonApplyInstanceValue &>(theCommand)); +// break; +// case CommandType::ApplyValue: +// if (theCurrentShader) +// applyValue(inEffect, inClass, theCurrentShader->m_shader, static_cast<const QDemonApplyValue &>(theCommand)); +// break; +// case CommandType::ApplyBlending: +// intermediateBlendingEnabled = applyBlending(static_cast<const QDemonApplyBlending &>(theCommand)); +// break; +// case CommandType::ApplyBufferValue: +// if (theCurrentShader) +// theCurrentSourceTexture = applyBufferValue(inEffect, +// theCurrentShader->m_shader, +// static_cast<const QDemonApplyBufferValue &>(theCommand), +// inSourceTexture, +// theCurrentSourceTexture); +// break; +// case CommandType::ApplyDepthValue: +// if (theCurrentShader) +// applyDepthValue(inEffect, theCurrentShader->m_shader, static_cast<const QDemonApplyDepthValue &>(theCommand), inDepthTexture); +// if (!inDepthTexture) { +// qCCritical(INVALID_OPERATION, +// "Depth value command detected but no " +// "depth buffer provided for effect %s", +// qPrintable(inEffect->className)); +// Q_ASSERT(false); +// } +// break; +// case CommandType::ApplyImageValue: +// if (theCurrentShader) +// applyImageValue(inEffect, theCurrentShader->m_shader, static_cast<const QDemonApplyImageValue &>(theCommand)); +// break; +// case CommandType::ApplyDataBufferValue: +// if (theCurrentShader) +// applyDataBufferValue(inEffect, +// theCurrentShader->m_shader, +// static_cast<const QDemonApplyDataBufferValue &>(theCommand)); +// break; +// case CommandType::DepthStencil: { +// const QDemonDepthStencil &theDepthStencil = static_cast<const QDemonDepthStencil &>(theCommand); +// theCurrentDepthStencilTexture = findTexture(inEffect, theDepthStencil.m_bufferName); +// if (theCurrentDepthStencilTexture) +// theCurrentDepthStencil = theDepthStencil; +// } break; +// case CommandType::Render: +// if (theCurrentShader && theCurrentSourceTexture.texture) { +// renderPass(*theCurrentShader, +// theMVP, +// theCurrentSourceTexture, +// theCurrentRenderTarget, +// theDestSize, +// inCameraClipRange, +// theCurrentDepthStencilTexture, +// theCurrentDepthStencil, +// static_cast<const QDemonRender &>(theCommand).m_drawIndirect); +// } +// // Reset the source texture regardless +// theCurrentSourceTexture = QDemonEffectTextureData(inSourceTexture, false); +// theCurrentDepthStencilTexture = nullptr; +// theCurrentDepthStencil = QDemonOption<QDemonDepthStencil>(); +// // reset intermediate blending state +// if (intermediateBlendingEnabled) { +// theContext->setBlendingEnabled(false); +// intermediateBlendingEnabled = false; +// } +// break; +// case CommandType::ApplyRenderState: +// applyRenderStateValue(theCurrentRenderTarget.data(), +// inDepthStencilTexture, +// static_cast<const QDemonApplyRenderState &>(theCommand)); +// break; +// default: +// Q_ASSERT(false); +// break; +// } +// } + +// setEffectRequiresCompilation(inEffect->className, false); + +// // reset to default stencil state +// if (inDepthStencilTexture) +// theContext->setDepthStencilState(m_defaultStencilState); + +// // Release any per-frame buffers +// if (inEffect->m_context) { +// QDemonEffectContext &theContext(*inEffect->m_context); +// // Query for size on every loop intentional +// for (qint32 idx = 0; idx < theContext.m_allocatedBuffers.size(); ++idx) { +// if (theContext.m_allocatedBuffers[idx].flags.isSceneLifetime() == false) { +// theContext.releaseBuffer(idx); +// --idx; +// } +// } +// for (qint32 idx = 0; idx < theContext.m_allocatedImages.size(); ++idx) { +// if (theContext.m_allocatedImages[idx].flags.isSceneLifetime() == false) { +// theContext.releaseImage(idx); +// --idx; +// } +// } +// } +// } } QDemonRef<QDemonRenderTexture2D> renderEffect(QDemonEffectRenderArgument inRenderArgument) override @@ -1641,8 +1650,9 @@ struct QDemonEffectSystem : public QDemonEffectSystemInterface // UdoL Some Effects may need to run before HDR tonemap. This means we need to keep the // input format QDemonRenderTextureFormat theOutputFormat = QDemonRenderTextureFormat::RGBA8; - if (theClass->dynamicClass->getOutputTextureFormat() == QDemonRenderTextureFormat::Unknown) - theOutputFormat = theDetails.format; + // TODO: +// if (theClass->dynamicClass->getOutputTextureFormat() == QDemonRenderTextureFormat::Unknown) +// theOutputFormat = theDetails.format; auto theTargetTexture = theManager->allocateTexture2D(theFinalWidth, theFinalHeight, theOutputFormat); theBuffer->attach(QDemonRenderFrameBufferAttachment::Color0, theTargetTexture); theContext->setRenderTarget(theBuffer);