diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag new file mode 100644 index 0000000000..7fb5d83719 --- /dev/null +++ b/interface/resources/shaders/directional_light.frag @@ -0,0 +1,26 @@ +#version 120 + +// +// directional_light.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/3/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal texture +uniform sampler2D normalMap; + +void main(void) { + // compute the base color based on OpenGL lighting model + vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); + gl_FragColor = vec4((texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + + gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * max(0.0, dot(normal * 2.0 - + vec4(1.0, 1.0, 1.0, 2.0), gl_LightSource[0].position)))).rgb, normal.a); +} diff --git a/interface/resources/shaders/metavoxel_heightfield_cascaded_shadow_map.frag b/interface/resources/shaders/directional_light_cascaded_shadow_map.frag similarity index 50% rename from interface/resources/shaders/metavoxel_heightfield_cascaded_shadow_map.frag rename to interface/resources/shaders/directional_light_cascaded_shadow_map.frag index 059a4e0296..d16467520e 100644 --- a/interface/resources/shaders/metavoxel_heightfield_cascaded_shadow_map.frag +++ b/interface/resources/shaders/directional_light_cascaded_shadow_map.frag @@ -1,10 +1,10 @@ #version 120 // -// metavoxel_heightfield.frag +// directional_light.frag // fragment shader // -// Created by Andrzej Kapolka on 7/28/14. +// Created by Andrzej Kapolka on 9/3/14. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -14,6 +14,12 @@ // the diffuse texture uniform sampler2D diffuseMap; +// the normal texture +uniform sampler2D normalMap; + +// the depth texture +uniform sampler2D depthMap; + // the shadow texture uniform sampler2DShadow shadowMap; @@ -21,28 +27,39 @@ uniform sampler2DShadow shadowMap; uniform vec3 shadowDistances; // the inverse of the size of the shadow map -const float shadowScale = 1.0 / 2048.0; +uniform float shadowScale; -// the interpolated position -varying vec4 position; +// the distance to the near clip plane +uniform float near; -// the interpolated normal -varying vec4 normal; +// scale factor for depth: (far - near) / far +uniform float depthScale; + +// offset for depth texture coordinates +uniform vec2 depthTexCoordOffset; + +// scale for depth texture coordinates +uniform vec2 depthTexCoordScale; void main(void) { + // compute the view space position using the depth + float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); + vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); + // compute the index of the cascade to use and the corresponding texture coordinates int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), dot(gl_EyePlaneR[shadowIndex], position)); - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalize(normal), gl_LightSource[0].position); + // compute the color based on OpenGL lighting model, use the alpha from the normal map + vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); + float diffuse = dot(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0), gl_LightSource[0].position); float facingLight = step(0.0, diffuse) * 0.25 * (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); - vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + + gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + gl_FragColor = vec4(baseColor.rgb, normal.a); } diff --git a/interface/resources/shaders/directional_light_shadow_map.frag b/interface/resources/shaders/directional_light_shadow_map.frag new file mode 100644 index 0000000000..d4ac254fc5 --- /dev/null +++ b/interface/resources/shaders/directional_light_shadow_map.frag @@ -0,0 +1,60 @@ +#version 120 + +// +// directional_light.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/3/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal texture +uniform sampler2D normalMap; + +// the depth texture +uniform sampler2D depthMap; + +// the shadow texture +uniform sampler2DShadow shadowMap; + +// the inverse of the size of the shadow map +uniform float shadowScale; + +// the distance to the near clip plane +uniform float near; + +// scale factor for depth: (far - near) / far +uniform float depthScale; + +// offset for depth texture coordinates +uniform vec2 depthTexCoordOffset; + +// scale for depth texture coordinates +uniform vec2 depthTexCoordScale; + +void main(void) { + // compute the view space position using the depth + float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); + vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); + + // compute the corresponding texture coordinates + vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position)); + + // compute the color based on OpenGL lighting model, use the alpha from the normal map + vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); + float diffuse = dot(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0), gl_LightSource[0].position); + float facingLight = step(0.0, diffuse) * 0.25 * + (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); + vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + + gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + gl_FragColor = vec4(baseColor.rgb, normal.a); +} diff --git a/interface/resources/shaders/metavoxel_heightfield.frag b/interface/resources/shaders/metavoxel_heightfield.frag deleted file mode 100644 index f99a0a6403..0000000000 --- a/interface/resources/shaders/metavoxel_heightfield.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 120 - -// -// metavoxel_heightfield.frag -// fragment shader -// -// Created by Andrzej Kapolka on 7/28/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// the diffuse texture -uniform sampler2D diffuseMap; - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // compute the base color based on OpenGL lighting model - vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * max(0.0, dot(normalize(normal), gl_LightSource[0].position))); - gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st); -} diff --git a/interface/resources/shaders/metavoxel_heightfield.vert b/interface/resources/shaders/metavoxel_heightfield.vert deleted file mode 100644 index 70cf3f9419..0000000000 --- a/interface/resources/shaders/metavoxel_heightfield.vert +++ /dev/null @@ -1,51 +0,0 @@ -#version 120 - -// -// metavoxel_heighfield.vert -// vertex shader -// -// Created by Andrzej Kapolka on 7/28/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// the height texture -uniform sampler2D heightMap; - -// the distance between height points in texture space -uniform float heightScale; - -// the scale between height and color textures -uniform float colorScale; - -// the interpolated position -varying vec4 position; - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // transform and store the normal for interpolation - vec2 heightCoord = gl_MultiTexCoord0.st; - float deltaX = texture2D(heightMap, heightCoord - vec2(heightScale, 0.0)).r - - texture2D(heightMap, heightCoord + vec2(heightScale, 0.0)).r; - float deltaZ = texture2D(heightMap, heightCoord - vec2(0.0, heightScale)).r - - texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r; - normal = normalize(gl_ModelViewMatrix * vec4(deltaX, heightScale, deltaZ, 0.0)); - - // add the height to the position - float height = texture2D(heightMap, heightCoord).r; - position = gl_ModelViewMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0)); - gl_Position = gl_ProjectionMatrix * position; - - // the zero height should be invisible - gl_FrontColor = vec4(1.0, 1.0, 1.0, step(height, 0.0)); - - // pass along the scaled/offset texture coordinates - gl_TexCoord[0] = (gl_MultiTexCoord0 - vec4(heightScale, heightScale, 0.0, 0.0)) * colorScale; - - // and the shadow texture coordinates - gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position), 1.0); -} diff --git a/interface/resources/shaders/metavoxel_heightfield_base.frag b/interface/resources/shaders/metavoxel_heightfield_base.frag index 9b64a59e6f..a4523ced23 100644 --- a/interface/resources/shaders/metavoxel_heightfield_base.frag +++ b/interface/resources/shaders/metavoxel_heightfield_base.frag @@ -14,7 +14,11 @@ // the diffuse texture uniform sampler2D diffuseMap; +// the interpolated normal +varying vec4 normal; + void main(void) { // compute the base color based on OpenGL lighting model - gl_FragColor = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].st); + gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].st); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); } diff --git a/interface/resources/shaders/metavoxel_heightfield_base.vert b/interface/resources/shaders/metavoxel_heightfield_base.vert index 3e4b081d6f..f097426e13 100644 --- a/interface/resources/shaders/metavoxel_heightfield_base.vert +++ b/interface/resources/shaders/metavoxel_heightfield_base.vert @@ -20,9 +20,20 @@ uniform float heightScale; // the scale between height and color textures uniform float colorScale; +// the interpolated normal +varying vec4 normal; + void main(void) { + // transform and store the normal for interpolation + vec2 heightCoord = gl_MultiTexCoord0.st; + float deltaX = texture2D(heightMap, heightCoord - vec2(heightScale, 0.0)).r - + texture2D(heightMap, heightCoord + vec2(heightScale, 0.0)).r; + float deltaZ = texture2D(heightMap, heightCoord - vec2(0.0, heightScale)).r - + texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r; + normal = normalize(gl_ModelViewMatrix * vec4(deltaX, heightScale, deltaZ, 0.0)); + // add the height to the position - float height = texture2D(heightMap, gl_MultiTexCoord0.st).r; + float height = texture2D(heightMap, heightCoord).r; gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0)); // the zero height should be invisible diff --git a/interface/resources/shaders/metavoxel_heightfield_light.frag b/interface/resources/shaders/metavoxel_heightfield_light.frag deleted file mode 100644 index ce3f23e142..0000000000 --- a/interface/resources/shaders/metavoxel_heightfield_light.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 120 - -// -// metavoxel_heightfield_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 8/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // compute the base color based on OpenGL lighting model - gl_FragColor = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * max(0.0, dot(normalize(normal), gl_LightSource[0].position))); -} diff --git a/interface/resources/shaders/metavoxel_heightfield_light.vert b/interface/resources/shaders/metavoxel_heightfield_light.vert deleted file mode 100644 index 228d575b81..0000000000 --- a/interface/resources/shaders/metavoxel_heightfield_light.vert +++ /dev/null @@ -1,45 +0,0 @@ -#version 120 - -// -// metavoxel_heighfield_light.vert -// vertex shader -// -// Created by Andrzej Kapolka on 8/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// the height texture -uniform sampler2D heightMap; - -// the distance between height points in texture space -uniform float heightScale; - -// the interpolated position -varying vec4 position; - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // transform and store the normal for interpolation - vec2 heightCoord = gl_MultiTexCoord0.st; - float deltaX = texture2D(heightMap, heightCoord - vec2(heightScale, 0.0)).r - - texture2D(heightMap, heightCoord + vec2(heightScale, 0.0)).r; - float deltaZ = texture2D(heightMap, heightCoord - vec2(0.0, heightScale)).r - - texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r; - normal = normalize(gl_ModelViewMatrix * vec4(deltaX, heightScale, deltaZ, 0.0)); - - // add the height to the position - float height = texture2D(heightMap, heightCoord).r; - position = gl_ModelViewMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0)); - gl_Position = gl_ProjectionMatrix * position; - - // the zero height should be invisible - gl_FrontColor = vec4(1.0, 1.0, 1.0, step(height, 0.0)); - - // and the shadow texture coordinates - gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position), 1.0); -} diff --git a/interface/resources/shaders/metavoxel_heightfield_light_cascaded_shadow_map.frag b/interface/resources/shaders/metavoxel_heightfield_light_cascaded_shadow_map.frag deleted file mode 100644 index 73382eb83c..0000000000 --- a/interface/resources/shaders/metavoxel_heightfield_light_cascaded_shadow_map.frag +++ /dev/null @@ -1,44 +0,0 @@ -#version 120 - -// -// metavoxel_heightfield_light_cascaded_shadow_map.frag -// fragment shader -// -// Created by Andrzej Kapolka on 8/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// the shadow texture -uniform sampler2DShadow shadowMap; - -// the distances to the cascade sections -uniform vec3 shadowDistances; - -// the inverse of the size of the shadow map -const float shadowScale = 1.0 / 2048.0; - -// the interpolated position -varying vec4 position; - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // compute the index of the cascade to use and the corresponding texture coordinates - int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); - vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), - dot(gl_EyePlaneR[shadowIndex], position)); - - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalize(normal), gl_LightSource[0].position); - float facingLight = step(0.0, diffuse) * 0.25 * - (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); - gl_FragColor = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); -} diff --git a/interface/resources/shaders/metavoxel_heightfield_light_shadow_map.frag b/interface/resources/shaders/metavoxel_heightfield_light_shadow_map.frag deleted file mode 100644 index 4f2df8958b..0000000000 --- a/interface/resources/shaders/metavoxel_heightfield_light_shadow_map.frag +++ /dev/null @@ -1,33 +0,0 @@ -#version 120 - -// -// metavoxel_heightfield_light_shadow_map.frag -// fragment shader -// -// Created by Andrzej Kapolka on 8/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// the shadow texture -uniform sampler2DShadow shadowMap; - -// the inverse of the size of the shadow map -const float shadowScale = 1.0 / 2048.0; - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalize(normal), gl_LightSource[0].position); - float facingLight = step(0.0, diffuse) * 0.25 * - (shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, shadowScale, 0.0)).r); - gl_FragColor = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); -} diff --git a/interface/resources/shaders/metavoxel_heightfield_shadow_map.frag b/interface/resources/shaders/metavoxel_heightfield_shadow_map.frag deleted file mode 100644 index bf319462d3..0000000000 --- a/interface/resources/shaders/metavoxel_heightfield_shadow_map.frag +++ /dev/null @@ -1,37 +0,0 @@ -#version 120 - -// -// metavoxel_heightfield.frag -// fragment shader -// -// Created by Andrzej Kapolka on 7/28/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// the diffuse texture -uniform sampler2D diffuseMap; - -// the shadow texture -uniform sampler2DShadow shadowMap; - -// the inverse of the size of the shadow map -const float shadowScale = 1.0 / 2048.0; - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalize(normal), gl_LightSource[0].position); - float facingLight = step(0.0, diffuse) * 0.25 * - (shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, shadowScale, 0.0)).r); - vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st); -} diff --git a/interface/resources/shaders/metavoxel_voxel_base.frag b/interface/resources/shaders/metavoxel_voxel_base.frag new file mode 100644 index 0000000000..72eca6b25d --- /dev/null +++ b/interface/resources/shaders/metavoxel_voxel_base.frag @@ -0,0 +1,21 @@ +#version 120 + +// +// metavoxel_voxel_base.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/4/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // store the interpolated color and normal + gl_FragData[0] = gl_Color; + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); +} diff --git a/interface/resources/shaders/metavoxel_voxel_base.vert b/interface/resources/shaders/metavoxel_voxel_base.vert new file mode 100644 index 0000000000..4fe5802462 --- /dev/null +++ b/interface/resources/shaders/metavoxel_voxel_base.vert @@ -0,0 +1,26 @@ +#version 120 + +// +// metavoxel_voxel_base.vert +// vertex shader +// +// Created by Andrzej Kapolka on 9/4/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // transform and store the normal for interpolation + normal = vec4(normalize(gl_NormalMatrix * gl_Normal), 0.0); + + // use the fixed-function position + gl_Position = ftransform(); + + // copy the color for interpolation + gl_FrontColor = vec4(gl_Color.rgb, 0.0); +} diff --git a/interface/resources/shaders/metavoxel_voxel_splat.frag b/interface/resources/shaders/metavoxel_voxel_splat.frag new file mode 100644 index 0000000000..66ce2721ac --- /dev/null +++ b/interface/resources/shaders/metavoxel_voxel_splat.frag @@ -0,0 +1,29 @@ +#version 120 + +// +// metavoxel_voxel_splat.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/4/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the number of splats per pass +const int SPLAT_COUNT = 4; + +// the splat textures +uniform sampler2D diffuseMaps[SPLAT_COUNT]; + +// alpha values for the four splat textures +varying vec4 alphaValues; + +void main(void) { + // blend the splat textures + gl_FragColor = (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x + + texture2D(diffuseMaps[1], gl_TexCoord[1].st) * alphaValues.y + + texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z + + texture2D(diffuseMaps[3], gl_TexCoord[3].st) * alphaValues.w); +} diff --git a/interface/resources/shaders/metavoxel_voxel_splat.vert b/interface/resources/shaders/metavoxel_voxel_splat.vert new file mode 100644 index 0000000000..150a9e7d2e --- /dev/null +++ b/interface/resources/shaders/metavoxel_voxel_splat.vert @@ -0,0 +1,62 @@ +#version 120 + +// +// metavoxel_voxel_splat.vert +// vertex shader +// +// Created by Andrzej Kapolka on 9/4/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the splat textures scales on the S axis +uniform vec4 splatTextureScalesS; + +// the splat texture scales on the T axis +uniform vec4 splatTextureScalesT; + +// the lower bounds of the values corresponding to the splat textures +uniform vec4 textureValueMinima; + +// the upper bounds of the values corresponding to the splat textures +uniform vec4 textureValueMaxima; + +// the materials to apply to the vertex +attribute vec4 materials; + +// the weights of each material +attribute vec4 materialWeights; + +// alpha values for the four splat textures +varying vec4 alphaValues; + +void main(void) { + // use the fixed-function position + gl_Position = ftransform(); + + // pass along the scaled/offset texture coordinates + vec4 textureSpacePosition = vec4(gl_Vertex.xz, 0.0, 1.0); + gl_TexCoord[0] = textureSpacePosition * vec4(splatTextureScalesS[0], splatTextureScalesT[0], 0.0, 1.0); + gl_TexCoord[1] = textureSpacePosition * vec4(splatTextureScalesS[1], splatTextureScalesT[1], 0.0, 1.0); + gl_TexCoord[2] = textureSpacePosition * vec4(splatTextureScalesS[2], splatTextureScalesT[2], 0.0, 1.0); + gl_TexCoord[3] = textureSpacePosition * vec4(splatTextureScalesS[3], splatTextureScalesT[3], 0.0, 1.0); + + // compute the alpha values for each texture + float value = materials[0]; + vec4 valueVector = vec4(value, value, value, value); + alphaValues = step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima) * materialWeights[0]; + + value = materials[1]; + valueVector = vec4(value, value, value, value); + alphaValues += step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima) * materialWeights[1]; + + value = materials[2]; + valueVector = vec4(value, value, value, value); + alphaValues += step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima) * materialWeights[2]; + + value = materials[3]; + valueVector = vec4(value, value, value, value); + alphaValues += step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima) * materialWeights[3]; +} diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index f135579526..d3819bf89b 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -9,7 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include <QMutexLocker> +#include <QOpenGLFramebufferObject> #include <QReadLocker> #include <QWriteLocker> #include <QtDebug> @@ -24,6 +28,7 @@ #include "Application.h" #include "MetavoxelSystem.h" #include "renderer/Model.h" +#include "renderer/RenderUtil.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation) REGISTER_META_OBJECT(SphereRenderer) @@ -46,6 +51,12 @@ void MetavoxelSystem::init() { new BufferDataAttribute("voxelBuffer")); _voxelBufferAttribute->setLODThresholdMultiplier( AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier()); + + loadLightProgram("shaders/directional_light.frag", _directionalLight, _directionalLightLocations); + loadLightProgram("shaders/directional_light_shadow_map.frag", _directionalLightShadowMap, + _directionalLightShadowMapLocations); + loadLightProgram("shaders/directional_light_cascaded_shadow_map.frag", _directionalLightCascadedShadowMap, + _directionalLightCascadedShadowMapLocations); } MetavoxelLOD MetavoxelSystem::getLOD() { @@ -116,6 +127,10 @@ int RenderVisitor::visit(MetavoxelInfo& info) { return STOP_RECURSION; } +const GLenum COLOR_DRAW_BUFFERS[] = { GL_COLOR_ATTACHMENT0 }; +const GLenum NORMAL_DRAW_BUFFERS[] = { GL_COLOR_ATTACHMENT1 }; +const GLenum COLOR_NORMAL_DRAW_BUFFERS[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; + void MetavoxelSystem::render() { // update the frustum ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); @@ -123,8 +138,128 @@ void MetavoxelSystem::render() { viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); + _needToLight = false; + + // clear the normal buffer + glDrawBuffers(sizeof(NORMAL_DRAW_BUFFERS) / sizeof(NORMAL_DRAW_BUFFERS[0]), NORMAL_DRAW_BUFFERS); + glClear(GL_COLOR_BUFFER_BIT); + + glDrawBuffers(sizeof(COLOR_DRAW_BUFFERS) / sizeof(COLOR_DRAW_BUFFERS[0]), COLOR_DRAW_BUFFERS); + RenderVisitor renderVisitor(getLOD()); guideToAugmented(renderVisitor, true); + + // give external parties a chance to join in + emit rendering(); + + if (!_needToLight) { + return; // skip lighting if not needed + } + + // perform deferred lighting, rendering to free fbo + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_BLEND); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + + QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + primaryFBO->release(); + + QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); + freeFBO->bind(); + glClear(GL_COLOR_BUFFER_BIT); + + glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID()); + + if (Menu::getInstance()->getShadowsEnabled()) { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); + + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); + + ProgramObject* program = &_directionalLightShadowMap; + const LightLocations* locations = &_directionalLightShadowMapLocations; + if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { + program = &_directionalLightCascadedShadowMap; + locations = &_directionalLightCascadedShadowMapLocations; + _directionalLightCascadedShadowMap.bind(); + _directionalLightCascadedShadowMap.setUniform(locations->shadowDistances, + Application::getInstance()->getShadowDistances()); + + } else { + program->bind(); + } + program->setUniformValue(locations->shadowScale, + 1.0f / Application::getInstance()->getTextureCache()->getShadowFramebufferObject()->width()); + + float left, right, bottom, top, nearVal, farVal; + glm::vec4 nearClipPlane, farClipPlane; + Application::getInstance()->computeOffAxisFrustum( + left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + program->setUniformValue(locations->near, nearVal); + program->setUniformValue(locations->depthScale, (farVal - nearVal) / farVal); + float nearScale = -1.0f / nearVal; + program->setUniformValue(locations->depthTexCoordOffset, left * nearScale, bottom * nearScale); + program->setUniformValue(locations->depthTexCoordScale, (right - left) * nearScale, (top - bottom) * nearScale); + + renderFullscreenQuad(); + + program->release(); + + glBindTexture(GL_TEXTURE_2D, 0); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, 0); + + glActiveTexture(GL_TEXTURE1); + + } else { + _directionalLight.bind(); + renderFullscreenQuad(); + _directionalLight.release(); + } + + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + + freeFBO->release(); + + // now transfer the lit region to the primary fbo + glEnable(GL_BLEND); + + primaryFBO->bind(); + + glBindTexture(GL_TEXTURE_2D, freeFBO->texture()); + glEnable(GL_TEXTURE_2D); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + renderFullscreenQuad(); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + + glDisable(GL_ALPHA_TEST); + + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } class RayHeightfieldIntersectionVisitor : public RayIntersectionVisitor { @@ -484,6 +619,24 @@ void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { } } +void MetavoxelSystem::loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations) { + program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + name); + program.link(); + + program.bind(); + program.setUniformValue("diffuseMap", 0); + program.setUniformValue("normalMap", 1); + program.setUniformValue("depthMap", 2); + program.setUniformValue("shadowMap", 3); + locations.shadowDistances = program.uniformLocation("shadowDistances"); + locations.shadowScale = program.uniformLocation("shadowScale"); + locations.near = program.uniformLocation("near"); + locations.depthScale = program.uniformLocation("depthScale"); + locations.depthTexCoordOffset = program.uniformLocation("depthTexCoordOffset"); + locations.depthTexCoordScale = program.uniformLocation("depthTexCoordScale"); + program.release(); +} + MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) : MetavoxelClient(node, updater) { } @@ -807,7 +960,6 @@ void HeightfieldBuffer::render(bool cursor) { glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); } else if (!_materials.isEmpty()) { - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind(); DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize); DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( @@ -817,6 +969,8 @@ void HeightfieldBuffer::render(bool cursor) { glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); + glDrawBuffers(sizeof(COLOR_DRAW_BUFFERS) / sizeof(COLOR_DRAW_BUFFERS[0]), COLOR_DRAW_BUFFERS); + glDepthFunc(GL_LEQUAL); glDepthMask(false); glEnable(GL_BLEND); @@ -825,18 +979,18 @@ void HeightfieldBuffer::render(bool cursor) { glPolygonOffset(-1.0f, -1.0f); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind(); + const DefaultMetavoxelRendererImplementation::SplatLocations& locations = + DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations(); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getSplatHeightScaleLocation(), 1.0f / _heightSize); + locations.heightScale, 1.0f / _heightSize); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getSplatTextureScaleLocation(), (float)_heightSize / innerSize); + locations.textureScale, (float)_heightSize / innerSize); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getSplatTextureOffsetLocation(), - _translation.x / _scale, _translation.z / _scale); + locations.splatTextureOffset, _translation.x / _scale, _translation.z / _scale); glBindTexture(GL_TEXTURE_2D, _materialTextureID); - const int TEXTURES_PER_SPLAT = 4; - for (int i = 0; i < _materials.size(); i += TEXTURES_PER_SPLAT) { + for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) { QVector4D scalesS, scalesT; for (int j = 0; j < SPLAT_COUNT; j++) { @@ -858,23 +1012,20 @@ void HeightfieldBuffer::render(bool cursor) { } const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getSplatTextureScalesSLocation(), scalesS); + locations.splatTextureScalesS, scalesS); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getSplatTextureScalesTLocation(), scalesT); + locations.splatTextureScalesT, scalesT); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getSplatTextureValueMinimaLocation(), + locations.textureValueMinima, (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getSplatTextureValueMaximaLocation(), + locations.textureValueMaxima, (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); } - glEnable(GL_ALPHA_TEST); - glBlendFunc(GL_DST_COLOR, GL_ZERO); - for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, 0); @@ -882,53 +1033,24 @@ void HeightfieldBuffer::render(bool cursor) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); - - if (Menu::getInstance()->isOptionChecked(MenuOption::SimpleShadows)) { - DefaultMetavoxelRendererImplementation::getShadowLightHeightfieldProgram().bind(); - DefaultMetavoxelRendererImplementation::getShadowLightHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getShadowLightHeightScaleLocation(), 1.0f / _heightSize); - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - DefaultMetavoxelRendererImplementation::getShadowMapHeightfieldProgram().bind(); - - } else if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { - DefaultMetavoxelRendererImplementation::getCascadedShadowLightHeightfieldProgram().bind(); - DefaultMetavoxelRendererImplementation::getCascadedShadowLightHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getCascadedShadowLightHeightScaleLocation(), 1.0f / _heightSize); - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - DefaultMetavoxelRendererImplementation::getCascadedShadowMapHeightfieldProgram().bind(); - - } else { - DefaultMetavoxelRendererImplementation::getLightHeightfieldProgram().bind(); - DefaultMetavoxelRendererImplementation::getLightHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getLightHeightScaleLocation(), 1.0f / _heightSize); - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - DefaultMetavoxelRendererImplementation::getHeightfieldProgram().bind(); - } - - glDisable(GL_POLYGON_OFFSET_FILL); - glDisable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glDepthFunc(GL_LESS); - glDepthMask(true); glActiveTexture(GL_TEXTURE0); + glDisable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDepthMask(true); + glDepthFunc(GL_LESS); + + glDrawBuffers(sizeof(COLOR_NORMAL_DRAW_BUFFERS) / sizeof(COLOR_NORMAL_DRAW_BUFFERS[0]), COLOR_NORMAL_DRAW_BUFFERS); + + DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind(); + } else { - int heightScaleLocation = DefaultMetavoxelRendererImplementation::getHeightScaleLocation(); - int colorScaleLocation = DefaultMetavoxelRendererImplementation::getColorScaleLocation(); - ProgramObject* program = &DefaultMetavoxelRendererImplementation::getHeightfieldProgram(); - if (Menu::getInstance()->isOptionChecked(MenuOption::SimpleShadows)) { - heightScaleLocation = DefaultMetavoxelRendererImplementation::getShadowMapHeightScaleLocation(); - colorScaleLocation = DefaultMetavoxelRendererImplementation::getShadowMapColorScaleLocation(); - program = &DefaultMetavoxelRendererImplementation::getShadowMapHeightfieldProgram(); - - } else if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { - heightScaleLocation = DefaultMetavoxelRendererImplementation::getCascadedShadowMapHeightScaleLocation(); - colorScaleLocation = DefaultMetavoxelRendererImplementation::getCascadedShadowMapColorScaleLocation(); - program = &DefaultMetavoxelRendererImplementation::getCascadedShadowMapHeightfieldProgram(); - } - program->setUniformValue(heightScaleLocation, 1.0f / _heightSize); - program->setUniformValue(colorScaleLocation, (float)_heightSize / innerSize); + DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( + DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize); + DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( + DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _colorTextureID); @@ -944,6 +1066,8 @@ void HeightfieldBuffer::render(bool cursor) { bufferPair.first.release(); bufferPair.second.release(); + + Application::getInstance()->getMetavoxels()->noteNeedToLight(); } QHash<int, HeightfieldBuffer::BufferPair> HeightfieldBuffer::_bufferPairs; @@ -959,7 +1083,7 @@ void HeightfieldPreview::render(const glm::vec3& translation, float scale) const glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - DefaultMetavoxelRendererImplementation::getHeightfieldProgram().bind(); + DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind(); glPushMatrix(); glTranslatef(translation.x, translation.y, translation.z); @@ -971,7 +1095,7 @@ void HeightfieldPreview::render(const glm::vec3& translation, float scale) const glPopMatrix(); - DefaultMetavoxelRendererImplementation::getHeightfieldProgram().release(); + DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release(); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); @@ -1025,8 +1149,89 @@ void VoxelBuffer::render(bool cursor) { glDrawRangeElements(GL_QUADS, 0, _vertexCount - 1, _indexCount, GL_UNSIGNED_INT, 0); + if (!_materials.isEmpty()) { + glDrawBuffers(sizeof(COLOR_DRAW_BUFFERS) / sizeof(COLOR_DRAW_BUFFERS[0]), COLOR_DRAW_BUFFERS); + + glDepthFunc(GL_LEQUAL); + glDepthMask(false); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().bind(); + const DefaultMetavoxelRendererImplementation::SplatLocations& locations = + DefaultMetavoxelRendererImplementation::getSplatVoxelLocations(); + + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setAttributeBuffer(locations.materials, + GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint)); + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().enableAttributeArray(locations.materials); + + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setAttributeBuffer(locations.materialWeights, + GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint)); + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().enableAttributeArray(locations.materialWeights); + + for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) { + QVector4D scalesS, scalesT; + + for (int j = 0; j < SPLAT_COUNT; j++) { + glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]); + int index = i + j; + if (index < _networkTextures.size()) { + const NetworkTexturePointer& texture = _networkTextures.at(index); + if (texture) { + MaterialObject* material = static_cast<MaterialObject*>(_materials.at(index).data()); + scalesS[j] = 1.0f / material->getScaleS(); + scalesT[j] = 1.0f / material->getScaleT(); + glBindTexture(GL_TEXTURE_2D, texture->getID()); + } else { + glBindTexture(GL_TEXTURE_2D, 0); + } + } else { + glBindTexture(GL_TEXTURE_2D, 0); + } + } + const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue( + locations.splatTextureScalesS, scalesS); + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue( + locations.splatTextureScalesT, scalesT); + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue( + locations.textureValueMinima, + (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, + (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue( + locations.textureValueMaxima, + (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, + (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); + glDrawRangeElements(GL_QUADS, 0, _vertexCount - 1, _indexCount, GL_UNSIGNED_INT, 0); + } + + for (int i = 0; i < SPLAT_COUNT; i++) { + glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); + glBindTexture(GL_TEXTURE_2D, 0); + } + + glActiveTexture(GL_TEXTURE0); + + glDisable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDepthMask(true); + glDepthFunc(GL_LESS); + + glDrawBuffers(sizeof(COLOR_NORMAL_DRAW_BUFFERS) / sizeof(COLOR_NORMAL_DRAW_BUFFERS[0]), COLOR_NORMAL_DRAW_BUFFERS); + + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materials); + DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materialWeights); + + DefaultMetavoxelRendererImplementation::getBaseVoxelProgram().bind(); + } + _vertexBuffer.release(); _indexBuffer.release(); + + Application::getInstance()->getMetavoxels()->noteNeedToLight(); } BufferDataAttribute::BufferDataAttribute(const QString& name) : @@ -1056,48 +1261,6 @@ void DefaultMetavoxelRendererImplementation::init() { _pointScaleLocation = _pointProgram.uniformLocation("pointScale"); _pointProgram.release(); - _heightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield.vert"); - _heightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield.frag"); - _heightfieldProgram.link(); - - _heightfieldProgram.bind(); - _heightfieldProgram.setUniformValue("heightMap", 0); - _heightfieldProgram.setUniformValue("diffuseMap", 1); - _heightScaleLocation = _heightfieldProgram.uniformLocation("heightScale"); - _colorScaleLocation = _heightfieldProgram.uniformLocation("colorScale"); - _heightfieldProgram.release(); - - _shadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield.vert"); - _shadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield_shadow_map.frag"); - _shadowMapHeightfieldProgram.link(); - - _shadowMapHeightfieldProgram.bind(); - _shadowMapHeightfieldProgram.setUniformValue("heightMap", 0); - _shadowMapHeightfieldProgram.setUniformValue("diffuseMap", 1); - _shadowMapHeightfieldProgram.setUniformValue("shadowMap", 2); - _shadowMapHeightScaleLocation = _shadowMapHeightfieldProgram.uniformLocation("heightScale"); - _shadowMapColorScaleLocation = _shadowMapHeightfieldProgram.uniformLocation("colorScale"); - _shadowMapHeightfieldProgram.release(); - - _cascadedShadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield.vert"); - _cascadedShadowMapHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield_cascaded_shadow_map.frag"); - _cascadedShadowMapHeightfieldProgram.link(); - - _cascadedShadowMapHeightfieldProgram.bind(); - _cascadedShadowMapHeightfieldProgram.setUniformValue("heightMap", 0); - _cascadedShadowMapHeightfieldProgram.setUniformValue("diffuseMap", 1); - _cascadedShadowMapHeightfieldProgram.setUniformValue("shadowMap", 2); - _cascadedShadowMapHeightScaleLocation = _cascadedShadowMapHeightfieldProgram.uniformLocation("heightScale"); - _cascadedShadowMapColorScaleLocation = _cascadedShadowMapHeightfieldProgram.uniformLocation("colorScale"); - _shadowDistancesLocation = _cascadedShadowMapHeightfieldProgram.uniformLocation("shadowDistances"); - _cascadedShadowMapHeightfieldProgram.release(); - _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_heightfield_base.vert"); _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + @@ -1111,60 +1274,7 @@ void DefaultMetavoxelRendererImplementation::init() { _baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale"); _baseHeightfieldProgram.release(); - _splatHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield_splat.vert"); - _splatHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield_splat.frag"); - _splatHeightfieldProgram.link(); - - _splatHeightfieldProgram.bind(); - _splatHeightfieldProgram.setUniformValue("heightMap", 0); - _splatHeightfieldProgram.setUniformValue("textureMap", 1); - _splatHeightfieldProgram.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT); - _splatHeightScaleLocation = _splatHeightfieldProgram.uniformLocation("heightScale"); - _splatTextureScaleLocation = _splatHeightfieldProgram.uniformLocation("textureScale"); - _splatTextureOffsetLocation = _splatHeightfieldProgram.uniformLocation("splatTextureOffset"); - _splatTextureScalesSLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesS"); - _splatTextureScalesTLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesT"); - _splatTextureValueMinimaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMinima"); - _splatTextureValueMaximaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMaxima"); - _splatHeightfieldProgram.release(); - - _lightHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield_light.vert"); - _lightHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield_light.frag"); - _lightHeightfieldProgram.link(); - - _lightHeightfieldProgram.bind(); - _lightHeightfieldProgram.setUniformValue("heightMap", 0); - _lightHeightScaleLocation = _lightHeightfieldProgram.uniformLocation("heightScale"); - _lightHeightfieldProgram.release(); - - _shadowLightHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield_light.vert"); - _shadowLightHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield_light_shadow_map.frag"); - _shadowLightHeightfieldProgram.link(); - - _shadowLightHeightfieldProgram.bind(); - _shadowLightHeightfieldProgram.setUniformValue("heightMap", 0); - _shadowLightHeightfieldProgram.setUniformValue("shadowMap", 2); - _shadowLightHeightScaleLocation = _shadowLightHeightfieldProgram.uniformLocation("heightScale"); - _shadowLightHeightfieldProgram.release(); - - _cascadedShadowLightHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield_light.vert"); - _cascadedShadowLightHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield_light_cascaded_shadow_map.frag"); - _cascadedShadowLightHeightfieldProgram.link(); - - _cascadedShadowLightHeightfieldProgram.bind(); - _cascadedShadowLightHeightfieldProgram.setUniformValue("heightMap", 0); - _cascadedShadowLightHeightfieldProgram.setUniformValue("shadowMap", 2); - _cascadedShadowLightHeightScaleLocation = _cascadedShadowLightHeightfieldProgram.uniformLocation("heightScale"); - _shadowLightDistancesLocation = _cascadedShadowLightHeightfieldProgram.uniformLocation("shadowDistances"); - _cascadedShadowLightHeightfieldProgram.release(); + loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_heightfield_cursor.vert"); @@ -1175,6 +1285,14 @@ void DefaultMetavoxelRendererImplementation::init() { _heightfieldCursorProgram.bind(); _heightfieldCursorProgram.setUniformValue("heightMap", 0); _heightfieldCursorProgram.release(); + + _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + "shaders/metavoxel_voxel_base.vert"); + _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/metavoxel_voxel_base.frag"); + _baseVoxelProgram.link(); + + loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations); } } @@ -1844,7 +1962,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { glm::vec3 center; glm::vec3 normal; const int MAX_MATERIALS_PER_VERTEX = 4; - quint8 materials[4]; + quint8 materials[] = { 0, 0, 0, 0 }; glm::vec4 materialWeights; float totalWeight = 0.0f; int red = 0, green = 0, blue = 0; @@ -1865,7 +1983,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { totalWeight += 1.0f; break; - } else if (materials[j] == 0.0f) { + } else if (materials[j] == 0) { materials[j] = crossing.material; materialWeights[j] = 1.0f; totalWeight += 1.0f; @@ -2149,38 +2267,22 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox _pointProgram.release(); + glDrawBuffers(sizeof(COLOR_NORMAL_DRAW_BUFFERS) / sizeof(COLOR_NORMAL_DRAW_BUFFERS[0]), COLOR_NORMAL_DRAW_BUFFERS); + glEnable(GL_CULL_FACE); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_EQUAL, 0.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - ProgramObject* program = &_heightfieldProgram; - if (Menu::getInstance()->getShadowsEnabled()) { - if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { - _cascadedShadowLightHeightfieldProgram.bind(); - _cascadedShadowLightHeightfieldProgram.setUniform(_shadowLightDistancesLocation, - Application::getInstance()->getShadowDistances()); - program = &_cascadedShadowMapHeightfieldProgram; - program->bind(); - program->setUniform(_shadowDistancesLocation, Application::getInstance()->getShadowDistances()); - - } else { - program = &_shadowMapHeightfieldProgram; - } - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); - glActiveTexture(GL_TEXTURE0); - } - - program->bind(); + _baseHeightfieldProgram.bind(); glEnableClientState(GL_TEXTURE_COORD_ARRAY); BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute()); data.guide(heightfieldRenderVisitor); - program->release(); + _baseHeightfieldProgram.release(); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); @@ -2189,57 +2291,63 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_ALPHA_TEST); - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - glEnable(GL_CULL_FACE); + _baseVoxelProgram.bind(); BufferRenderVisitor voxelRenderVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute()); data.guide(voxelRenderVisitor); + _baseVoxelProgram.release(); + + glDisable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); + + glDrawBuffers(sizeof(COLOR_DRAW_BUFFERS) / sizeof(COLOR_DRAW_BUFFERS[0]), COLOR_DRAW_BUFFERS); +} + +void DefaultMetavoxelRendererImplementation::loadSplatProgram(const char* type, + ProgramObject& program, SplatLocations& locations) { + program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + "shaders/metavoxel_" + type + "_splat.vert"); + program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/metavoxel_" + type + "_splat.frag"); + program.link(); + + program.bind(); + program.setUniformValue("heightMap", 0); + program.setUniformValue("textureMap", 1); + program.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT); + locations.heightScale = program.uniformLocation("heightScale"); + locations.textureScale = program.uniformLocation("textureScale"); + locations.splatTextureOffset = program.uniformLocation("splatTextureOffset"); + locations.splatTextureScalesS = program.uniformLocation("splatTextureScalesS"); + locations.splatTextureScalesT = program.uniformLocation("splatTextureScalesT"); + locations.textureValueMinima = program.uniformLocation("textureValueMinima"); + locations.textureValueMaxima = program.uniformLocation("textureValueMaxima"); + locations.materials = program.attributeLocation("materials"); + locations.materialWeights = program.attributeLocation("materialWeights"); + program.release(); } ProgramObject DefaultMetavoxelRendererImplementation::_pointProgram; int DefaultMetavoxelRendererImplementation::_pointScaleLocation; -ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldProgram; -int DefaultMetavoxelRendererImplementation::_heightScaleLocation; -int DefaultMetavoxelRendererImplementation::_colorScaleLocation; -ProgramObject DefaultMetavoxelRendererImplementation::_shadowMapHeightfieldProgram; -int DefaultMetavoxelRendererImplementation::_shadowMapHeightScaleLocation; -int DefaultMetavoxelRendererImplementation::_shadowMapColorScaleLocation; -ProgramObject DefaultMetavoxelRendererImplementation::_cascadedShadowMapHeightfieldProgram; -int DefaultMetavoxelRendererImplementation::_cascadedShadowMapHeightScaleLocation; -int DefaultMetavoxelRendererImplementation::_cascadedShadowMapColorScaleLocation; -int DefaultMetavoxelRendererImplementation::_shadowDistancesLocation; ProgramObject DefaultMetavoxelRendererImplementation::_baseHeightfieldProgram; int DefaultMetavoxelRendererImplementation::_baseHeightScaleLocation; int DefaultMetavoxelRendererImplementation::_baseColorScaleLocation; ProgramObject DefaultMetavoxelRendererImplementation::_splatHeightfieldProgram; -int DefaultMetavoxelRendererImplementation::_splatHeightScaleLocation; -int DefaultMetavoxelRendererImplementation::_splatTextureScaleLocation; -int DefaultMetavoxelRendererImplementation::_splatTextureOffsetLocation; -int DefaultMetavoxelRendererImplementation::_splatTextureScalesSLocation; -int DefaultMetavoxelRendererImplementation::_splatTextureScalesTLocation; -int DefaultMetavoxelRendererImplementation::_splatTextureValueMinimaLocation; -int DefaultMetavoxelRendererImplementation::_splatTextureValueMaximaLocation; -ProgramObject DefaultMetavoxelRendererImplementation::_lightHeightfieldProgram; -int DefaultMetavoxelRendererImplementation::_lightHeightScaleLocation; -ProgramObject DefaultMetavoxelRendererImplementation::_shadowLightHeightfieldProgram; -int DefaultMetavoxelRendererImplementation::_shadowLightHeightScaleLocation; -ProgramObject DefaultMetavoxelRendererImplementation::_cascadedShadowLightHeightfieldProgram; -int DefaultMetavoxelRendererImplementation::_cascadedShadowLightHeightScaleLocation; -int DefaultMetavoxelRendererImplementation::_shadowLightDistancesLocation; +DefaultMetavoxelRendererImplementation::SplatLocations DefaultMetavoxelRendererImplementation::_splatHeightfieldLocations; ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram; +ProgramObject DefaultMetavoxelRendererImplementation::_baseVoxelProgram; +ProgramObject DefaultMetavoxelRendererImplementation::_splatVoxelProgram; +DefaultMetavoxelRendererImplementation::SplatLocations DefaultMetavoxelRendererImplementation::_splatVoxelLocations; static void enableClipPlane(GLenum plane, float x, float y, float z, float w) { GLdouble coefficients[] = { x, y, z, w }; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index aa15dcc8db..54bee3d451 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -52,6 +52,12 @@ public: Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID); + void noteNeedToLight() { _needToLight = true; } + +signals: + + void rendering(); + protected: virtual MetavoxelClient* createClient(const SharedNodePointer& node); @@ -60,6 +66,18 @@ private: void guideToAugmented(MetavoxelVisitor& visitor, bool render = false); + class LightLocations { + public: + int shadowDistances; + int shadowScale; + int near; + int depthScale; + int depthTexCoordOffset; + int depthTexCoordScale; + }; + + static void loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations); + AttributePointer _pointBufferAttribute; AttributePointer _heightfieldBufferAttribute; AttributePointer _voxelBufferAttribute; @@ -67,6 +85,14 @@ private: MetavoxelLOD _lod; QReadWriteLock _lodLock; Frustum _frustum; + bool _needToLight; + + ProgramObject _directionalLight; + LightLocations _directionalLightLocations; + ProgramObject _directionalLightShadowMap; + LightLocations _directionalLightShadowMapLocations; + ProgramObject _directionalLightCascadedShadowMap; + LightLocations _directionalLightCascadedShadowMapLocations; }; /// Describes contents of a point in a point buffer. @@ -266,42 +292,33 @@ public: static void init(); - static ProgramObject& getHeightfieldProgram() { return _heightfieldProgram; } - static int getHeightScaleLocation() { return _heightScaleLocation; } - static int getColorScaleLocation() { return _colorScaleLocation; } - - static ProgramObject& getShadowMapHeightfieldProgram() { return _shadowMapHeightfieldProgram; } - static int getShadowMapHeightScaleLocation() { return _shadowMapHeightScaleLocation; } - static int getShadowMapColorScaleLocation() { return _shadowMapColorScaleLocation; } - - static ProgramObject& getCascadedShadowMapHeightfieldProgram() { return _cascadedShadowMapHeightfieldProgram; } - static int getCascadedShadowMapHeightScaleLocation() { return _cascadedShadowMapHeightScaleLocation; } - static int getCascadedShadowMapColorScaleLocation() { return _cascadedShadowMapColorScaleLocation; } - static ProgramObject& getBaseHeightfieldProgram() { return _baseHeightfieldProgram; } static int getBaseHeightScaleLocation() { return _baseHeightScaleLocation; } static int getBaseColorScaleLocation() { return _baseColorScaleLocation; } + class SplatLocations { + public: + int heightScale; + int textureScale; + int splatTextureOffset; + int splatTextureScalesS; + int splatTextureScalesT; + int textureValueMinima; + int textureValueMaxima; + int materials; + int materialWeights; + }; + static ProgramObject& getSplatHeightfieldProgram() { return _splatHeightfieldProgram; } - static int getSplatHeightScaleLocation() { return _splatHeightScaleLocation; } - static int getSplatTextureScaleLocation() { return _splatTextureScaleLocation; } - static int getSplatTextureOffsetLocation() { return _splatTextureOffsetLocation; } - static int getSplatTextureScalesSLocation() { return _splatTextureScalesSLocation; } - static int getSplatTextureScalesTLocation() { return _splatTextureScalesTLocation; } - static int getSplatTextureValueMinimaLocation() { return _splatTextureValueMinimaLocation; } - static int getSplatTextureValueMaximaLocation() { return _splatTextureValueMaximaLocation; } - - static ProgramObject& getLightHeightfieldProgram() { return _lightHeightfieldProgram; } - static int getLightHeightScaleLocation() { return _lightHeightScaleLocation; } - - static ProgramObject& getShadowLightHeightfieldProgram() { return _shadowLightHeightfieldProgram; } - static int getShadowLightHeightScaleLocation() { return _shadowLightHeightScaleLocation; } - - static ProgramObject& getCascadedShadowLightHeightfieldProgram() { return _cascadedShadowLightHeightfieldProgram; } - static int getCascadedShadowLightHeightScaleLocation() { return _cascadedShadowLightHeightScaleLocation; } + static const SplatLocations& getSplatHeightfieldLocations() { return _splatHeightfieldLocations; } static ProgramObject& getHeightfieldCursorProgram() { return _heightfieldCursorProgram; } + static ProgramObject& getBaseVoxelProgram() { return _baseVoxelProgram; } + + static ProgramObject& getSplatVoxelProgram() { return _splatVoxelProgram; } + static const SplatLocations& getSplatVoxelLocations() { return _splatVoxelLocations; } + Q_INVOKABLE DefaultMetavoxelRendererImplementation(); virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod); @@ -310,27 +327,18 @@ public: private: + static void loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations); + static ProgramObject _pointProgram; static int _pointScaleLocation; - static ProgramObject _heightfieldProgram; - static int _heightScaleLocation; - static int _colorScaleLocation; - - static ProgramObject _shadowMapHeightfieldProgram; - static int _shadowMapHeightScaleLocation; - static int _shadowMapColorScaleLocation; - - static ProgramObject _cascadedShadowMapHeightfieldProgram; - static int _cascadedShadowMapHeightScaleLocation; - static int _cascadedShadowMapColorScaleLocation; - static int _shadowDistancesLocation; - static ProgramObject _baseHeightfieldProgram; static int _baseHeightScaleLocation; static int _baseColorScaleLocation; static ProgramObject _splatHeightfieldProgram; + static SplatLocations _splatHeightfieldLocations; + static int _splatHeightScaleLocation; static int _splatTextureScaleLocation; static int _splatTextureOffsetLocation; @@ -339,17 +347,11 @@ private: static int _splatTextureValueMinimaLocation; static int _splatTextureValueMaximaLocation; - static ProgramObject _lightHeightfieldProgram; - static int _lightHeightScaleLocation; - - static ProgramObject _shadowLightHeightfieldProgram; - static int _shadowLightHeightScaleLocation; - - static ProgramObject _cascadedShadowLightHeightfieldProgram; - static int _cascadedShadowLightHeightScaleLocation; - static int _shadowLightDistancesLocation; - static ProgramObject _heightfieldCursorProgram; + + static ProgramObject _baseVoxelProgram; + static ProgramObject _splatVoxelProgram; + static SplatLocations _splatVoxelLocations; }; /// Base class for spanner renderers; provides clipping. diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index d960525817..bb07e83980 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -29,6 +29,7 @@ TextureCache::TextureCache() : _whiteTextureID(0), _blueTextureID(0), _primaryDepthTextureID(0), + _primaryNormalTextureID(0), _primaryFramebufferObject(NULL), _secondaryFramebufferObject(NULL), _tertiaryFramebufferObject(NULL), @@ -46,6 +47,7 @@ TextureCache::~TextureCache() { } if (_primaryFramebufferObject) { glDeleteTextures(1, &_primaryDepthTextureID); + glDeleteTextures(1, &_primaryNormalTextureID); } if (_primaryFramebufferObject) { @@ -71,6 +73,8 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) { _primaryFramebufferObject = NULL; glDeleteTextures(1, &_primaryDepthTextureID); _primaryDepthTextureID = 0; + glDeleteTextures(1, &_primaryNormalTextureID); + _primaryNormalTextureID = 0; } if (_secondaryFramebufferObject) { @@ -205,15 +209,22 @@ QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() { glGenTextures(1, &_primaryDepthTextureID); glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, _frameBufferSize.width(), _frameBufferSize.height(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glGenTextures(1, &_primaryNormalTextureID); + glBindTexture(GL_TEXTURE_2D, _primaryNormalTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _frameBufferSize.width(), _frameBufferSize.height(), + 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); _primaryFramebufferObject->bind(); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _primaryDepthTextureID, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _primaryNormalTextureID, 0); _primaryFramebufferObject->release(); } return _primaryFramebufferObject; @@ -225,6 +236,12 @@ GLuint TextureCache::getPrimaryDepthTextureID() { return _primaryDepthTextureID; } +GLuint TextureCache::getPrimaryNormalTextureID() { + // ensure that the primary framebuffer object is initialized before returning the normal texture id + getPrimaryFramebufferObject(); + return _primaryNormalTextureID; +} + QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() { if (!_secondaryFramebufferObject) { _secondaryFramebufferObject = createFramebufferObject(); @@ -278,6 +295,7 @@ bool TextureCache::eventFilter(QObject* watched, QEvent* event) { delete _primaryFramebufferObject; _primaryFramebufferObject = NULL; glDeleteTextures(1, &_primaryDepthTextureID); + glDeleteTextures(1, &_primaryNormalTextureID); } if (_secondaryFramebufferObject && _secondaryFramebufferObject->size() != size) { delete _secondaryFramebufferObject; diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index e1d69677f6..ce0e7661af 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -61,6 +61,9 @@ public: /// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering. GLuint getPrimaryDepthTextureID(); + /// Returns the ID of the primary framebuffer object's normal texture. + GLuint getPrimaryNormalTextureID(); + /// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full /// screen effects. QOpenGLFramebufferObject* getSecondaryFramebufferObject(); @@ -95,6 +98,7 @@ private: QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures; GLuint _primaryDepthTextureID; + GLuint _primaryNormalTextureID; QOpenGLFramebufferObject* _primaryFramebufferObject; QOpenGLFramebufferObject* _secondaryFramebufferObject; QOpenGLFramebufferObject* _tertiaryFramebufferObject; diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index b9e262f3fc..dc669365e8 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -971,11 +971,9 @@ ImportHeightfieldTool::ImportHeightfieldTool(MetavoxelEditor* editor) : connect(_height, &QAbstractButton::clicked, this, &ImportHeightfieldTool::selectHeightFile); _form->addRow("Color:", _color = new QPushButton()); connect(_color, &QAbstractButton::clicked, this, &ImportHeightfieldTool::selectColorFile); -} - -void ImportHeightfieldTool::render() { - HeightfieldTool::render(); - _preview.render(_translation->getValue(), _translation->getSingleStep()); + + connect(Application::getInstance()->getMetavoxels(), &MetavoxelSystem::rendering, + this, &ImportHeightfieldTool::renderPreview); } void ImportHeightfieldTool::apply() { @@ -1084,6 +1082,12 @@ void ImportHeightfieldTool::updatePreview() { _preview.setBuffers(buffers); } +void ImportHeightfieldTool::renderPreview() { + if (isVisible()) { + _preview.render(_translation->getValue(), _translation->getSingleStep()); + } +} + EraseHeightfieldTool::EraseHeightfieldTool(MetavoxelEditor* editor) : HeightfieldTool(editor, "Erase Heightfield") { diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index 96f4a2abe9..447d2197cd 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -283,8 +283,6 @@ public: ImportHeightfieldTool(MetavoxelEditor* editor); - virtual void render(); - protected: virtual void apply(); @@ -294,6 +292,7 @@ private slots: void selectHeightFile(); void selectColorFile(); void updatePreview(); + void renderPreview(); private: