mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 04:03:59 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into move-locations
This commit is contained in:
commit
1007f528f0
81 changed files with 2232 additions and 2165 deletions
|
@ -14,6 +14,9 @@
|
|||
// the depth texture
|
||||
uniform sampler2D depthTexture;
|
||||
|
||||
// the normal texture
|
||||
uniform sampler2D normalTexture;
|
||||
|
||||
// the random rotation texture
|
||||
uniform sampler2D rotationTexture;
|
||||
|
||||
|
@ -57,10 +60,11 @@ vec3 texCoordToViewSpace(vec2 texCoord) {
|
|||
}
|
||||
|
||||
void main(void) {
|
||||
vec3 rotationX = texture2D(rotationTexture, gl_TexCoord[0].st * noiseScale).rgb;
|
||||
vec3 rotationY = normalize(cross(rotationX, vec3(0.0, 0.0, 1.0)));
|
||||
mat3 rotation = mat3(rotationX, rotationY, cross(rotationX, rotationY));
|
||||
|
||||
vec3 rotationZ = texture2D(normalTexture, gl_TexCoord[0].st).xyz * 2.0 - vec3(1.0, 1.0, 1.0);
|
||||
vec3 rotationY = normalize(cross(rotationZ, texture2D(rotationTexture,
|
||||
gl_TexCoord[0].st * noiseScale).xyz - vec3(0.5, 0.5, 0.5)));
|
||||
mat3 rotation = mat3(cross(rotationY, rotationZ), rotationY, rotationZ);
|
||||
|
||||
vec3 center = texCoordToViewSpace(gl_TexCoord[0].st);
|
||||
|
||||
vec2 rdenominator = 1.0 / (rightTop - leftBottom);
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// cascaded_shadow_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/29/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 color in shadow
|
||||
varying vec4 shadowColor;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 position;
|
||||
|
||||
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));
|
||||
|
||||
gl_FragColor = mix(shadowColor, gl_Color, 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));
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// cascaded_shadow_map.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/29/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 color in shadow
|
||||
varying vec4 shadowColor;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 position;
|
||||
|
||||
void main(void) {
|
||||
// the shadow color includes only the ambient terms
|
||||
shadowColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient);
|
||||
|
||||
// the normal color includes diffuse
|
||||
vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
|
||||
gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position)));
|
||||
|
||||
// generate the shadow texture coordinates using the eye position
|
||||
position = gl_ModelViewMatrix * gl_Vertex;
|
||||
|
||||
// use the fixed function transform
|
||||
gl_Position = ftransform();
|
||||
}
|
17
interface/resources/shaders/deferred_light.vert
Normal file
17
interface/resources/shaders/deferred_light.vert
Normal file
|
@ -0,0 +1,17 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// deferred_light.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/18/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
|
||||
//
|
||||
|
||||
void main(void) {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
60
interface/resources/shaders/deferred_light_limited.vert
Normal file
60
interface/resources/shaders/deferred_light_limited.vert
Normal file
|
@ -0,0 +1,60 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// deferred_light_limited.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/19/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 radius (hard cutoff) of the light effect
|
||||
uniform float radius;
|
||||
|
||||
void main(void) {
|
||||
// find the right "right" direction
|
||||
vec3 firstRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(0.0, 1.0, 0.0));
|
||||
vec3 secondRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(1.0, 0.0, 0.0));
|
||||
vec3 right = mix(firstRightCandidate, secondRightCandidate, step(length(firstRightCandidate), length(secondRightCandidate)));
|
||||
right = normalize(right);
|
||||
|
||||
// and the "up"
|
||||
vec3 up = cross(right, gl_LightSource[1].spotDirection);
|
||||
|
||||
// and the "back," which depends on whether this is a spot light
|
||||
vec3 back = -gl_LightSource[1].spotDirection * step(gl_LightSource[1].spotCosCutoff, 0.0);
|
||||
|
||||
// find the eight corners of the bounds
|
||||
vec4 c0 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (-up - right + back), 1.0);
|
||||
vec4 c1 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (-up + right + back), 1.0);
|
||||
vec4 c2 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (up - right + back), 1.0);
|
||||
vec4 c3 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (up + right + back), 1.0);
|
||||
vec4 c4 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (-up - right + gl_LightSource[1].spotDirection), 1.0);
|
||||
vec4 c5 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (-up + right + gl_LightSource[1].spotDirection), 1.0);
|
||||
vec4 c6 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (up - right + gl_LightSource[1].spotDirection), 1.0);
|
||||
vec4 c7 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
||||
radius * (up + right + gl_LightSource[1].spotDirection), 1.0);
|
||||
|
||||
// find their projected extents
|
||||
vec2 extents = max(
|
||||
max(max(gl_Vertex.xy * (c0.xy / max(c0.w, 0.001)), gl_Vertex.xy * (c1.xy / max(c1.w, 0.001))),
|
||||
max(gl_Vertex.xy * (c2.xy / max(c2.w, 0.001)), gl_Vertex.xy * (c3.xy / max(c3.w, 0.001)))),
|
||||
max(max(gl_Vertex.xy * (c4.xy / max(c4.w, 0.001)), gl_Vertex.xy * (c5.xy / max(c5.w, 0.001))),
|
||||
max(gl_Vertex.xy * (c6.xy / max(c6.w, 0.001)), gl_Vertex.xy * (c7.xy / max(c7.w, 0.001)))));
|
||||
|
||||
// make sure they don't extend beyond the screen
|
||||
extents = min(extents, vec2(1.0, 1.0));
|
||||
|
||||
gl_Position = vec4(gl_Vertex.xy * extents, 0.0, 1.0);
|
||||
gl_TexCoord[0] = vec4(dot(gl_Position, gl_ObjectPlaneS[3]), dot(gl_Position, gl_ObjectPlaneT[3]), 0.0, 1.0);
|
||||
}
|
|
@ -17,10 +17,44 @@ uniform sampler2D diffuseMap;
|
|||
// the normal texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// the specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the depth texture
|
||||
uniform sampler2D depthMap;
|
||||
|
||||
// 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 base color based on OpenGL lighting model
|
||||
// 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, 0.0);
|
||||
|
||||
// get the normal from the map
|
||||
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);
|
||||
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor +
|
||||
gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute the specular multiplier (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(position)),
|
||||
normalizedNormal));
|
||||
|
||||
// add specular contribution
|
||||
vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st);
|
||||
gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ uniform sampler2D diffuseMap;
|
|||
// the normal texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// the specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the depth texture
|
||||
uniform sampler2D depthMap;
|
||||
|
||||
|
@ -51,15 +54,27 @@ void main(void) {
|
|||
vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position),
|
||||
dot(gl_EyePlaneR[shadowIndex], position));
|
||||
|
||||
// compute the color based on OpenGL lighting model, use the alpha from the normal map
|
||||
// get the normal from the 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);
|
||||
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
|
||||
|
||||
// average values from the shadow map
|
||||
float diffuse = dot(normalizedNormal, 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);
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
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);
|
||||
|
||||
// compute the specular multiplier (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// add specular contribution
|
||||
vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st);
|
||||
gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ uniform sampler2D diffuseMap;
|
|||
// the normal texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// the specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the depth texture
|
||||
uniform sampler2D depthMap;
|
||||
|
||||
|
@ -46,15 +49,27 @@ void main(void) {
|
|||
// 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
|
||||
// get the normal from the 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);
|
||||
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
|
||||
|
||||
// average values from the shadow map
|
||||
float diffuse = dot(normalizedNormal, 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);
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
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);
|
||||
|
||||
// compute the specular multiplier (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// add specular contribution
|
||||
vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st);
|
||||
gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a);
|
||||
}
|
||||
|
|
|
@ -11,43 +11,19 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// the maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 position;
|
||||
// the alpha threshold
|
||||
uniform float alphaThreshold;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
// add up the local lights
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(normalizedNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
|
||||
// set the diffuse, normal, specular data
|
||||
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0);
|
||||
}
|
||||
|
|
|
@ -11,31 +11,19 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
const int MAX_LOCAL_LIGHTS = 4;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 position;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
|
||||
// transform and store the normal for interpolation
|
||||
normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
|
||||
|
||||
// likewise with the position
|
||||
position = gl_ModelViewMatrix * gl_Vertex;
|
||||
|
||||
// pass along the vertex color
|
||||
gl_FrontColor = gl_Color;
|
||||
// pass along the diffuse color
|
||||
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
||||
|
||||
// and the texture coordinates
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
|
||||
// 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);
|
||||
|
||||
// use standard pipeline transform
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_cascaded_shadow_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/29/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// 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));
|
||||
|
||||
// add up the local lights
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(normalizedNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(normalizedNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_cascaded_shadow_normal_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/29/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the normal map texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// 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 interpolatedPosition;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
||||
// the interpolated tangent
|
||||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
|
||||
|
||||
// compute the index of the cascade to use and the corresponding texture coordinates
|
||||
int shadowIndex = int(dot(step(vec3(interpolatedPosition.z), shadowDistances), vec3(1.0, 1.0, 1.0)));
|
||||
vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], interpolatedPosition),
|
||||
dot(gl_EyePlaneT[shadowIndex], interpolatedPosition),
|
||||
dot(gl_EyePlaneR[shadowIndex], interpolatedPosition));
|
||||
|
||||
// add up the local lights
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(viewNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(viewNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
||||
normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_cascaded_shadow_normal_specular_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/29/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the normal map texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// the specular map texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// 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 interpolatedPosition;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
||||
// the interpolated tangent
|
||||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
|
||||
|
||||
// compute the index of the cascade to use and the corresponding texture coordinates
|
||||
int shadowIndex = int(dot(step(vec3(interpolatedPosition.z), shadowDistances), vec3(1.0, 1.0, 1.0)));
|
||||
vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], interpolatedPosition),
|
||||
dot(gl_EyePlaneT[shadowIndex], interpolatedPosition),
|
||||
dot(gl_EyePlaneR[shadowIndex], interpolatedPosition));
|
||||
|
||||
// add up the local lights
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(viewNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(viewNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
||||
normalize(vec4(interpolatedPosition.xyz, 0.0))), viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb *
|
||||
texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_cascaded_shadow_specular_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/29/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// 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 in view space
|
||||
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));
|
||||
|
||||
// add up the local lights
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(normalizedNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(normalizedNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb *
|
||||
texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
}
|
|
@ -11,23 +11,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// the maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the normal map texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 interpolatedPosition;
|
||||
// the alpha threshold
|
||||
uniform float alphaThreshold;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
@ -36,30 +27,17 @@ varying vec4 interpolatedNormal;
|
|||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
// compute the view normal from the various bits
|
||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
|
||||
|
||||
// add up the local lights
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5);
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(viewNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(viewNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
||||
normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
|
||||
// set the diffuse, normal, specular data
|
||||
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||
gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0);
|
||||
}
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
// the tangent vector
|
||||
attribute vec3 tangent;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 interpolatedPosition;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
||||
|
@ -24,22 +21,16 @@ varying vec4 interpolatedNormal;
|
|||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
|
||||
// transform and store the position, normal and tangent for interpolation
|
||||
interpolatedPosition = gl_ModelViewMatrix * gl_Vertex;
|
||||
// transform and store the normal and tangent for interpolation
|
||||
interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0);
|
||||
interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0);
|
||||
|
||||
// pass along the vertex color
|
||||
gl_FrontColor = gl_Color;
|
||||
// pass along the diffuse color
|
||||
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
||||
|
||||
// and the texture coordinates
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
|
||||
// and the shadow texture coordinates
|
||||
gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], interpolatedPosition), dot(gl_EyePlaneT[0], interpolatedPosition),
|
||||
dot(gl_EyePlaneR[0], interpolatedPosition), 1.0);
|
||||
|
||||
// use standard pipeline transform
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
|
|
@ -11,15 +11,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// the maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
|
@ -29,8 +20,8 @@ uniform sampler2D normalMap;
|
|||
// the specular map texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 interpolatedPosition;
|
||||
// the alpha threshold
|
||||
uniform float alphaThreshold;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
@ -39,31 +30,18 @@ varying vec4 interpolatedNormal;
|
|||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
// compute the view normal from the various bits
|
||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
|
||||
|
||||
// add up the local lights
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5);
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(viewNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(viewNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
||||
normalize(vec4(interpolatedPosition.xyz, 0.0))), viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb *
|
||||
texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
// set the diffuse, normal, specular data
|
||||
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||
gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb,
|
||||
gl_FrontMaterial.shininess / 128.0);
|
||||
}
|
||||
|
|
|
@ -13,5 +13,5 @@
|
|||
|
||||
void main(void) {
|
||||
// fixed color for now (we may eventually want to use texture alpha)
|
||||
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
gl_FragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_shadow_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/23/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// 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 position
|
||||
varying vec4 position;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
// add up the local lights
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(normalizedNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(normalizedNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_shadow_normal_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/23/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the normal map texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// the shadow texture
|
||||
uniform sampler2DShadow shadowMap;
|
||||
|
||||
// the inverse of the size of the shadow map
|
||||
const float shadowScale = 1.0 / 2048.0;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 interpolatedPosition;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
||||
// the interpolated tangent
|
||||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
|
||||
|
||||
// add up the local lights
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(viewNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(viewNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
||||
normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_shadow_normal_specular_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/23/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the normal map texture
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
// the specular map texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the shadow texture
|
||||
uniform sampler2DShadow shadowMap;
|
||||
|
||||
// the inverse of the size of the shadow map
|
||||
const float shadowScale = 1.0 / 2048.0;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 interpolatedPosition;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
||||
// the interpolated tangent
|
||||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
|
||||
|
||||
// add up the local lights
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(viewNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(viewNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
||||
normalize(vec4(interpolatedPosition.xyz, 0.0))), viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb *
|
||||
texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_shadow_specular_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/23/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 maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the shadow texture
|
||||
uniform sampler2DShadow shadowMap;
|
||||
|
||||
// the inverse of the size of the shadow map
|
||||
const float shadowScale = 1.0 / 2048.0;
|
||||
|
||||
// the interpolated position in view space
|
||||
varying vec4 position;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
// add up the local lights
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(normalizedNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(normalizedNormal, 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) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb *
|
||||
texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
}
|
|
@ -11,47 +11,23 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// the maximum number of local lights to apply
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
// the color of each local light
|
||||
uniform vec4 localLightColors[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the direction of each local light
|
||||
uniform vec4 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
// the diffuse texture
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
// the specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the interpolated position in view space
|
||||
varying vec4 position;
|
||||
// the alpha threshold
|
||||
uniform float alphaThreshold;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
// add up the local lights
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
vec4 localLight = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
localLight += localLightColors[i] * max(0.0, dot(normalizedNormal, localLightDirections[i]));
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + localLight);
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = vec4(base.rgb, gl_FrontMaterial.diffuse.a) * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb *
|
||||
texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
// set the diffuse, normal, specular data
|
||||
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb,
|
||||
gl_FrontMaterial.shininess / 128.0);
|
||||
}
|
||||
|
|
20
interface/resources/shaders/model_translucent.frag
Normal file
20
interface/resources/shaders/model_translucent.frag
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// model_translucent.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/19/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;
|
||||
|
||||
void main(void) {
|
||||
// set the diffuse data
|
||||
gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||
}
|
|
@ -26,6 +26,9 @@ const float amplitude = 0.5;
|
|||
// the position in model space
|
||||
varying vec3 position;
|
||||
|
||||
// the normal in view space
|
||||
varying vec4 normal;
|
||||
|
||||
// gradient based on gradients from cube edge centers rather than random from texture lookup
|
||||
float randomEdgeGrad(int hash, vec3 position){
|
||||
int h = int(mod(hash, 16));
|
||||
|
@ -114,7 +117,8 @@ void main(void) {
|
|||
|
||||
// apply vertex lighting
|
||||
vec3 color = gl_Color.rgb * vec3(noise, noise, noise);
|
||||
gl_FragColor = vec4(color, 1);
|
||||
gl_FragData[0] = vec4(color, 1);
|
||||
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -156,4 +160,4 @@ float perlin(vec3 location) {
|
|||
mix(mix(ffcv, cfcv, params.x), mix(fccv, cccv, params.x), params.y),
|
||||
params.z);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
// the position in model space
|
||||
varying vec3 position;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
position = gl_Vertex.xyz;
|
||||
vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
|
||||
gl_FrontColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient +
|
||||
gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position)));
|
||||
normal = vec4(gl_NormalMatrix * gl_Normal, 0.0);
|
||||
gl_FrontColor = gl_Color;
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
|
69
interface/resources/shaders/point_light.frag
Normal file
69
interface/resources/shaders/point_light.frag
Normal file
|
@ -0,0 +1,69 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// spot_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/18/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 specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the depth texture
|
||||
uniform sampler2D depthMap;
|
||||
|
||||
// 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;
|
||||
|
||||
// the radius (hard cutoff) of the light effect
|
||||
uniform float radius;
|
||||
|
||||
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);
|
||||
|
||||
// get the normal from the map
|
||||
vec4 normal = texture2D(normalMap, gl_TexCoord[0].st);
|
||||
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 lightVector = gl_LightSource[1].position - position;
|
||||
float lightDistance = length(lightVector);
|
||||
lightVector = lightVector / lightDistance;
|
||||
float diffuse = dot(normalizedNormal, lightVector);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightProduct[1].ambient +
|
||||
gl_FrontLightProduct[1].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute attenuation based on distance, etc.
|
||||
float attenuation = step(lightDistance, radius) / dot(vec3(gl_LightSource[1].constantAttenuation,
|
||||
gl_LightSource[1].linearAttenuation, gl_LightSource[1].quadraticAttenuation),
|
||||
vec3(1.0, lightDistance, lightDistance * lightDistance));
|
||||
|
||||
// add base to specular, modulate by attenuation
|
||||
float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st);
|
||||
gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// shadow_map.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 11/21/13.
|
||||
// Copyright 2013 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
|
||||
//
|
||||
|
||||
uniform sampler2DShadow shadowMap;
|
||||
|
||||
// the inverse of the size of the shadow map
|
||||
const float shadowScale = 1.0 / 2048.0;
|
||||
|
||||
// the color in shadow
|
||||
varying vec4 shadowColor;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = mix(shadowColor, gl_Color, 0.25 *
|
||||
(shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, -shadowScale, 0.0)).r +
|
||||
shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, shadowScale, 0.0)).r +
|
||||
shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, -shadowScale, 0.0)).r +
|
||||
shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, shadowScale, 0.0)).r));
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// shadow_map.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 3/27/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 color in shadow
|
||||
varying vec4 shadowColor;
|
||||
|
||||
void main(void) {
|
||||
// the shadow color includes only the ambient terms
|
||||
shadowColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient);
|
||||
|
||||
// the normal color includes diffuse
|
||||
vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
|
||||
gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position)));
|
||||
|
||||
// generate the shadow texture coordinates using the eye position
|
||||
vec4 eyePosition = gl_ModelViewMatrix * gl_Vertex;
|
||||
gl_TexCoord[0] = vec4(dot(gl_EyePlaneS[0], eyePosition), dot(gl_EyePlaneT[0], eyePosition),
|
||||
dot(gl_EyePlaneR[0], eyePosition), 1.0);
|
||||
|
||||
// use the fixed function transform
|
||||
gl_Position = ftransform();
|
||||
}
|
25
interface/resources/shaders/simple.frag
Normal file
25
interface/resources/shaders/simple.frag
Normal file
|
@ -0,0 +1,25 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// simple.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/15/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;
|
||||
|
||||
// the glow intensity
|
||||
uniform float glowIntensity;
|
||||
|
||||
void main(void) {
|
||||
// set the diffuse, normal, specular data
|
||||
gl_FragData[0] = vec4(gl_Color.rgb, glowIntensity);
|
||||
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0);
|
||||
}
|
26
interface/resources/shaders/simple.vert
Normal file
26
interface/resources/shaders/simple.vert
Normal file
|
@ -0,0 +1,26 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// simple.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/15/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 = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
|
||||
|
||||
// pass along the diffuse color
|
||||
gl_FrontColor = gl_Color;
|
||||
|
||||
// use standard pipeline transform
|
||||
gl_Position = ftransform();
|
||||
}
|
|
@ -19,14 +19,11 @@ uniform mat4 clusterMatrices[MAX_CLUSTERS];
|
|||
attribute vec4 clusterIndices;
|
||||
attribute vec4 clusterWeights;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 position;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 normal;
|
||||
|
||||
void main(void) {
|
||||
position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
normal = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])];
|
||||
|
@ -35,17 +32,13 @@ void main(void) {
|
|||
normal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight;
|
||||
}
|
||||
|
||||
position = gl_ModelViewMatrix * position;
|
||||
normal = normalize(gl_ModelViewMatrix * normal);
|
||||
|
||||
// pass along the vertex color
|
||||
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
// pass along the diffuse color
|
||||
gl_FrontColor = gl_FrontMaterial.diffuse;
|
||||
|
||||
// and the texture coordinates
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
|
||||
// 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);
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * position;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * position;
|
||||
}
|
||||
|
|
|
@ -22,9 +22,6 @@ attribute vec3 tangent;
|
|||
attribute vec4 clusterIndices;
|
||||
attribute vec4 clusterWeights;
|
||||
|
||||
// the interpolated position
|
||||
varying vec4 interpolatedPosition;
|
||||
|
||||
// the interpolated normal
|
||||
varying vec4 interpolatedNormal;
|
||||
|
||||
|
@ -32,7 +29,7 @@ varying vec4 interpolatedNormal;
|
|||
varying vec4 interpolatedTangent;
|
||||
|
||||
void main(void) {
|
||||
interpolatedPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 interpolatedPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
|
@ -42,19 +39,14 @@ void main(void) {
|
|||
interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight;
|
||||
interpolatedTangent += clusterMatrix * vec4(tangent, 0.0) * clusterWeight;
|
||||
}
|
||||
interpolatedPosition = gl_ModelViewMatrix * interpolatedPosition;
|
||||
interpolatedNormal = gl_ModelViewMatrix * interpolatedNormal;
|
||||
interpolatedTangent = gl_ModelViewMatrix * interpolatedTangent;
|
||||
|
||||
// pass along the vertex color
|
||||
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
// pass along the diffuse color
|
||||
gl_FrontColor = gl_FrontMaterial.diffuse;
|
||||
|
||||
// and the texture coordinates
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
|
||||
// and the shadow texture coordinates
|
||||
gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], interpolatedPosition), dot(gl_EyePlaneT[0], interpolatedPosition),
|
||||
dot(gl_EyePlaneR[0], interpolatedPosition), 1.0);
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * interpolatedPosition;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition;
|
||||
}
|
||||
|
|
71
interface/resources/shaders/spot_light.frag
Normal file
71
interface/resources/shaders/spot_light.frag
Normal file
|
@ -0,0 +1,71 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// spot_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/18/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 specular texture
|
||||
uniform sampler2D specularMap;
|
||||
|
||||
// the depth texture
|
||||
uniform sampler2D depthMap;
|
||||
|
||||
// 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;
|
||||
|
||||
// the radius (hard cutoff) of the light effect
|
||||
uniform float radius;
|
||||
|
||||
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);
|
||||
|
||||
// get the normal from the map
|
||||
vec4 normal = texture2D(normalMap, gl_TexCoord[0].st);
|
||||
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 lightVector = gl_LightSource[1].position - position;
|
||||
float lightDistance = length(lightVector);
|
||||
lightVector = lightVector / lightDistance;
|
||||
float diffuse = dot(normalizedNormal, lightVector);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightProduct[1].ambient +
|
||||
gl_FrontLightProduct[1].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute attenuation based on spot angle, distance, etc.
|
||||
float cosSpotAngle = max(-dot(lightVector.xyz, gl_LightSource[1].spotDirection), 0.0);
|
||||
float attenuation = step(lightDistance, radius) * step(gl_LightSource[1].spotCosCutoff, cosSpotAngle) *
|
||||
pow(cosSpotAngle, gl_LightSource[1].spotExponent) / dot(vec3(gl_LightSource[1].constantAttenuation,
|
||||
gl_LightSource[1].linearAttenuation, gl_LightSource[1].quadraticAttenuation),
|
||||
vec3(1.0, lightDistance, lightDistance * lightDistance));
|
||||
|
||||
// add base to specular, modulate by attenuation
|
||||
float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st);
|
||||
gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0);
|
||||
}
|
21
interface/resources/shaders/voxel.frag
Normal file
21
interface/resources/shaders/voxel.frag
Normal file
|
@ -0,0 +1,21 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// voxel.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/11/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 color and normal directly
|
||||
gl_FragData[0] = gl_Color;
|
||||
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
}
|
26
interface/resources/shaders/voxel.vert
Normal file
26
interface/resources/shaders/voxel.vert
Normal file
|
@ -0,0 +1,26 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// voxel.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/11/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 normal for interpolation
|
||||
normal = vec4(gl_NormalMatrix * gl_Normal, 0.0);
|
||||
|
||||
// use the standard position
|
||||
gl_Position = ftransform();
|
||||
|
||||
// store the color directly
|
||||
gl_FrontColor = vec4(gl_Color.rgb, 0.0);
|
||||
}
|
|
@ -695,8 +695,6 @@ void Application::paintGL() {
|
|||
displaySide(whichCamera);
|
||||
glPopMatrix();
|
||||
|
||||
_glowEffect.render();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
||||
renderRearViewMirror(_mirrorViewRect);
|
||||
|
||||
|
@ -704,6 +702,8 @@ void Application::paintGL() {
|
|||
_rearMirrorTools->render(true);
|
||||
}
|
||||
|
||||
_glowEffect.render();
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("renderOverlay");
|
||||
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
||||
|
@ -1751,6 +1751,7 @@ void Application::init() {
|
|||
|
||||
_environment.init();
|
||||
|
||||
_deferredLightingEffect.init();
|
||||
_glowEffect.init();
|
||||
_ambientOcclusionEffect.init();
|
||||
_voxelShader.init();
|
||||
|
@ -2706,7 +2707,6 @@ void Application::updateShadowMap() {
|
|||
const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f };
|
||||
const GLfloat WORLD_DIFFUSE_COLOR[] = { 0.6f, 0.525f, 0.525f };
|
||||
const GLfloat WORLD_SPECULAR_COLOR[] = { 0.94f, 0.94f, 0.737f, 1.0f };
|
||||
const GLfloat NO_SPECULAR_COLOR[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
void Application::setupWorldLight() {
|
||||
|
||||
|
@ -2727,7 +2727,8 @@ void Application::setupWorldLight() {
|
|||
QImage Application::renderAvatarBillboard() {
|
||||
_textureCache.getPrimaryFramebufferObject()->bind();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
// the "glow" here causes an alpha of one
|
||||
Glower glower;
|
||||
|
||||
const int BILLBOARD_SIZE = 64;
|
||||
renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true);
|
||||
|
@ -2735,8 +2736,6 @@ QImage Application::renderAvatarBillboard() {
|
|||
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
||||
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
_textureCache.getPrimaryFramebufferObject()->release();
|
||||
|
||||
return image;
|
||||
|
@ -2840,6 +2839,8 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
_deferredLightingEffect.prepare();
|
||||
|
||||
if (!selfAvatarOnly) {
|
||||
// draw a red sphere
|
||||
float originSphereRadius = 0.05f;
|
||||
|
@ -2848,15 +2849,19 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
glutSolidSphere(originSphereRadius, 15, 15);
|
||||
glPopMatrix();
|
||||
|
||||
// disable specular lighting for ground and voxels
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR);
|
||||
|
||||
// draw the audio reflector overlay
|
||||
{
|
||||
PerformanceTimer perfTimer("audio");
|
||||
_audioReflector.render();
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
|
||||
PerformanceTimer perfTimer("buckyBalls");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::displaySide() ... bucky balls...");
|
||||
_buckyBalls.render();
|
||||
}
|
||||
|
||||
// Draw voxels
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||
PerformanceTimer perfTimer("voxels");
|
||||
|
@ -2873,13 +2878,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
_metavoxels.render();
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
|
||||
PerformanceTimer perfTimer("buckyBalls");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::displaySide() ... bucky balls...");
|
||||
_buckyBalls.render();
|
||||
}
|
||||
|
||||
// render particles...
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) {
|
||||
PerformanceTimer perfTimer("particles");
|
||||
|
@ -2903,27 +2901,34 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
"Application::displaySide() ... AmbientOcclusion...");
|
||||
_ambientOcclusionEffect.render();
|
||||
}
|
||||
|
||||
// restore default, white specular
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, WORLD_SPECULAR_COLOR);
|
||||
|
||||
_nodeBoundsDisplay.draw();
|
||||
|
||||
}
|
||||
|
||||
bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
|
||||
{
|
||||
PerformanceTimer perfTimer("avatars");
|
||||
|
||||
_avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly);
|
||||
_avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,
|
||||
false, selfAvatarOnly);
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("lighting");
|
||||
_deferredLightingEffect.render();
|
||||
}
|
||||
|
||||
//Render the sixense lasers
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
|
||||
_myAvatar->renderLaserPointers();
|
||||
}
|
||||
{
|
||||
PerformanceTimer perfTimer("avatarsPostLighting");
|
||||
_avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,
|
||||
true, selfAvatarOnly);
|
||||
}
|
||||
|
||||
//Render the sixense lasers
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
|
||||
_myAvatar->renderLaserPointers();
|
||||
}
|
||||
|
||||
if (!selfAvatarOnly) {
|
||||
_nodeBoundsDisplay.draw();
|
||||
|
||||
// Render the world box
|
||||
if (whichCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) {
|
||||
|
@ -2998,7 +3003,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom
|
|||
float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
|
||||
|
||||
// allow 3DTV/Oculus to override parameters from camera
|
||||
_viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
_displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
if (OculusManager::isConnected()) {
|
||||
OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
|
||||
|
@ -3797,8 +3802,8 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
|||
scriptEngine->getEntityScriptingInterface()->setPacketSender(&_entityEditSender);
|
||||
scriptEngine->getEntityScriptingInterface()->setEntityTree(_entities.getTree());
|
||||
|
||||
// model has some custom types
|
||||
Model::registerMetaTypes(scriptEngine);
|
||||
// AvatarManager has some custom types
|
||||
AvatarManager::registerMetaTypes(scriptEngine);
|
||||
|
||||
// hook our avatar object into this script engine
|
||||
scriptEngine->setAvatarData(_myAvatar, "MyAvatar"); // leave it as a MyAvatar class to expose thrust features
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "entities/EntityTreeRenderer.h"
|
||||
#include "particles/ParticleTreeRenderer.h"
|
||||
#include "renderer/AmbientOcclusionEffect.h"
|
||||
#include "renderer/DeferredLightingEffect.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
#include "renderer/GlowEffect.h"
|
||||
#include "renderer/PointShader.h"
|
||||
|
@ -247,6 +248,7 @@ public:
|
|||
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||
AnimationCache* getAnimationCache() { return &_animationCache; }
|
||||
TextureCache* getTextureCache() { return &_textureCache; }
|
||||
DeferredLightingEffect* getDeferredLightingEffect() { return &_deferredLightingEffect; }
|
||||
GlowEffect* getGlowEffect() { return &_glowEffect; }
|
||||
ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; }
|
||||
|
||||
|
@ -559,6 +561,7 @@ private:
|
|||
AnimationCache _animationCache;
|
||||
TextureCache _textureCache;
|
||||
|
||||
DeferredLightingEffect _deferredLightingEffect;
|
||||
GlowEffect _glowEffect;
|
||||
AmbientOcclusionEffect _ambientOcclusionEffect;
|
||||
VoxelShader _voxelShader;
|
||||
|
|
|
@ -509,7 +509,7 @@ void Audio::handleAudioInput() {
|
|||
if (!_muted && (_audioSourceInjectEnabled || _peqEnabled)) {
|
||||
|
||||
int16_t* inputFrameData = (int16_t*)inputByteArray.data();
|
||||
const int inputFrameCount = inputByteArray.size() / sizeof(int16_t);
|
||||
const uint32_t inputFrameCount = inputByteArray.size() / sizeof(int16_t);
|
||||
|
||||
_inputFrameBuffer.copyFrames(1, inputFrameCount, inputFrameData, false /*copy in*/);
|
||||
|
||||
|
|
|
@ -369,7 +369,6 @@ Menu::Menu() :
|
|||
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, "None", 0, true));
|
||||
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::SimpleShadows, 0, false));
|
||||
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::CascadedShadows, 0, false));
|
||||
addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::AvatarsReceiveShadows, 0, true);
|
||||
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, Qt::Key_Asterisk, true);
|
||||
|
|
|
@ -346,7 +346,6 @@ namespace MenuOption {
|
|||
const QString AudioSourcePinkNoise = "Pink Noise";
|
||||
const QString AudioSourceSine440 = "Sine 440hz";
|
||||
const QString Avatars = "Avatars";
|
||||
const QString AvatarsReceiveShadows = "Avatars Receive Shadows";
|
||||
const QString Bandwidth = "Bandwidth Display";
|
||||
const QString BandwidthDetails = "Bandwidth Details";
|
||||
const QString BlueSpeechSphere = "Blue Sphere While Speaking";
|
||||
|
|
|
@ -51,12 +51,6 @@ 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() {
|
||||
|
@ -127,150 +121,18 @@ 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()->getDisplayViewFrustum();
|
||||
_frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(),
|
||||
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());
|
||||
|
||||
// get the viewport side (left, right, both)
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
const int VIEWPORT_X_INDEX = 0;
|
||||
const int VIEWPORT_WIDTH_INDEX = 2;
|
||||
float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width();
|
||||
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width();
|
||||
|
||||
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->nearLocation, nearVal);
|
||||
program->setUniformValue(locations->depthScale, (farVal - nearVal) / farVal);
|
||||
float nearScale = -1.0f / nearVal;
|
||||
float sScale = 1.0f / sWidth;
|
||||
float depthTexCoordScaleS = (right - left) * nearScale * sScale;
|
||||
program->setUniformValue(locations->depthTexCoordOffset, left * nearScale - sMin * depthTexCoordScaleS,
|
||||
bottom * nearScale);
|
||||
program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, (top - bottom) * nearScale);
|
||||
|
||||
renderFullscreenQuad(sMin, sMin + sWidth);
|
||||
|
||||
program->release();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
|
||||
} else {
|
||||
_directionalLight.bind();
|
||||
renderFullscreenQuad(sMin, sMin + sWidth);
|
||||
_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(sMin, sMin + sWidth);
|
||||
|
||||
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 {
|
||||
|
@ -630,24 +492,6 @@ 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.nearLocation = 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) {
|
||||
}
|
||||
|
@ -980,7 +824,7 @@ 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);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(false);
|
||||
|
@ -1053,7 +897,7 @@ void HeightfieldBuffer::render(bool cursor) {
|
|||
glDepthMask(true);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
glDrawBuffers(sizeof(COLOR_NORMAL_DRAW_BUFFERS) / sizeof(COLOR_NORMAL_DRAW_BUFFERS[0]), COLOR_NORMAL_DRAW_BUFFERS);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
|
||||
|
||||
|
@ -1077,14 +921,12 @@ void HeightfieldBuffer::render(bool cursor) {
|
|||
|
||||
bufferPair.first.release();
|
||||
bufferPair.second.release();
|
||||
|
||||
Application::getInstance()->getMetavoxels()->noteNeedToLight();
|
||||
}
|
||||
|
||||
QHash<int, HeightfieldBuffer::BufferPair> HeightfieldBuffer::_bufferPairs;
|
||||
|
||||
void HeightfieldPreview::render(const glm::vec3& translation, float scale) const {
|
||||
glDrawBuffers(sizeof(COLOR_NORMAL_DRAW_BUFFERS) / sizeof(COLOR_NORMAL_DRAW_BUFFERS[0]), COLOR_NORMAL_DRAW_BUFFERS);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
@ -1117,7 +959,7 @@ void HeightfieldPreview::render(const glm::vec3& translation, float scale) const
|
|||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glDrawBuffers(sizeof(COLOR_DRAW_BUFFERS) / sizeof(COLOR_DRAW_BUFFERS[0]), COLOR_DRAW_BUFFERS);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
}
|
||||
|
||||
VoxelBuffer::VoxelBuffer(const QVector<VoxelPoint>& vertices, const QVector<int>& indices,
|
||||
|
@ -1165,7 +1007,7 @@ 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);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(false);
|
||||
|
@ -1235,7 +1077,7 @@ void VoxelBuffer::render(bool cursor) {
|
|||
glDepthMask(true);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
glDrawBuffers(sizeof(COLOR_NORMAL_DRAW_BUFFERS) / sizeof(COLOR_NORMAL_DRAW_BUFFERS[0]), COLOR_NORMAL_DRAW_BUFFERS);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materials);
|
||||
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materialWeights);
|
||||
|
@ -1245,8 +1087,6 @@ void VoxelBuffer::render(bool cursor) {
|
|||
|
||||
_vertexBuffer.release();
|
||||
_indexBuffer.release();
|
||||
|
||||
Application::getInstance()->getMetavoxels()->noteNeedToLight();
|
||||
}
|
||||
|
||||
BufferDataAttribute::BufferDataAttribute(const QString& name) :
|
||||
|
@ -2282,7 +2122,7 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
|
|||
|
||||
_pointProgram.release();
|
||||
|
||||
glDrawBuffers(sizeof(COLOR_NORMAL_DRAW_BUFFERS) / sizeof(COLOR_NORMAL_DRAW_BUFFERS[0]), COLOR_NORMAL_DRAW_BUFFERS);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
|
@ -2325,7 +2165,7 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
|
|||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glDrawBuffers(sizeof(COLOR_DRAW_BUFFERS) / sizeof(COLOR_DRAW_BUFFERS[0]), COLOR_DRAW_BUFFERS);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
}
|
||||
|
||||
void DefaultMetavoxelRendererImplementation::loadSplatProgram(const char* type,
|
||||
|
@ -2479,9 +2319,16 @@ void StaticModelRenderer::renderUnclipped(float alpha, Mode mode) {
|
|||
_model->render(alpha);
|
||||
}
|
||||
|
||||
bool StaticModelRenderer::findRayIntersection(RayIntersectionInfo& intersection,
|
||||
const glm::vec3& clipMinimum, float clipSize) const {
|
||||
return _model->findRayIntersection(intersection);
|
||||
bool StaticModelRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const {
|
||||
RayIntersectionInfo info;
|
||||
info._rayStart = origin;
|
||||
info._rayDirection = direction;
|
||||
if (!_model->findRayIntersection(info)) {
|
||||
return false;
|
||||
}
|
||||
distance = info._hitDistance;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StaticModelRenderer::applyTranslation(const glm::vec3& translation) {
|
||||
|
|
|
@ -52,8 +52,6 @@ public:
|
|||
|
||||
Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID);
|
||||
|
||||
void noteNeedToLight() { _needToLight = true; }
|
||||
|
||||
signals:
|
||||
|
||||
void rendering();
|
||||
|
@ -66,18 +64,6 @@ private:
|
|||
|
||||
void guideToAugmented(MetavoxelVisitor& visitor, bool render = false);
|
||||
|
||||
class LightLocations {
|
||||
public:
|
||||
int shadowDistances;
|
||||
int shadowScale;
|
||||
int nearLocation;
|
||||
int depthScale;
|
||||
int depthTexCoordOffset;
|
||||
int depthTexCoordScale;
|
||||
};
|
||||
|
||||
static void loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations);
|
||||
|
||||
AttributePointer _pointBufferAttribute;
|
||||
AttributePointer _heightfieldBufferAttribute;
|
||||
AttributePointer _voxelBufferAttribute;
|
||||
|
@ -85,14 +71,6 @@ 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.
|
||||
|
@ -392,8 +370,8 @@ public:
|
|||
|
||||
virtual void init(Spanner* spanner);
|
||||
virtual void simulate(float deltaTime);
|
||||
virtual bool findRayIntersection(RayIntersectionInfo& intersection,
|
||||
const glm::vec3& clipMinimum, float clipSize) const;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -273,13 +273,12 @@ static TextRenderer* textRenderer(TextRendererType type) {
|
|||
return displayNameRenderer;
|
||||
}
|
||||
|
||||
void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||
void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool postLighting) {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
if (glm::distance(Application::getInstance()->getAvatar()->getPosition(),
|
||||
_position) < 10.0f) {
|
||||
if (postLighting && glm::distance(Application::getInstance()->getAvatar()->getPosition(), _position) < 10.0f) {
|
||||
// render pointing lasers
|
||||
glm::vec3 laserColor = glm::vec3(1.0f, 0.0f, 1.0f);
|
||||
float laserLength = 50.0f;
|
||||
|
@ -351,17 +350,28 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
|||
? 1.0f
|
||||
: GLOW_FROM_AVERAGE_LOUDNESS;
|
||||
|
||||
|
||||
// local lights directions and colors
|
||||
const QVector<Model::LocalLight>& localLights = Application::getInstance()->getAvatarManager().getLocalLights();
|
||||
_skeletonModel.setLocalLights(localLights);
|
||||
getHead()->getFaceModel().setLocalLights(localLights);
|
||||
|
||||
// render body
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
||||
renderBody(renderMode, glowLevel);
|
||||
renderBody(renderMode, postLighting, glowLevel);
|
||||
}
|
||||
if (renderMode != SHADOW_RENDER_MODE) {
|
||||
|
||||
if (!postLighting && renderMode != SHADOW_RENDER_MODE) {
|
||||
// add local lights
|
||||
const float BASE_LIGHT_DISTANCE = 2.0f;
|
||||
const float LIGHT_EXPONENT = 1.0f;
|
||||
const float LIGHT_CUTOFF = glm::radians(80.0f);
|
||||
float distance = BASE_LIGHT_DISTANCE * _scale;
|
||||
glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f);
|
||||
glm::quat orientation = getOrientation();
|
||||
foreach (const AvatarManager::LocalLight& light, Application::getInstance()->getAvatarManager().getLocalLights()) {
|
||||
glm::vec3 direction = orientation * light.direction;
|
||||
Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position - direction * distance,
|
||||
distance * 2.0f, glm::vec3(), light.color, light.color, 1.0f, 0.5f, 0.0f, direction,
|
||||
LIGHT_EXPONENT, LIGHT_CUTOFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (postLighting) {
|
||||
bool renderSkeleton = Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes);
|
||||
bool renderHead = Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionShapes);
|
||||
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
||||
|
@ -397,7 +407,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
|||
// quick check before falling into the code below:
|
||||
// (a 10 degree breadth of an almost 2 meter avatar kicks in at about 12m)
|
||||
const float MIN_VOICE_SPHERE_DISTANCE = 12.0f;
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::BlueSpeechSphere)
|
||||
if (postLighting && Menu::getInstance()->isOptionChecked(MenuOption::BlueSpeechSphere)
|
||||
&& distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) {
|
||||
|
||||
// render voice intensity sphere for avatars that are farther away
|
||||
|
@ -425,7 +435,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
|||
|
||||
const float DISPLAYNAME_DISTANCE = 20.0f;
|
||||
setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE);
|
||||
if (renderMode != NORMAL_RENDER_MODE || (isMyAvatar() &&
|
||||
if (!postLighting || renderMode != NORMAL_RENDER_MODE || (isMyAvatar() &&
|
||||
Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) {
|
||||
return;
|
||||
}
|
||||
|
@ -489,34 +499,40 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
|||
return glm::angleAxis(angle * proportion, axis);
|
||||
}
|
||||
|
||||
void Avatar::renderBody(RenderMode renderMode, float glowLevel) {
|
||||
void Avatar::renderBody(RenderMode renderMode, bool postLighting, float glowLevel) {
|
||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
||||
{
|
||||
Glower glower(glowLevel);
|
||||
|
||||
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
if ((_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) &&
|
||||
(postLighting || renderMode == SHADOW_RENDER_MODE)) {
|
||||
// render the billboard until both models are loaded
|
||||
renderBillboard();
|
||||
return;
|
||||
}
|
||||
|
||||
_skeletonModel.render(1.0f, modelRenderMode, Menu::getInstance()->isOptionChecked(MenuOption::AvatarsReceiveShadows));
|
||||
renderAttachments(renderMode);
|
||||
getHand()->render(false, modelRenderMode);
|
||||
if (postLighting) {
|
||||
getHand()->render(false, modelRenderMode);
|
||||
} else {
|
||||
_skeletonModel.render(1.0f, modelRenderMode);
|
||||
renderAttachments(renderMode);
|
||||
}
|
||||
}
|
||||
getHead()->render(1.0f, modelRenderMode);
|
||||
if (!postLighting) {
|
||||
getHead()->render(1.0f, modelRenderMode);
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||
// Render Hair
|
||||
glPushMatrix();
|
||||
glm::vec3 headPosition = getHead()->getPosition();
|
||||
glTranslatef(headPosition.x, headPosition.y, headPosition.z);
|
||||
const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame();
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
_hair.render();
|
||||
glPopMatrix();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||
// Render Hair
|
||||
glPushMatrix();
|
||||
glm::vec3 headPosition = getHead()->getPosition();
|
||||
glTranslatef(headPosition.x, headPosition.y, headPosition.z);
|
||||
const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame();
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
_hair.render();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,9 +563,8 @@ void Avatar::simulateAttachments(float deltaTime) {
|
|||
void Avatar::renderAttachments(RenderMode renderMode) {
|
||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
||||
bool receiveShadows = Menu::getInstance()->isOptionChecked(MenuOption::AvatarsReceiveShadows);
|
||||
foreach (Model* model, _attachmentModels) {
|
||||
model->render(1.0f, modelRenderMode, receiveShadows);
|
||||
model->render(1.0f, modelRenderMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,8 @@ public:
|
|||
|
||||
enum RenderMode { NORMAL_RENDER_MODE, SHADOW_RENDER_MODE, MIRROR_RENDER_MODE };
|
||||
|
||||
virtual void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE);
|
||||
virtual void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE,
|
||||
bool postLighting = false);
|
||||
|
||||
//setters
|
||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
||||
|
@ -227,7 +228,7 @@ protected:
|
|||
glm::vec3 getDisplayNamePosition();
|
||||
|
||||
void renderDisplayName();
|
||||
virtual void renderBody(RenderMode renderMode, float glowLevel = 0.0f);
|
||||
virtual void renderBody(RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const;
|
||||
|
||||
void simulateAttachments(float deltaTime);
|
||||
|
|
|
@ -11,9 +11,12 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <QScriptEngine>
|
||||
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#include <PerfStat.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
@ -26,6 +29,23 @@
|
|||
// We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key.
|
||||
const QUuid MY_AVATAR_KEY; // NULL key
|
||||
|
||||
static QScriptValue localLightToScriptValue(QScriptEngine* engine, const AvatarManager::LocalLight& light) {
|
||||
QScriptValue object = engine->newObject();
|
||||
object.setProperty("direction", vec3toScriptValue(engine, light.direction));
|
||||
object.setProperty("color", vec3toScriptValue(engine, light.color));
|
||||
return object;
|
||||
}
|
||||
|
||||
static void localLightFromScriptValue(const QScriptValue& value, AvatarManager::LocalLight& light) {
|
||||
vec3FromScriptValue(value.property("direction"), light.direction);
|
||||
vec3FromScriptValue(value.property("color"), light.color);
|
||||
}
|
||||
|
||||
void AvatarManager::registerMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterMetaType(engine, localLightToScriptValue, localLightFromScriptValue);
|
||||
qScriptRegisterSequenceMetaType<QVector<AvatarManager::LocalLight> >(engine);
|
||||
}
|
||||
|
||||
AvatarManager::AvatarManager(QObject* parent) :
|
||||
_avatarFades() {
|
||||
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||
|
@ -79,7 +99,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
simulateAvatarFades(deltaTime);
|
||||
}
|
||||
|
||||
void AvatarManager::renderAvatars(Avatar::RenderMode renderMode, bool selfAvatarOnly) {
|
||||
void AvatarManager::renderAvatars(Avatar::RenderMode renderMode, bool postLighting, bool selfAvatarOnly) {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::renderAvatars()");
|
||||
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderLookAtVectors);
|
||||
|
@ -92,13 +112,13 @@ void AvatarManager::renderAvatars(Avatar::RenderMode renderMode, bool selfAvatar
|
|||
if (!avatar->isInitialized()) {
|
||||
continue;
|
||||
}
|
||||
avatar->render(cameraPosition, renderMode);
|
||||
avatar->render(cameraPosition, renderMode, postLighting);
|
||||
avatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||
}
|
||||
renderAvatarFades(cameraPosition, renderMode);
|
||||
} else {
|
||||
// just render myAvatar
|
||||
_myAvatar->render(cameraPosition, renderMode);
|
||||
_myAvatar->render(cameraPosition, renderMode, postLighting);
|
||||
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||
}
|
||||
}
|
||||
|
@ -159,19 +179,19 @@ void AvatarManager::clearOtherAvatars() {
|
|||
_myAvatar->clearLookAtTargetAvatar();
|
||||
}
|
||||
|
||||
void AvatarManager::setLocalLights(const QVector<Model::LocalLight>& localLights) {
|
||||
void AvatarManager::setLocalLights(const QVector<AvatarManager::LocalLight>& localLights) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setLocalLights", Q_ARG(const QVector<Model::LocalLight>&, localLights));
|
||||
QMetaObject::invokeMethod(this, "setLocalLights", Q_ARG(const QVector<AvatarManager::LocalLight>&, localLights));
|
||||
return;
|
||||
}
|
||||
_localLights = localLights;
|
||||
}
|
||||
|
||||
QVector<Model::LocalLight> AvatarManager::getLocalLights() const {
|
||||
QVector<AvatarManager::LocalLight> AvatarManager::getLocalLights() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVector<Model::LocalLight> result;
|
||||
QVector<AvatarManager::LocalLight> result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarManager*>(this), "getLocalLights", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVector<Model::LocalLight>, result));
|
||||
Q_RETURN_ARG(QVector<AvatarManager::LocalLight>, result));
|
||||
return result;
|
||||
}
|
||||
return _localLights;
|
||||
|
|
|
@ -26,6 +26,10 @@ class AvatarManager : public AvatarHashMap {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/// Registers the script types associated with the avatar manager.
|
||||
static void registerMetaTypes(QScriptEngine* engine);
|
||||
|
||||
AvatarManager(QObject* parent = 0);
|
||||
|
||||
void init();
|
||||
|
@ -33,12 +37,18 @@ public:
|
|||
MyAvatar* getMyAvatar() { return _myAvatar.data(); }
|
||||
|
||||
void updateOtherAvatars(float deltaTime);
|
||||
void renderAvatars(Avatar::RenderMode renderMode, bool selfAvatarOnly = false);
|
||||
void renderAvatars(Avatar::RenderMode renderMode, bool postLighting = false, bool selfAvatarOnly = false);
|
||||
|
||||
void clearOtherAvatars();
|
||||
|
||||
Q_INVOKABLE void setLocalLights(const QVector<Model::LocalLight>& localLights);
|
||||
Q_INVOKABLE QVector<Model::LocalLight> getLocalLights() const;
|
||||
class LocalLight {
|
||||
public:
|
||||
glm::vec3 color;
|
||||
glm::vec3 direction;
|
||||
};
|
||||
|
||||
Q_INVOKABLE void setLocalLights(const QVector<AvatarManager::LocalLight>& localLights);
|
||||
Q_INVOKABLE QVector<AvatarManager::LocalLight> getLocalLights() const;
|
||||
|
||||
private:
|
||||
AvatarManager(const AvatarManager& other);
|
||||
|
@ -54,7 +64,10 @@ private:
|
|||
QVector<AvatarSharedPointer> _avatarFades;
|
||||
QSharedPointer<MyAvatar> _myAvatar;
|
||||
|
||||
QVector<Model::LocalLight> _localLights;
|
||||
QVector<AvatarManager::LocalLight> _localLights;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AvatarManager::LocalLight)
|
||||
Q_DECLARE_METATYPE(QVector<AvatarManager::LocalLight>)
|
||||
|
||||
#endif // hifi_AvatarManager_h
|
||||
|
|
|
@ -89,8 +89,6 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
} else {
|
||||
_longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f));
|
||||
}
|
||||
float deltaLoudness = glm::max(0.0f, _averageLoudness - _longTermAverageLoudness);
|
||||
//qDebug() << "deltaLoudness: " << deltaLoudness;
|
||||
|
||||
if (!(_isFaceshiftConnected || billboard)) {
|
||||
// Update eye saccades
|
||||
|
@ -194,12 +192,16 @@ void Head::relaxLean(float deltaTime) {
|
|||
}
|
||||
|
||||
void Head::render(float alpha, Model::RenderMode mode) {
|
||||
_faceModel.render(alpha, mode, Menu::getInstance()->isOptionChecked(MenuOption::AvatarsReceiveShadows));
|
||||
_faceModel.render(alpha, mode);
|
||||
if (_renderLookatVectors && mode != Model::SHADOW_RENDER_MODE) {
|
||||
renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition);
|
||||
Application::getInstance()->getDeferredLightingEffect()->addPostLightingRenderable(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Head::renderPostLighting() {
|
||||
renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition);
|
||||
}
|
||||
|
||||
void Head::setScale (float scale) {
|
||||
if (_scale == scale) {
|
||||
return;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "FaceModel.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "world.h"
|
||||
#include "renderer/DeferredLightingEffect.h"
|
||||
|
||||
enum eyeContactTargets {
|
||||
LEFT_EYE,
|
||||
|
@ -35,7 +36,7 @@ const float EYE_EAR_GAP = 0.08f;
|
|||
class Avatar;
|
||||
class ProgramObject;
|
||||
|
||||
class Head : public HeadData {
|
||||
class Head : public HeadData, public PostLightingRenderable {
|
||||
public:
|
||||
Head(Avatar* owningAvatar);
|
||||
|
||||
|
@ -43,6 +44,7 @@ public:
|
|||
void reset();
|
||||
void simulate(float deltaTime, bool isMine, bool billboard = false);
|
||||
void render(float alpha, Model::RenderMode mode);
|
||||
virtual void renderPostLighting();
|
||||
void setScale(float scale);
|
||||
void setPosition(glm::vec3 position) { _position = position; }
|
||||
void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
|
||||
|
|
|
@ -411,16 +411,16 @@ void MyAvatar::renderDebugBodyPoints() {
|
|||
}
|
||||
|
||||
// virtual
|
||||
void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||
void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool postLighting) {
|
||||
// don't render if we've been asked to disable local rendering
|
||||
if (!_shouldRender) {
|
||||
return; // exit early
|
||||
}
|
||||
|
||||
Avatar::render(cameraPosition, renderMode);
|
||||
Avatar::render(cameraPosition, renderMode, postLighting);
|
||||
|
||||
// don't display IK constraints in shadow mode
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ShowIKConstraints) && renderMode != SHADOW_RENDER_MODE) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ShowIKConstraints) && postLighting) {
|
||||
_skeletonModel.renderIKConstraints();
|
||||
}
|
||||
}
|
||||
|
@ -1096,7 +1096,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g
|
|||
Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved);
|
||||
}
|
||||
|
||||
void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
|
||||
void MyAvatar::renderBody(RenderMode renderMode, bool postLighting, float glowLevel) {
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until both models are loaded
|
||||
}
|
||||
|
@ -1104,28 +1104,34 @@ void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
|
|||
// Render the body's voxels and head
|
||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
||||
_skeletonModel.render(1.0f, modelRenderMode, Menu::getInstance()->isOptionChecked(MenuOption::AvatarsReceiveShadows));
|
||||
renderAttachments(renderMode);
|
||||
if (!postLighting) {
|
||||
_skeletonModel.render(1.0f, modelRenderMode);
|
||||
renderAttachments(renderMode);
|
||||
}
|
||||
|
||||
// Render head so long as the camera isn't inside it
|
||||
const Camera *camera = Application::getInstance()->getCamera();
|
||||
const glm::vec3 cameraPos = camera->getPosition() + (camera->getRotation() * glm::vec3(0.0f, 0.0f, 1.0f)) * camera->getDistance();
|
||||
if (shouldRenderHead(cameraPos, renderMode)) {
|
||||
getHead()->render(1.0f, modelRenderMode);
|
||||
if (!postLighting) {
|
||||
getHead()->render(1.0f, modelRenderMode);
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||
// Render Hair
|
||||
glPushMatrix();
|
||||
glm::vec3 headPosition = getHead()->getPosition();
|
||||
glTranslatef(headPosition.x, headPosition.y, headPosition.z);
|
||||
const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame();
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
_hair.render();
|
||||
glPopMatrix();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||
// Render Hair
|
||||
glPushMatrix();
|
||||
glm::vec3 headPosition = getHead()->getPosition();
|
||||
glTranslatef(headPosition.x, headPosition.y, headPosition.z);
|
||||
const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame();
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
_hair.render();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
getHand()->render(true, modelRenderMode);
|
||||
if (postLighting) {
|
||||
getHand()->render(true, modelRenderMode);
|
||||
}
|
||||
}
|
||||
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||
|
@ -1939,11 +1945,10 @@ void MyAvatar::renderAttachments(RenderMode renderMode) {
|
|||
QString headJointName = (geometry.headJointIndex == -1) ? QString() : geometry.joints.at(geometry.headJointIndex).name;
|
||||
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
|
||||
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
||||
bool receiveShadows = Menu::getInstance()->isOptionChecked(MenuOption::AvatarsReceiveShadows);
|
||||
for (int i = 0; i < _attachmentData.size(); i++) {
|
||||
const QString& jointName = _attachmentData.at(i).jointName;
|
||||
if (jointName != headJointName && jointName != "Head") {
|
||||
_attachmentModels.at(i)->render(1.0f, modelRenderMode, receiveShadows);
|
||||
_attachmentModels.at(i)->render(1.0f, modelRenderMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,8 @@ public:
|
|||
void updateFromTrackers(float deltaTime);
|
||||
void moveWithLean();
|
||||
|
||||
void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE);
|
||||
void renderBody(RenderMode renderMode, float glowLevel = 0.0f);
|
||||
void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE, bool postLighting = false);
|
||||
void renderBody(RenderMode renderMode, bool postLighting, float glowLevel = 0.0f);
|
||||
bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const;
|
||||
void renderDebugBodyPoints();
|
||||
void renderHeadMouse(int screenWidth, int screenHeight) const;
|
||||
|
|
|
@ -50,7 +50,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
|||
glm::vec3 positionToCenter = center - position;
|
||||
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
|
||||
glScalef(dimensions.x, dimensions.y, dimensions.z);
|
||||
glutSolidCube(1.0f);
|
||||
Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f);
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
} else {
|
||||
|
@ -86,6 +86,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
|||
|
||||
glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]);
|
||||
|
||||
Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
|
@ -99,6 +101,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
|||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
|
||||
Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram();
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]);
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutWireCube(size);
|
||||
Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size);
|
||||
glPopMatrix();
|
||||
}
|
||||
} else {
|
||||
|
@ -133,7 +133,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]);
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutWireCube(size);
|
||||
Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]);
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutWireCube(size);
|
||||
Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
|
|||
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
|
||||
|
||||
glScalef(dimensions.x, dimensions.y, dimensions.z);
|
||||
glutSolidSphere(0.5f, 15, 15);
|
||||
Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(0.5f, 15, 15);
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include "Application.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "ParticleTreeRenderer.h"
|
||||
|
@ -112,7 +113,7 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg
|
|||
if (wantDebugSphere) {
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutWireSphere(radius, 15, 15);
|
||||
Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(radius, 15, 15);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
@ -120,7 +121,7 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg
|
|||
} else {
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutSolidSphere(radius, 15, 15);
|
||||
Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(radius, 15, 15);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ void AmbientOcclusionEffect::init() {
|
|||
+ "shaders/ambient_occlusion.frag");
|
||||
_occlusionProgram->link();
|
||||
|
||||
// create the sample kernel: an array of spherically distributed offset vectors
|
||||
// create the sample kernel: an array of hemispherically distributed offset vectors
|
||||
const int SAMPLE_KERNEL_SIZE = 16;
|
||||
QVector3D sampleKernel[SAMPLE_KERNEL_SIZE];
|
||||
for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
|
||||
|
@ -51,7 +51,8 @@ void AmbientOcclusionEffect::init() {
|
|||
|
||||
_occlusionProgram->bind();
|
||||
_occlusionProgram->setUniformValue("depthTexture", 0);
|
||||
_occlusionProgram->setUniformValue("rotationTexture", 1);
|
||||
_occlusionProgram->setUniformValue("normalTexture", 1);
|
||||
_occlusionProgram->setUniformValue("rotationTexture", 2);
|
||||
_occlusionProgram->setUniformValueArray("sampleKernel", sampleKernel, SAMPLE_KERNEL_SIZE);
|
||||
_occlusionProgram->setUniformValue("radius", 0.1f);
|
||||
_occlusionProgram->release();
|
||||
|
@ -71,10 +72,10 @@ void AmbientOcclusionEffect::init() {
|
|||
unsigned char rotationData[ROTATION_WIDTH * ROTATION_HEIGHT * ELEMENTS_PER_PIXEL];
|
||||
unsigned char* rotation = rotationData;
|
||||
for (int i = 0; i < ROTATION_WIDTH * ROTATION_HEIGHT; i++) {
|
||||
glm::vec3 randvec = glm::sphericalRand(1.0f);
|
||||
*rotation++ = ((randvec.x + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((randvec.y + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((randvec.z + 1.0f) / 2.0f) * 255.0f;
|
||||
glm::vec3 vector = glm::sphericalRand(1.0f);
|
||||
*rotation++ = ((vector.x + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((vector.y + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((vector.z + 1.0f) / 2.0f) * 255.0f;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ROTATION_WIDTH, ROTATION_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, rotationData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
@ -101,6 +102,9 @@ void AmbientOcclusionEffect::render() {
|
|||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID());
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID());
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
|
||||
|
||||
// render with the occlusion shader to the secondary/tertiary buffer
|
||||
|
@ -137,6 +141,10 @@ void AmbientOcclusionEffect::render() {
|
|||
freeFBO->release();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// now render secondary to primary with 4x4 blur
|
||||
|
|
347
interface/src/renderer/DeferredLightingEffect.cpp
Normal file
347
interface/src/renderer/DeferredLightingEffect.cpp
Normal file
|
@ -0,0 +1,347 @@
|
|||
//
|
||||
// DeferredLightingEffect.cpp
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/11/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
|
||||
//
|
||||
|
||||
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
||||
#include "Application.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
#include "RenderUtil.h"
|
||||
|
||||
void DeferredLightingEffect::init() {
|
||||
_simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/simple.vert");
|
||||
_simpleProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/simple.frag");
|
||||
_simpleProgram.link();
|
||||
|
||||
_simpleProgram.bind();
|
||||
_glowIntensityLocation = _simpleProgram.uniformLocation("glowIntensity");
|
||||
_simpleProgram.release();
|
||||
|
||||
loadLightProgram("shaders/directional_light.frag", false, _directionalLight, _directionalLightLocations);
|
||||
loadLightProgram("shaders/directional_light_shadow_map.frag", false, _directionalLightShadowMap,
|
||||
_directionalLightShadowMapLocations);
|
||||
loadLightProgram("shaders/directional_light_cascaded_shadow_map.frag", false, _directionalLightCascadedShadowMap,
|
||||
_directionalLightCascadedShadowMapLocations);
|
||||
loadLightProgram("shaders/point_light.frag", true, _pointLight, _pointLightLocations);
|
||||
loadLightProgram("shaders/spot_light.frag", true, _spotLight, _spotLightLocations);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::bindSimpleProgram() {
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true, true);
|
||||
_simpleProgram.bind();
|
||||
_simpleProgram.setUniformValue(_glowIntensityLocation, Application::getInstance()->getGlowEffect()->getIntensity());
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::releaseSimpleProgram() {
|
||||
glEnable(GL_BLEND);
|
||||
_simpleProgram.release();
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false, false);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks) {
|
||||
bindSimpleProgram();
|
||||
glutSolidSphere(radius, slices, stacks);
|
||||
releaseSimpleProgram();
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::renderWireSphere(float radius, int slices, int stacks) {
|
||||
bindSimpleProgram();
|
||||
glutWireSphere(radius, slices, stacks);
|
||||
releaseSimpleProgram();
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::renderSolidCube(float size) {
|
||||
bindSimpleProgram();
|
||||
glutSolidCube(size);
|
||||
releaseSimpleProgram();
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::renderWireCube(float size) {
|
||||
bindSimpleProgram();
|
||||
glutWireCube(size);
|
||||
releaseSimpleProgram();
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
|
||||
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation,
|
||||
float linearAttenuation, float quadraticAttenuation) {
|
||||
addSpotLight(position, radius, ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
|
||||
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation, float linearAttenuation,
|
||||
float quadraticAttenuation, const glm::vec3& direction, float exponent, float cutoff) {
|
||||
if (exponent == 0.0f && cutoff == PI) {
|
||||
PointLight light;
|
||||
light.position = glm::vec4(position, 1.0f);
|
||||
light.radius = radius;
|
||||
light.ambient = glm::vec4(ambient, 1.0f);
|
||||
light.diffuse = glm::vec4(diffuse, 1.0f);
|
||||
light.specular = glm::vec4(specular, 1.0f);
|
||||
light.constantAttenuation = constantAttenuation;
|
||||
light.linearAttenuation = linearAttenuation;
|
||||
_pointLights.append(light);
|
||||
|
||||
} else {
|
||||
SpotLight light;
|
||||
light.position = glm::vec4(position, 1.0f);
|
||||
light.radius = radius;
|
||||
light.ambient = glm::vec4(ambient, 1.0f);
|
||||
light.diffuse = glm::vec4(diffuse, 1.0f);
|
||||
light.specular = glm::vec4(specular, 1.0f);
|
||||
light.constantAttenuation = constantAttenuation;
|
||||
light.linearAttenuation = linearAttenuation;
|
||||
light.direction = direction;
|
||||
light.exponent = exponent;
|
||||
light.cutoff = cutoff;
|
||||
_spotLights.append(light);
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::prepare() {
|
||||
// clear the normal and specular buffers
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, false);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, false, true);
|
||||
// clearing to zero alpha for specular causes problems on my Nvidia card; clear to lowest non-zero value instead
|
||||
const float MAX_SPECULAR_EXPONENT = 128.0f;
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false, false);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::render() {
|
||||
// perform deferred lighting, rendering to free fbo
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
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());
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimarySpecularTextureID());
|
||||
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID());
|
||||
|
||||
// get the viewport side (left, right, both)
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
const int VIEWPORT_X_INDEX = 0;
|
||||
const int VIEWPORT_Y_INDEX = 1;
|
||||
const int VIEWPORT_WIDTH_INDEX = 2;
|
||||
const int VIEWPORT_HEIGHT_INDEX = 3;
|
||||
float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width();
|
||||
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width();
|
||||
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)primaryFBO->height();
|
||||
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)primaryFBO->height();
|
||||
|
||||
ProgramObject* program = &_directionalLight;
|
||||
const LightLocations* locations = &_directionalLightLocations;
|
||||
bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled();
|
||||
if (shadowsEnabled) {
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
|
||||
|
||||
program = &_directionalLightShadowMap;
|
||||
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());
|
||||
|
||||
} else {
|
||||
program->bind();
|
||||
}
|
||||
|
||||
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->nearLocation, nearVal);
|
||||
float depthScale = (farVal - nearVal) / farVal;
|
||||
program->setUniformValue(locations->depthScale, depthScale);
|
||||
float nearScale = -1.0f / nearVal;
|
||||
float depthTexCoordScaleS = (right - left) * nearScale / sWidth;
|
||||
float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight;
|
||||
float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS;
|
||||
float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT;
|
||||
program->setUniformValue(locations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
|
||||
program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
|
||||
|
||||
renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight);
|
||||
|
||||
program->release();
|
||||
|
||||
if (shadowsEnabled) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
}
|
||||
|
||||
// additive blending
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
|
||||
glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f);
|
||||
glm::vec4 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f);
|
||||
glTexGenfv(GL_S, GL_OBJECT_PLANE, (const GLfloat*)&sCoefficients);
|
||||
glTexGenfv(GL_T, GL_OBJECT_PLANE, (const GLfloat*)&tCoefficients);
|
||||
|
||||
if (!_pointLights.isEmpty()) {
|
||||
_pointLight.bind();
|
||||
_pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal);
|
||||
_pointLight.setUniformValue(_pointLightLocations.depthScale, depthScale);
|
||||
_pointLight.setUniformValue(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
|
||||
_pointLight.setUniformValue(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
|
||||
|
||||
foreach (const PointLight& light, _pointLights) {
|
||||
_pointLight.setUniformValue(_pointLightLocations.radius, light.radius);
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light.constantAttenuation);
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation);
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation);
|
||||
|
||||
renderFullscreenQuad();
|
||||
}
|
||||
_pointLights.clear();
|
||||
|
||||
_pointLight.release();
|
||||
}
|
||||
|
||||
if (!_spotLights.isEmpty()) {
|
||||
_spotLight.bind();
|
||||
_spotLight.setUniformValue(_spotLightLocations.nearLocation, nearVal);
|
||||
_spotLight.setUniformValue(_spotLightLocations.depthScale, depthScale);
|
||||
_spotLight.setUniformValue(_spotLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
|
||||
_spotLight.setUniformValue(_spotLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
|
||||
|
||||
foreach (const SpotLight& light, _spotLights) {
|
||||
_spotLight.setUniformValue(_spotLightLocations.radius, light.radius);
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light.constantAttenuation);
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation);
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation);
|
||||
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, (const GLfloat*)&light.direction);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff));
|
||||
|
||||
renderFullscreenQuad();
|
||||
}
|
||||
_spotLights.clear();
|
||||
|
||||
_spotLight.release();
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
freeFBO->release();
|
||||
|
||||
// now transfer the lit region to the primary fbo
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
glColorMask(true, true, true, false);
|
||||
|
||||
primaryFBO->bind();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColorMask(true, true, true, true);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
// now render the objects we held back until after deferred lighting
|
||||
foreach (PostLightingRenderable* renderable, _postLightingRenderables) {
|
||||
renderable->renderPostLighting();
|
||||
}
|
||||
_postLightingRenderables.clear();
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::loadLightProgram(const char* name, bool limited, ProgramObject& program, LightLocations& locations) {
|
||||
program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
|
||||
(limited ? "shaders/deferred_light_limited.vert" : "shaders/deferred_light.vert"));
|
||||
program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + name);
|
||||
program.link();
|
||||
|
||||
program.bind();
|
||||
program.setUniformValue("diffuseMap", 0);
|
||||
program.setUniformValue("normalMap", 1);
|
||||
program.setUniformValue("specularMap", 2);
|
||||
program.setUniformValue("depthMap", 3);
|
||||
program.setUniformValue("shadowMap", 4);
|
||||
locations.shadowDistances = program.uniformLocation("shadowDistances");
|
||||
locations.shadowScale = program.uniformLocation("shadowScale");
|
||||
locations.nearLocation = program.uniformLocation("near");
|
||||
locations.depthScale = program.uniformLocation("depthScale");
|
||||
locations.depthTexCoordOffset = program.uniformLocation("depthTexCoordOffset");
|
||||
locations.depthTexCoordScale = program.uniformLocation("depthTexCoordScale");
|
||||
locations.radius = program.uniformLocation("radius");
|
||||
program.release();
|
||||
}
|
127
interface/src/renderer/DeferredLightingEffect.h
Normal file
127
interface/src/renderer/DeferredLightingEffect.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// DeferredLightingEffect.h
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Andrzej Kapolka on 9/11/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
|
||||
//
|
||||
|
||||
#ifndef hifi_DeferredLightingEffect_h
|
||||
#define hifi_DeferredLightingEffect_h
|
||||
|
||||
#include <QVector>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "ProgramObject.h"
|
||||
|
||||
class PostLightingRenderable;
|
||||
|
||||
/// Handles deferred lighting for the bits that require it (voxels, metavoxels...)
|
||||
class DeferredLightingEffect {
|
||||
public:
|
||||
|
||||
void init();
|
||||
|
||||
/// Returns a reference to a simple program suitable for rendering static
|
||||
/// untextured geometry (such as that generated by glutSolidSphere, etc.)
|
||||
ProgramObject& getSimpleProgram() { return _simpleProgram; }
|
||||
|
||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||
void bindSimpleProgram();
|
||||
|
||||
/// Tears down the state necessary to render static untextured geometry with the simple program.
|
||||
void releaseSimpleProgram();
|
||||
|
||||
//// Renders a solid sphere with the simple program.
|
||||
void renderSolidSphere(float radius, int slices, int stacks);
|
||||
|
||||
//// Renders a wireframe sphere with the simple program.
|
||||
void renderWireSphere(float radius, int slices, int stacks);
|
||||
|
||||
//// Renders a solid cube with the simple program.
|
||||
void renderSolidCube(float size);
|
||||
|
||||
//// Renders a wireframe cube with the simple program.
|
||||
void renderWireCube(float size);
|
||||
|
||||
/// Adds a point light to render for the current frame.
|
||||
void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
|
||||
const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f),
|
||||
float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f);
|
||||
|
||||
/// Adds a spot light to render for the current frame.
|
||||
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
|
||||
const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f),
|
||||
float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f,
|
||||
const glm::vec3& direction = glm::vec3(0.0f, 0.0f, -1.0f), float exponent = 0.0f, float cutoff = PI);
|
||||
|
||||
/// Adds an object to render after performing the deferred lighting for the current frame (e.g., a translucent object).
|
||||
void addPostLightingRenderable(PostLightingRenderable* renderable) { _postLightingRenderables.append(renderable); }
|
||||
|
||||
void prepare();
|
||||
void render();
|
||||
|
||||
private:
|
||||
|
||||
class LightLocations {
|
||||
public:
|
||||
int shadowDistances;
|
||||
int shadowScale;
|
||||
int nearLocation;
|
||||
int depthScale;
|
||||
int depthTexCoordOffset;
|
||||
int depthTexCoordScale;
|
||||
int radius;
|
||||
};
|
||||
|
||||
static void loadLightProgram(const char* name, bool limited, ProgramObject& program, LightLocations& locations);
|
||||
|
||||
ProgramObject _simpleProgram;
|
||||
int _glowIntensityLocation;
|
||||
|
||||
ProgramObject _directionalLight;
|
||||
LightLocations _directionalLightLocations;
|
||||
ProgramObject _directionalLightShadowMap;
|
||||
LightLocations _directionalLightShadowMapLocations;
|
||||
ProgramObject _directionalLightCascadedShadowMap;
|
||||
LightLocations _directionalLightCascadedShadowMapLocations;
|
||||
ProgramObject _pointLight;
|
||||
LightLocations _pointLightLocations;
|
||||
ProgramObject _spotLight;
|
||||
LightLocations _spotLightLocations;
|
||||
|
||||
class PointLight {
|
||||
public:
|
||||
glm::vec4 position;
|
||||
float radius;
|
||||
glm::vec4 ambient;
|
||||
glm::vec4 diffuse;
|
||||
glm::vec4 specular;
|
||||
float constantAttenuation;
|
||||
float linearAttenuation;
|
||||
float quadraticAttenuation;
|
||||
};
|
||||
|
||||
class SpotLight : public PointLight {
|
||||
public:
|
||||
glm::vec3 direction;
|
||||
float exponent;
|
||||
float cutoff;
|
||||
};
|
||||
|
||||
QVector<PointLight> _pointLights;
|
||||
QVector<SpotLight> _spotLights;
|
||||
QVector<PostLightingRenderable*> _postLightingRenderables;
|
||||
};
|
||||
|
||||
/// Simple interface for objects that require something to be rendered after deferred lighting.
|
||||
class PostLightingRenderable {
|
||||
public:
|
||||
virtual void renderPostLighting() = 0;
|
||||
};
|
||||
|
||||
#endif // hifi_DeferredLightingEffect_h
|
|
@ -43,6 +43,9 @@ public:
|
|||
/// Stops using the glow effect.
|
||||
void end();
|
||||
|
||||
/// Returns the current glow intensity.
|
||||
float getIntensity() const { return _intensity; }
|
||||
|
||||
/// Renders the glow effect. To be called after rendering the scene.
|
||||
/// \param toTexture whether to render to a texture, rather than to the frame buffer
|
||||
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <QMetaType>
|
||||
#include <QRunnable>
|
||||
#include <QScriptEngine>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
@ -20,7 +19,6 @@
|
|||
#include <CapsuleShape.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <PhysicsEntity.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <ShapeCollider.h>
|
||||
#include <SphereShape.h>
|
||||
|
||||
|
@ -33,23 +31,6 @@ static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();
|
|||
static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();
|
||||
static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
|
||||
|
||||
static QScriptValue localLightToScriptValue(QScriptEngine* engine, const Model::LocalLight& light) {
|
||||
QScriptValue object = engine->newObject();
|
||||
object.setProperty("direction", vec3toScriptValue(engine, light.direction));
|
||||
object.setProperty("color", vec3toScriptValue(engine, light.color));
|
||||
return object;
|
||||
}
|
||||
|
||||
static void localLightFromScriptValue(const QScriptValue& value, Model::LocalLight& light) {
|
||||
vec3FromScriptValue(value.property("direction"), light.direction);
|
||||
vec3FromScriptValue(value.property("color"), light.color);
|
||||
}
|
||||
|
||||
void Model::registerMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterMetaType(engine, localLightToScriptValue, localLightFromScriptValue);
|
||||
qScriptRegisterSequenceMetaType<QVector<Model::LocalLight> >(engine);
|
||||
}
|
||||
|
||||
Model::Model(QObject* parent) :
|
||||
QObject(parent),
|
||||
_scale(1.0f, 1.0f, 1.0f),
|
||||
|
@ -77,16 +58,7 @@ ProgramObject Model::_program;
|
|||
ProgramObject Model::_normalMapProgram;
|
||||
ProgramObject Model::_specularMapProgram;
|
||||
ProgramObject Model::_normalSpecularMapProgram;
|
||||
|
||||
ProgramObject Model::_shadowMapProgram;
|
||||
ProgramObject Model::_shadowNormalMapProgram;
|
||||
ProgramObject Model::_shadowSpecularMapProgram;
|
||||
ProgramObject Model::_shadowNormalSpecularMapProgram;
|
||||
|
||||
ProgramObject Model::_cascadedShadowMapProgram;
|
||||
ProgramObject Model::_cascadedShadowNormalMapProgram;
|
||||
ProgramObject Model::_cascadedShadowSpecularMapProgram;
|
||||
ProgramObject Model::_cascadedShadowNormalSpecularMapProgram;
|
||||
ProgramObject Model::_translucentProgram;
|
||||
|
||||
ProgramObject Model::_shadowProgram;
|
||||
|
||||
|
@ -94,16 +66,7 @@ ProgramObject Model::_skinProgram;
|
|||
ProgramObject Model::_skinNormalMapProgram;
|
||||
ProgramObject Model::_skinSpecularMapProgram;
|
||||
ProgramObject Model::_skinNormalSpecularMapProgram;
|
||||
|
||||
ProgramObject Model::_skinShadowMapProgram;
|
||||
ProgramObject Model::_skinShadowNormalMapProgram;
|
||||
ProgramObject Model::_skinShadowSpecularMapProgram;
|
||||
ProgramObject Model::_skinShadowNormalSpecularMapProgram;
|
||||
|
||||
ProgramObject Model::_skinCascadedShadowMapProgram;
|
||||
ProgramObject Model::_skinCascadedShadowNormalMapProgram;
|
||||
ProgramObject Model::_skinCascadedShadowSpecularMapProgram;
|
||||
ProgramObject Model::_skinCascadedShadowNormalSpecularMapProgram;
|
||||
ProgramObject Model::_skinTranslucentProgram;
|
||||
|
||||
ProgramObject Model::_skinShadowProgram;
|
||||
|
||||
|
@ -111,28 +74,14 @@ Model::Locations Model::_locations;
|
|||
Model::Locations Model::_normalMapLocations;
|
||||
Model::Locations Model::_specularMapLocations;
|
||||
Model::Locations Model::_normalSpecularMapLocations;
|
||||
Model::Locations Model::_shadowMapLocations;
|
||||
Model::Locations Model::_shadowNormalMapLocations;
|
||||
Model::Locations Model::_shadowSpecularMapLocations;
|
||||
Model::Locations Model::_shadowNormalSpecularMapLocations;
|
||||
Model::Locations Model::_cascadedShadowMapLocations;
|
||||
Model::Locations Model::_cascadedShadowNormalMapLocations;
|
||||
Model::Locations Model::_cascadedShadowSpecularMapLocations;
|
||||
Model::Locations Model::_cascadedShadowNormalSpecularMapLocations;
|
||||
|
||||
Model::Locations Model::_translucentLocations;
|
||||
|
||||
Model::SkinLocations Model::_skinLocations;
|
||||
Model::SkinLocations Model::_skinNormalMapLocations;
|
||||
Model::SkinLocations Model::_skinSpecularMapLocations;
|
||||
Model::SkinLocations Model::_skinNormalSpecularMapLocations;
|
||||
Model::SkinLocations Model::_skinShadowMapLocations;
|
||||
Model::SkinLocations Model::_skinShadowNormalMapLocations;
|
||||
Model::SkinLocations Model::_skinShadowSpecularMapLocations;
|
||||
Model::SkinLocations Model::_skinShadowNormalSpecularMapLocations;
|
||||
Model::SkinLocations Model::_skinCascadedShadowMapLocations;
|
||||
Model::SkinLocations Model::_skinCascadedShadowNormalMapLocations;
|
||||
Model::SkinLocations Model::_skinCascadedShadowSpecularMapLocations;
|
||||
Model::SkinLocations Model::_skinCascadedShadowNormalSpecularMapLocations;
|
||||
Model::SkinLocations Model::_skinShadowLocations;
|
||||
Model::SkinLocations Model::_skinTranslucentLocations;
|
||||
|
||||
void Model::setScale(const glm::vec3& scale) {
|
||||
setScaleInternal(scale);
|
||||
|
@ -164,23 +113,18 @@ void Model::setOffset(const glm::vec3& offset) {
|
|||
_snappedToRegistrationPoint = false;
|
||||
}
|
||||
|
||||
void Model::initProgram(ProgramObject& program, Model::Locations& locations,
|
||||
int specularTextureUnit, int shadowTextureUnit) {
|
||||
void Model::initProgram(ProgramObject& program, Model::Locations& locations, int specularTextureUnit) {
|
||||
program.bind();
|
||||
locations.tangent = program.attributeLocation("tangent");
|
||||
locations.shadowDistances = program.uniformLocation("shadowDistances");
|
||||
locations.localLightColors = program.uniformLocation("localLightColors");
|
||||
locations.localLightDirections = program.uniformLocation("localLightDirections");
|
||||
locations.alphaThreshold = program.uniformLocation("alphaThreshold");
|
||||
program.setUniformValue("diffuseMap", 0);
|
||||
program.setUniformValue("normalMap", 1);
|
||||
program.setUniformValue("specularMap", specularTextureUnit);
|
||||
program.setUniformValue("shadowMap", shadowTextureUnit);
|
||||
program.release();
|
||||
}
|
||||
|
||||
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations,
|
||||
int specularTextureUnit, int shadowTextureUnit) {
|
||||
initProgram(program, locations, specularTextureUnit, shadowTextureUnit);
|
||||
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, int specularTextureUnit) {
|
||||
initProgram(program, locations, specularTextureUnit);
|
||||
|
||||
program.bind();
|
||||
locations.clusterMatrices = program.uniformLocation("clusterMatrices");
|
||||
|
@ -253,78 +197,19 @@ void Model::init() {
|
|||
|
||||
initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations, 2);
|
||||
|
||||
|
||||
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert");
|
||||
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||
"shaders/model_shadow_map.frag");
|
||||
_shadowMapProgram.link();
|
||||
|
||||
initProgram(_shadowMapProgram, _shadowMapLocations);
|
||||
|
||||
_shadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/model_normal_map.vert");
|
||||
_shadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_shadow_normal_map.frag");
|
||||
_shadowNormalMapProgram.link();
|
||||
|
||||
initProgram(_shadowNormalMapProgram, _shadowNormalMapLocations, 1, 2);
|
||||
|
||||
_shadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
_translucentProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/model.vert");
|
||||
_shadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_shadow_specular_map.frag");
|
||||
_shadowSpecularMapProgram.link();
|
||||
|
||||
initProgram(_shadowSpecularMapProgram, _shadowSpecularMapLocations, 1, 2);
|
||||
|
||||
_shadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/model_normal_map.vert");
|
||||
_shadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_shadow_normal_specular_map.frag");
|
||||
_shadowNormalSpecularMapProgram.link();
|
||||
|
||||
initProgram(_shadowNormalSpecularMapProgram, _shadowNormalSpecularMapLocations, 2, 3);
|
||||
|
||||
|
||||
_cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
|
||||
"shaders/model.vert");
|
||||
_cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||
"shaders/model_cascaded_shadow_map.frag");
|
||||
_cascadedShadowMapProgram.link();
|
||||
|
||||
initProgram(_cascadedShadowMapProgram, _cascadedShadowMapLocations);
|
||||
|
||||
_cascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/model_normal_map.vert");
|
||||
_cascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_map.frag");
|
||||
_cascadedShadowNormalMapProgram.link();
|
||||
|
||||
initProgram(_cascadedShadowNormalMapProgram, _cascadedShadowNormalMapLocations, 1, 2);
|
||||
|
||||
_cascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/model.vert");
|
||||
_cascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_cascaded_shadow_specular_map.frag");
|
||||
_cascadedShadowSpecularMapProgram.link();
|
||||
|
||||
initProgram(_cascadedShadowSpecularMapProgram, _cascadedShadowSpecularMapLocations, 1, 2);
|
||||
|
||||
_cascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/model_normal_map.vert");
|
||||
_cascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_specular_map.frag");
|
||||
_cascadedShadowNormalSpecularMapProgram.link();
|
||||
|
||||
initProgram(_cascadedShadowNormalSpecularMapProgram, _cascadedShadowNormalSpecularMapLocations, 2, 3);
|
||||
_translucentProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_translucent.frag");
|
||||
_translucentProgram.link();
|
||||
|
||||
initProgram(_translucentProgram, _translucentLocations);
|
||||
|
||||
_shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert");
|
||||
_shadowProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_shadow.frag");
|
||||
_shadowProgram.link();
|
||||
|
||||
|
||||
_skinProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert");
|
||||
_skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag");
|
||||
_skinProgram.link();
|
||||
|
@ -355,73 +240,6 @@ void Model::init() {
|
|||
|
||||
initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations, 2);
|
||||
|
||||
|
||||
_skinShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
|
||||
"shaders/skin_model.vert");
|
||||
_skinShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||
"shaders/model_shadow_map.frag");
|
||||
_skinShadowMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinShadowMapProgram, _skinShadowMapLocations);
|
||||
|
||||
_skinShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model_normal_map.vert");
|
||||
_skinShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_shadow_normal_map.frag");
|
||||
_skinShadowNormalMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinShadowNormalMapProgram, _skinShadowNormalMapLocations, 1, 2);
|
||||
|
||||
_skinShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model.vert");
|
||||
_skinShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_shadow_specular_map.frag");
|
||||
_skinShadowSpecularMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinShadowSpecularMapProgram, _skinShadowSpecularMapLocations, 1, 2);
|
||||
|
||||
_skinShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model_normal_map.vert");
|
||||
_skinShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_shadow_normal_specular_map.frag");
|
||||
_skinShadowNormalSpecularMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinShadowNormalSpecularMapProgram, _skinShadowNormalSpecularMapLocations, 2, 3);
|
||||
|
||||
|
||||
_skinCascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
|
||||
"shaders/skin_model.vert");
|
||||
_skinCascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||
"shaders/model_cascaded_shadow_map.frag");
|
||||
_skinCascadedShadowMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinCascadedShadowMapProgram, _skinCascadedShadowMapLocations);
|
||||
|
||||
_skinCascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model_normal_map.vert");
|
||||
_skinCascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_map.frag");
|
||||
_skinCascadedShadowNormalMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinCascadedShadowNormalMapProgram, _skinCascadedShadowNormalMapLocations, 1, 2);
|
||||
|
||||
_skinCascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model.vert");
|
||||
_skinCascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_cascaded_shadow_specular_map.frag");
|
||||
_skinCascadedShadowSpecularMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinCascadedShadowSpecularMapProgram, _skinCascadedShadowSpecularMapLocations, 1, 2);
|
||||
|
||||
_skinCascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model_normal_map.vert");
|
||||
_skinCascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_specular_map.frag");
|
||||
_skinCascadedShadowNormalSpecularMapProgram.link();
|
||||
|
||||
initSkinProgram(_skinCascadedShadowNormalSpecularMapProgram, _skinCascadedShadowNormalSpecularMapLocations, 2, 3);
|
||||
|
||||
|
||||
_skinShadowProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model_shadow.vert");
|
||||
_skinShadowProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
|
@ -429,6 +247,14 @@ void Model::init() {
|
|||
_skinShadowProgram.link();
|
||||
|
||||
initSkinProgram(_skinShadowProgram, _skinShadowLocations);
|
||||
|
||||
_skinTranslucentProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/skin_model.vert");
|
||||
_skinTranslucentProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/model_translucent.frag");
|
||||
_skinTranslucentProgram.link();
|
||||
|
||||
initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,7 +384,7 @@ void Model::setJointStates(QVector<JointState> states) {
|
|||
_boundingRadius = radius;
|
||||
}
|
||||
|
||||
bool Model::render(float alpha, RenderMode mode, bool receiveShadows) {
|
||||
bool Model::render(float alpha, RenderMode mode) {
|
||||
// render the attachments
|
||||
foreach (Model* attachment, _attachments) {
|
||||
attachment->render(alpha, mode);
|
||||
|
@ -588,34 +414,42 @@ bool Model::render(float alpha, RenderMode mode, bool receiveShadows) {
|
|||
glEnable(GL_CULL_FACE);
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
} else if (mode == DEFAULT_RENDER_MODE) {
|
||||
// update the local lights
|
||||
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||
if (i < _localLights.size()) {
|
||||
_localLightDirections[i] = glm::normalize(Application::getInstance()->getUntranslatedViewMatrix() *
|
||||
glm::vec4(_rotation * _localLights.at(i).direction, 0.0f));
|
||||
} else {
|
||||
_localLightColors[i] = glm::vec4();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// render opaque meshes with alpha testing
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER, 0.5f * alpha);
|
||||
|
||||
receiveShadows &= Menu::getInstance()->getShadowsEnabled();
|
||||
renderMeshes(mode, false, receiveShadows);
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
glAlphaFunc(GL_EQUAL, 0.0f);
|
||||
}
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(
|
||||
mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE);
|
||||
|
||||
renderMeshes(mode, false);
|
||||
|
||||
// render translucent meshes afterwards
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
renderMeshes(mode, true, 0.75f);
|
||||
|
||||
renderMeshes(mode, true, receiveShadows);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(false);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
|
||||
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
renderMeshes(mode, true, 0.0f);
|
||||
}
|
||||
|
||||
glDepthMask(true);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
|
@ -1358,12 +1192,11 @@ void Model::deleteGeometry() {
|
|||
_blendedBlendshapeCoefficients.clear();
|
||||
}
|
||||
|
||||
void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows) {
|
||||
void Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold) {
|
||||
updateVisibleJointStates();
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||
|
||||
bool cascadedShadows = Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows);
|
||||
for (int i = 0; i < networkMeshes.size(); i++) {
|
||||
// exit early if the translucency doesn't match what we're drawing
|
||||
const NetworkMesh& networkMesh = networkMeshes.at(i);
|
||||
|
@ -1373,7 +1206,7 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
continue;
|
||||
}
|
||||
const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bind();
|
||||
|
||||
|
||||
int vertexCount = mesh.vertices.size();
|
||||
if (vertexCount == 0) {
|
||||
// sanity check
|
||||
|
@ -1387,48 +1220,25 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
ProgramObject* skinProgram = &_skinProgram;
|
||||
SkinLocations* skinLocations = &_skinLocations;
|
||||
GLenum specularTextureUnit = 0;
|
||||
GLenum shadowTextureUnit = 0;
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
program = &_shadowProgram;
|
||||
skinProgram = &_skinShadowProgram;
|
||||
skinLocations = &_skinShadowLocations;
|
||||
|
||||
} else if (translucent && alphaThreshold == 0.0f) {
|
||||
program = &_translucentProgram;
|
||||
locations = &_translucentLocations;
|
||||
skinProgram = &_skinTranslucentProgram;
|
||||
skinLocations = &_skinTranslucentLocations;
|
||||
|
||||
} else if (!mesh.tangents.isEmpty()) {
|
||||
if (mesh.hasSpecularTexture()) {
|
||||
if (receiveShadows) {
|
||||
if (cascadedShadows) {
|
||||
program = &_cascadedShadowNormalSpecularMapProgram;
|
||||
locations = &_cascadedShadowNormalSpecularMapLocations;
|
||||
skinProgram = &_skinCascadedShadowNormalSpecularMapProgram;
|
||||
skinLocations = &_skinCascadedShadowNormalSpecularMapLocations;
|
||||
} else {
|
||||
program = &_shadowNormalSpecularMapProgram;
|
||||
locations = &_shadowNormalSpecularMapLocations;
|
||||
skinProgram = &_skinShadowNormalSpecularMapProgram;
|
||||
skinLocations = &_skinShadowNormalSpecularMapLocations;
|
||||
}
|
||||
shadowTextureUnit = GL_TEXTURE3;
|
||||
} else {
|
||||
program = &_normalSpecularMapProgram;
|
||||
locations = &_normalSpecularMapLocations;
|
||||
skinProgram = &_skinNormalSpecularMapProgram;
|
||||
skinLocations = &_skinNormalSpecularMapLocations;
|
||||
}
|
||||
program = &_normalSpecularMapProgram;
|
||||
locations = &_normalSpecularMapLocations;
|
||||
skinProgram = &_skinNormalSpecularMapProgram;
|
||||
skinLocations = &_skinNormalSpecularMapLocations;
|
||||
specularTextureUnit = GL_TEXTURE2;
|
||||
|
||||
} else if (receiveShadows) {
|
||||
if (cascadedShadows) {
|
||||
program = &_cascadedShadowNormalMapProgram;
|
||||
locations = &_cascadedShadowNormalMapLocations;
|
||||
skinProgram = &_skinCascadedShadowNormalMapProgram;
|
||||
skinLocations = &_skinCascadedShadowNormalMapLocations;
|
||||
} else {
|
||||
program = &_shadowNormalMapProgram;
|
||||
locations = &_shadowNormalMapLocations;
|
||||
skinProgram = &_skinShadowNormalMapProgram;
|
||||
skinLocations = &_skinShadowNormalMapLocations;
|
||||
}
|
||||
shadowTextureUnit = GL_TEXTURE2;
|
||||
} else {
|
||||
program = &_normalMapProgram;
|
||||
locations = &_normalMapLocations;
|
||||
|
@ -1436,40 +1246,11 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
skinLocations = &_skinNormalMapLocations;
|
||||
}
|
||||
} else if (mesh.hasSpecularTexture()) {
|
||||
if (receiveShadows) {
|
||||
if (cascadedShadows) {
|
||||
program = &_cascadedShadowSpecularMapProgram;
|
||||
locations = &_cascadedShadowSpecularMapLocations;
|
||||
skinProgram = &_skinCascadedShadowSpecularMapProgram;
|
||||
skinLocations = &_skinCascadedShadowSpecularMapLocations;
|
||||
} else {
|
||||
program = &_shadowSpecularMapProgram;
|
||||
locations = &_shadowSpecularMapLocations;
|
||||
skinProgram = &_skinShadowSpecularMapProgram;
|
||||
skinLocations = &_skinShadowSpecularMapLocations;
|
||||
}
|
||||
shadowTextureUnit = GL_TEXTURE2;
|
||||
} else {
|
||||
program = &_specularMapProgram;
|
||||
locations = &_specularMapLocations;
|
||||
skinProgram = &_skinSpecularMapProgram;
|
||||
skinLocations = &_skinSpecularMapLocations;
|
||||
}
|
||||
specularTextureUnit = GL_TEXTURE1;
|
||||
|
||||
} else if (receiveShadows) {
|
||||
if (cascadedShadows) {
|
||||
program = &_cascadedShadowMapProgram;
|
||||
locations = &_cascadedShadowMapLocations;
|
||||
skinProgram = &_skinCascadedShadowMapProgram;
|
||||
skinLocations = &_skinCascadedShadowMapLocations;
|
||||
} else {
|
||||
program = &_shadowMapProgram;
|
||||
locations = &_shadowMapLocations;
|
||||
skinProgram = &_skinShadowMapProgram;
|
||||
skinLocations = &_skinShadowMapLocations;
|
||||
}
|
||||
shadowTextureUnit = GL_TEXTURE1;
|
||||
program = &_specularMapProgram;
|
||||
locations = &_specularMapLocations;
|
||||
skinProgram = &_skinSpecularMapProgram;
|
||||
skinLocations = &_skinSpecularMapLocations;
|
||||
specularTextureUnit = GL_TEXTURE1;
|
||||
}
|
||||
|
||||
const MeshState& state = _meshStates.at(i);
|
||||
|
@ -1497,14 +1278,9 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
||||
program->bind();
|
||||
}
|
||||
if (cascadedShadows) {
|
||||
activeProgram->setUniform(activeLocations->shadowDistances, Application::getInstance()->getShadowDistances());
|
||||
}
|
||||
if (mode != SHADOW_RENDER_MODE) {
|
||||
activeProgram->setUniformValueArray(activeLocations->localLightDirections,
|
||||
(const GLfloat*)_localLightDirections, MAX_LOCAL_LIGHTS, 4);
|
||||
}
|
||||
|
||||
|
||||
activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold);
|
||||
|
||||
if (mesh.blendshapes.isEmpty()) {
|
||||
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
|
||||
activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
|
||||
|
@ -1550,18 +1326,19 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
|
||||
} else {
|
||||
glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity);
|
||||
glm::vec4 specular = glm::vec4(part.specularColor, part.opacity);
|
||||
if (!(translucent && alphaThreshold == 0.0f)) {
|
||||
float emissive = (part.emissiveColor.r + part.emissiveColor.g + part.emissiveColor.b) / 3.0f;
|
||||
diffuse.a = qMax(Application::getInstance()->getGlowEffect()->getIntensity(), emissive);
|
||||
glAlphaFunc(GL_EQUAL, diffuse.a);
|
||||
diffuse = glm::vec4(qMax(diffuse.r, part.emissiveColor.r), qMax(diffuse.g, part.emissiveColor.g),
|
||||
qMax(diffuse.b, part.emissiveColor.b), diffuse.a);
|
||||
}
|
||||
glm::vec4 specular = glm::vec4(part.specularColor, 1.0f);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, part.shininess);
|
||||
|
||||
for (int k = 0; k < qMin(MAX_LOCAL_LIGHTS, _localLights.size()); k++) {
|
||||
_localLightColors[k] = glm::vec4(_localLights.at(k).color, 1.0f) * diffuse;
|
||||
}
|
||||
activeProgram->setUniformValueArray(activeLocations->localLightColors,
|
||||
(const GLfloat*)_localLightColors, MAX_LOCAL_LIGHTS, 4);
|
||||
|
||||
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
||||
if (mesh.isEye && diffuseMap) {
|
||||
diffuseMap = (_dilatedTextures[i][j] =
|
||||
|
@ -1570,7 +1347,6 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
glBindTexture(GL_TEXTURE_2D, !diffuseMap ?
|
||||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
|
||||
|
||||
|
||||
if (!mesh.tangents.isEmpty()) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
Texture* normalMap = networkPart.normalTexture.data();
|
||||
|
@ -1586,12 +1362,6 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
if (shadowTextureUnit) {
|
||||
glActiveTexture(shadowTextureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
|
||||
offset += part.quadIndices.size() * sizeof(int);
|
||||
|
@ -1621,12 +1391,6 @@ void Model::renderMeshes(RenderMode mode, bool translucent, bool receiveShadows)
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
if (shadowTextureUnit) {
|
||||
glActiveTexture(shadowTextureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterIndices);
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||
|
|
|
@ -34,17 +34,12 @@ class Shape;
|
|||
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
|
||||
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
||||
|
||||
const int MAX_LOCAL_LIGHTS = 2;
|
||||
|
||||
/// A generic 3D model displaying geometry loaded from a URL.
|
||||
class Model : public QObject, public PhysicsEntity {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/// Registers the script types associated with models.
|
||||
static void registerMetaTypes(QScriptEngine* engine);
|
||||
|
||||
Model(QObject* parent = NULL);
|
||||
virtual ~Model();
|
||||
|
||||
|
@ -89,7 +84,7 @@ public:
|
|||
|
||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE };
|
||||
|
||||
bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, bool receiveShadows = true);
|
||||
bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE);
|
||||
|
||||
/// Sets the URL of the model to render.
|
||||
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
||||
|
@ -171,22 +166,13 @@ public:
|
|||
void setBlendedVertices(int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
|
||||
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
|
||||
|
||||
class LocalLight {
|
||||
public:
|
||||
glm::vec3 color;
|
||||
glm::vec3 direction;
|
||||
};
|
||||
|
||||
void setLocalLights(const QVector<LocalLight>& localLights) { _localLights = localLights; }
|
||||
const QVector<LocalLight>& getLocalLights() const { return _localLights; }
|
||||
|
||||
void setShowTrueJointTransforms(bool show) { _showTrueJointTransforms = show; }
|
||||
|
||||
QVector<JointState>& getJointStates() { return _jointStates; }
|
||||
const QVector<JointState>& getJointStates() const { return _jointStates; }
|
||||
|
||||
void inverseKinematics(int jointIndex, glm::vec3 position, const glm::quat& rotation, float priority);
|
||||
|
||||
|
||||
protected:
|
||||
QSharedPointer<NetworkGeometry> _geometry;
|
||||
|
||||
|
@ -203,8 +189,6 @@ protected:
|
|||
|
||||
bool _showTrueJointTransforms;
|
||||
|
||||
QVector<LocalLight> _localLights;
|
||||
|
||||
QVector<JointState> _jointStates;
|
||||
|
||||
class MeshState {
|
||||
|
@ -258,7 +242,7 @@ private:
|
|||
|
||||
void applyNextGeometry();
|
||||
void deleteGeometry();
|
||||
void renderMeshes(RenderMode mode, bool translucent, bool receiveShadows);
|
||||
void renderMeshes(RenderMode mode, bool translucent, float alphaThreshold = 0.5f);
|
||||
QVector<JointState> createJointStates(const FBXGeometry& geometry);
|
||||
void initJointTransforms();
|
||||
|
||||
|
@ -284,9 +268,6 @@ private:
|
|||
|
||||
QList<AnimationHandlePointer> _runningAnimations;
|
||||
|
||||
glm::vec4 _localLightColors[MAX_LOCAL_LIGHTS];
|
||||
glm::vec4 _localLightDirections[MAX_LOCAL_LIGHTS];
|
||||
|
||||
QVector<float> _blendedBlendshapeCoefficients;
|
||||
int _blendNumber;
|
||||
int _appliedBlendNumber;
|
||||
|
@ -295,16 +276,7 @@ private:
|
|||
static ProgramObject _normalMapProgram;
|
||||
static ProgramObject _specularMapProgram;
|
||||
static ProgramObject _normalSpecularMapProgram;
|
||||
|
||||
static ProgramObject _shadowMapProgram;
|
||||
static ProgramObject _shadowNormalMapProgram;
|
||||
static ProgramObject _shadowSpecularMapProgram;
|
||||
static ProgramObject _shadowNormalSpecularMapProgram;
|
||||
|
||||
static ProgramObject _cascadedShadowMapProgram;
|
||||
static ProgramObject _cascadedShadowNormalMapProgram;
|
||||
static ProgramObject _cascadedShadowSpecularMapProgram;
|
||||
static ProgramObject _cascadedShadowNormalSpecularMapProgram;
|
||||
static ProgramObject _translucentProgram;
|
||||
|
||||
static ProgramObject _shadowProgram;
|
||||
|
||||
|
@ -312,54 +284,26 @@ private:
|
|||
static ProgramObject _skinNormalMapProgram;
|
||||
static ProgramObject _skinSpecularMapProgram;
|
||||
static ProgramObject _skinNormalSpecularMapProgram;
|
||||
|
||||
static ProgramObject _skinShadowMapProgram;
|
||||
static ProgramObject _skinShadowNormalMapProgram;
|
||||
static ProgramObject _skinShadowSpecularMapProgram;
|
||||
static ProgramObject _skinShadowNormalSpecularMapProgram;
|
||||
|
||||
static ProgramObject _skinCascadedShadowMapProgram;
|
||||
static ProgramObject _skinCascadedShadowNormalMapProgram;
|
||||
static ProgramObject _skinCascadedShadowSpecularMapProgram;
|
||||
static ProgramObject _skinCascadedShadowNormalSpecularMapProgram;
|
||||
static ProgramObject _skinTranslucentProgram;
|
||||
|
||||
static ProgramObject _skinShadowProgram;
|
||||
|
||||
static int _normalMapTangentLocation;
|
||||
static int _normalSpecularMapTangentLocation;
|
||||
static int _shadowNormalMapTangentLocation;
|
||||
static int _shadowNormalSpecularMapTangentLocation;
|
||||
static int _cascadedShadowNormalMapTangentLocation;
|
||||
static int _cascadedShadowNormalSpecularMapTangentLocation;
|
||||
|
||||
static int _cascadedShadowMapDistancesLocation;
|
||||
static int _cascadedShadowNormalMapDistancesLocation;
|
||||
static int _cascadedShadowSpecularMapDistancesLocation;
|
||||
static int _cascadedShadowNormalSpecularMapDistancesLocation;
|
||||
|
||||
class Locations {
|
||||
public:
|
||||
int localLightColors;
|
||||
int localLightDirections;
|
||||
int tangent;
|
||||
int shadowDistances;
|
||||
int alphaThreshold;
|
||||
};
|
||||
|
||||
static Locations _locations;
|
||||
static Locations _normalMapLocations;
|
||||
static Locations _specularMapLocations;
|
||||
static Locations _normalSpecularMapLocations;
|
||||
static Locations _shadowMapLocations;
|
||||
static Locations _shadowNormalMapLocations;
|
||||
static Locations _shadowSpecularMapLocations;
|
||||
static Locations _shadowNormalSpecularMapLocations;
|
||||
static Locations _cascadedShadowMapLocations;
|
||||
static Locations _cascadedShadowNormalMapLocations;
|
||||
static Locations _cascadedShadowSpecularMapLocations;
|
||||
static Locations _cascadedShadowNormalSpecularMapLocations;
|
||||
static Locations _translucentLocations;
|
||||
|
||||
static void initProgram(ProgramObject& program, Locations& locations,
|
||||
int specularTextureUnit = 1, int shadowTextureUnit = 1);
|
||||
static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1);
|
||||
|
||||
class SkinLocations : public Locations {
|
||||
public:
|
||||
|
@ -371,26 +315,16 @@ private:
|
|||
static SkinLocations _skinLocations;
|
||||
static SkinLocations _skinNormalMapLocations;
|
||||
static SkinLocations _skinSpecularMapLocations;
|
||||
static SkinLocations _skinNormalSpecularMapLocations;
|
||||
static SkinLocations _skinShadowMapLocations;
|
||||
static SkinLocations _skinShadowNormalMapLocations;
|
||||
static SkinLocations _skinShadowSpecularMapLocations;
|
||||
static SkinLocations _skinShadowNormalSpecularMapLocations;
|
||||
static SkinLocations _skinCascadedShadowMapLocations;
|
||||
static SkinLocations _skinCascadedShadowNormalMapLocations;
|
||||
static SkinLocations _skinCascadedShadowSpecularMapLocations;
|
||||
static SkinLocations _skinCascadedShadowNormalSpecularMapLocations;
|
||||
static SkinLocations _skinNormalSpecularMapLocations;
|
||||
static SkinLocations _skinShadowLocations;
|
||||
|
||||
static void initSkinProgram(ProgramObject& program, SkinLocations& locations,
|
||||
int specularTextureUnit = 1, int shadowTextureUnit = 1);
|
||||
static SkinLocations _skinTranslucentLocations;
|
||||
|
||||
static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QPointer<Model>)
|
||||
Q_DECLARE_METATYPE(QWeakPointer<NetworkGeometry>)
|
||||
Q_DECLARE_METATYPE(QVector<glm::vec3>)
|
||||
Q_DECLARE_METATYPE(Model::LocalLight)
|
||||
Q_DECLARE_METATYPE(QVector<Model::LocalLight>)
|
||||
|
||||
/// Represents a handle to a model animation.
|
||||
class AnimationHandle : public QObject {
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
#include "InterfaceConfig.h"
|
||||
#include "RenderUtil.h"
|
||||
|
||||
void renderFullscreenQuad(float sMin, float sMax) {
|
||||
void renderFullscreenQuad(float sMin, float sMax, float tMin, float tMax) {
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(sMin, 0.0f);
|
||||
glTexCoord2f(sMin, tMin);
|
||||
glVertex2f(-1.0f, -1.0f);
|
||||
glTexCoord2f(sMax, 0.0f);
|
||||
glTexCoord2f(sMax, tMin);
|
||||
glVertex2f(1.0f, -1.0f);
|
||||
glTexCoord2f(sMax, 1.0f);
|
||||
glTexCoord2f(sMax, tMax);
|
||||
glVertex2f(1.0f, 1.0f);
|
||||
glTexCoord2f(sMin, 1.0f);
|
||||
glTexCoord2f(sMin, tMax);
|
||||
glVertex2f(-1.0f, 1.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#ifndef hifi_RenderUtil_h
|
||||
#define hifi_RenderUtil_h
|
||||
|
||||
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, 0) to (sMax, 1).
|
||||
void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f);
|
||||
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, tMin) to (sMax, tMax).
|
||||
void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f, float tMin = 0.0f, float tMax = 1.0f);
|
||||
|
||||
#endif // hifi_RenderUtil_h
|
||||
|
|
|
@ -30,6 +30,7 @@ TextureCache::TextureCache() :
|
|||
_blueTextureID(0),
|
||||
_primaryDepthTextureID(0),
|
||||
_primaryNormalTextureID(0),
|
||||
_primarySpecularTextureID(0),
|
||||
_primaryFramebufferObject(NULL),
|
||||
_secondaryFramebufferObject(NULL),
|
||||
_tertiaryFramebufferObject(NULL),
|
||||
|
@ -48,6 +49,7 @@ TextureCache::~TextureCache() {
|
|||
if (_primaryFramebufferObject) {
|
||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
||||
glDeleteTextures(1, &_primaryNormalTextureID);
|
||||
glDeleteTextures(1, &_primarySpecularTextureID);
|
||||
}
|
||||
|
||||
if (_primaryFramebufferObject) {
|
||||
|
@ -75,6 +77,8 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
|
|||
_primaryDepthTextureID = 0;
|
||||
glDeleteTextures(1, &_primaryNormalTextureID);
|
||||
_primaryNormalTextureID = 0;
|
||||
glDeleteTextures(1, &_primarySpecularTextureID);
|
||||
_primarySpecularTextureID = 0;
|
||||
}
|
||||
|
||||
if (_secondaryFramebufferObject) {
|
||||
|
@ -222,9 +226,18 @@ QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glGenTextures(1, &_primarySpecularTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _primarySpecularTextureID);
|
||||
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);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _primarySpecularTextureID, 0);
|
||||
_primaryFramebufferObject->release();
|
||||
}
|
||||
return _primaryFramebufferObject;
|
||||
|
@ -242,6 +255,26 @@ GLuint TextureCache::getPrimaryNormalTextureID() {
|
|||
return _primaryNormalTextureID;
|
||||
}
|
||||
|
||||
GLuint TextureCache::getPrimarySpecularTextureID() {
|
||||
getPrimaryFramebufferObject();
|
||||
return _primarySpecularTextureID;
|
||||
}
|
||||
|
||||
void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) {
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
if (color) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
}
|
||||
if (normal) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
}
|
||||
if (specular) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
}
|
||||
glDrawBuffers(bufferCount, buffers);
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
|
||||
if (!_secondaryFramebufferObject) {
|
||||
_secondaryFramebufferObject = createFramebufferObject();
|
||||
|
@ -296,6 +329,7 @@ bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
|
|||
_primaryFramebufferObject = NULL;
|
||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
||||
glDeleteTextures(1, &_primaryNormalTextureID);
|
||||
glDeleteTextures(1, &_primarySpecularTextureID);
|
||||
}
|
||||
if (_secondaryFramebufferObject && _secondaryFramebufferObject->size() != size) {
|
||||
delete _secondaryFramebufferObject;
|
||||
|
|
|
@ -64,6 +64,12 @@ public:
|
|||
/// Returns the ID of the primary framebuffer object's normal texture.
|
||||
GLuint getPrimaryNormalTextureID();
|
||||
|
||||
/// Returns the ID of the primary framebuffer object's specular texture.
|
||||
GLuint getPrimarySpecularTextureID();
|
||||
|
||||
/// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound.
|
||||
void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false);
|
||||
|
||||
/// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
|
||||
/// screen effects.
|
||||
QOpenGLFramebufferObject* getSecondaryFramebufferObject();
|
||||
|
@ -99,6 +105,7 @@ private:
|
|||
|
||||
GLuint _primaryDepthTextureID;
|
||||
GLuint _primaryNormalTextureID;
|
||||
GLuint _primarySpecularTextureID;
|
||||
QOpenGLFramebufferObject* _primaryFramebufferObject;
|
||||
QOpenGLFramebufferObject* _secondaryFramebufferObject;
|
||||
QOpenGLFramebufferObject* _tertiaryFramebufferObject;
|
||||
|
|
|
@ -506,29 +506,13 @@ void VoxelSystem::initVoxelMemory() {
|
|||
_memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);
|
||||
|
||||
// create our simple fragment shader if we're the first system to init
|
||||
if (!_shadowMapProgram.isLinked()) {
|
||||
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/shadow_map.vert");
|
||||
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/shadow_map.frag");
|
||||
_shadowMapProgram.link();
|
||||
|
||||
_shadowMapProgram.bind();
|
||||
_shadowMapProgram.setUniformValue("shadowMap", 0);
|
||||
_shadowMapProgram.release();
|
||||
|
||||
_cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/cascaded_shadow_map.vert");
|
||||
_cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/cascaded_shadow_map.frag");
|
||||
_cascadedShadowMapProgram.link();
|
||||
|
||||
_cascadedShadowMapProgram.bind();
|
||||
_cascadedShadowMapProgram.setUniformValue("shadowMap", 0);
|
||||
_shadowDistancesLocation = _cascadedShadowMapProgram.uniformLocation("shadowDistances");
|
||||
_cascadedShadowMapProgram.release();
|
||||
if (!_program.isLinked()) {
|
||||
_program.addShaderFromSourceFile(QGLShader::Vertex,
|
||||
Application::resourcesPath() + "shaders/voxel.vert");
|
||||
_program.addShaderFromSourceFile(QGLShader::Fragment,
|
||||
Application::resourcesPath() + "shaders/voxel.frag");
|
||||
_program.link();
|
||||
}
|
||||
|
||||
}
|
||||
_renderer = new PrimitiveRenderer(_maxVoxels);
|
||||
|
||||
|
@ -1150,10 +1134,8 @@ glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float vo
|
|||
return startVertex + glm::vec3(identityVertex[0], identityVertex[1], identityVertex[2]) * voxelScale;
|
||||
}
|
||||
|
||||
ProgramObject VoxelSystem::_program;
|
||||
ProgramObject VoxelSystem::_perlinModulateProgram;
|
||||
ProgramObject VoxelSystem::_shadowMapProgram;
|
||||
ProgramObject VoxelSystem::_cascadedShadowMapProgram;
|
||||
int VoxelSystem::_shadowDistancesLocation;
|
||||
|
||||
void VoxelSystem::init() {
|
||||
if (_initialized) {
|
||||
|
@ -1410,8 +1392,11 @@ void VoxelSystem::render() {
|
|||
|
||||
applyScaleAndBindProgram(texture);
|
||||
|
||||
// for performance, enable backface culling
|
||||
// for performance, enable backface culling and disable blending
|
||||
glEnable(GL_CULL_FACE);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// draw voxels in 6 passes
|
||||
|
@ -1453,6 +1438,7 @@ void VoxelSystem::render() {
|
|||
PerformanceWarning warn(showWarnings, "render().. cleanup after glDrawRangeElementsEXT()...");
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
removeScaleAndReleaseProgram(texture);
|
||||
|
||||
|
@ -1478,41 +1464,31 @@ void VoxelSystem::render() {
|
|||
}
|
||||
|
||||
void VoxelSystem::applyScaleAndBindProgram(bool texture) {
|
||||
|
||||
if (Menu::getInstance()->getShadowsEnabled()) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
|
||||
_cascadedShadowMapProgram.bind();
|
||||
_cascadedShadowMapProgram.setUniform(_shadowDistancesLocation, Application::getInstance()->getShadowDistances());
|
||||
} else {
|
||||
_shadowMapProgram.bind();
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
|
||||
|
||||
} else if (texture) {
|
||||
if (texture) {
|
||||
bindPerlinModulateProgram();
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID());
|
||||
} else {
|
||||
_program.bind();
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glScalef(_treeScale, _treeScale, _treeScale);
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
}
|
||||
|
||||
void VoxelSystem::removeScaleAndReleaseProgram(bool texture) {
|
||||
// scale back down to 1 so heads aren't massive
|
||||
glPopMatrix();
|
||||
|
||||
if (Menu::getInstance()->getShadowsEnabled()) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
|
||||
_cascadedShadowMapProgram.release();
|
||||
} else {
|
||||
_shadowMapProgram.release();
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
} else if (texture) {
|
||||
if (texture) {
|
||||
_perlinModulateProgram.release();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
} else {
|
||||
_program.release();
|
||||
}
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
}
|
||||
|
||||
int VoxelSystem::_nodeCount = 0;
|
||||
|
|
|
@ -228,10 +228,8 @@ private:
|
|||
|
||||
bool _voxelsDirty;
|
||||
|
||||
static ProgramObject _program;
|
||||
static ProgramObject _perlinModulateProgram;
|
||||
static ProgramObject _shadowMapProgram;
|
||||
static ProgramObject _cascadedShadowMapProgram;
|
||||
static int _shadowDistancesLocation;
|
||||
|
||||
static void bindPerlinModulateProgram();
|
||||
|
||||
|
|
|
@ -17,193 +17,441 @@
|
|||
template< typename T >
|
||||
class AudioFrameBuffer {
|
||||
|
||||
uint16_t _channelCount;
|
||||
uint16_t _channelCountMax;
|
||||
uint16_t _frameCount;
|
||||
uint16_t _frameCountMax;
|
||||
protected:
|
||||
|
||||
uint32_t _channelCount;
|
||||
uint32_t _channelCountMax;
|
||||
uint32_t _frameCount;
|
||||
uint32_t _frameCountMax;
|
||||
|
||||
T** _frameBuffer;
|
||||
|
||||
void allocateFrames() {
|
||||
_frameBuffer = new T*[_channelCountMax];
|
||||
if (_frameBuffer) {
|
||||
for (uint16_t i = 0; i < _channelCountMax; ++i) {
|
||||
_frameBuffer[i] = new T[_frameCountMax];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deallocateFrames() {
|
||||
if (_frameBuffer) {
|
||||
for (uint16_t i = 0; i < _channelCountMax; ++i) {
|
||||
delete _frameBuffer[i];
|
||||
}
|
||||
delete _frameBuffer;
|
||||
}
|
||||
_frameBuffer = NULL;
|
||||
}
|
||||
void allocateFrames();
|
||||
void deallocateFrames();
|
||||
|
||||
public:
|
||||
|
||||
AudioFrameBuffer() :
|
||||
_channelCount(0),
|
||||
_frameCount(0),
|
||||
_frameCountMax(0),
|
||||
_frameBuffer(NULL) {
|
||||
}
|
||||
AudioFrameBuffer();
|
||||
AudioFrameBuffer(const uint32_t channelCount, const uint32_t frameCount);
|
||||
virtual ~AudioFrameBuffer();
|
||||
|
||||
AudioFrameBuffer(const uint16_t channelCount, const uint16_t frameCount) :
|
||||
_channelCount(channelCount),
|
||||
_channelCountMax(channelCount),
|
||||
_frameCount(frameCount),
|
||||
_frameCountMax(frameCount),
|
||||
_frameBuffer(NULL) {
|
||||
allocateFrames();
|
||||
void initialize(const uint32_t channelCount, const uint32_t frameCount);
|
||||
void finalize();
|
||||
|
||||
T**& getFrameData();
|
||||
uint32_t getChannelCount();
|
||||
uint32_t getFrameCount();
|
||||
|
||||
template< typename S >
|
||||
void copyFrames(uint32_t channelCount, const uint32_t frameCount, S* frames, const bool copyOut = false);
|
||||
void zeroFrames();
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
AudioFrameBuffer< T >::AudioFrameBuffer() :
|
||||
_channelCount(0),
|
||||
_frameCount(0),
|
||||
_frameCountMax(0),
|
||||
_frameBuffer(NULL) {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
AudioFrameBuffer< T >::AudioFrameBuffer(const uint32_t channelCount, const uint32_t frameCount) :
|
||||
_channelCount(channelCount),
|
||||
_channelCountMax(channelCount),
|
||||
_frameCount(frameCount),
|
||||
_frameCountMax(frameCount),
|
||||
_frameBuffer(NULL) {
|
||||
allocateFrames();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
AudioFrameBuffer< T >::~AudioFrameBuffer() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void AudioFrameBuffer< T >::allocateFrames() {
|
||||
_frameBuffer = new T*[_channelCountMax];
|
||||
if (_frameBuffer) {
|
||||
for (uint32_t i = 0; i < _channelCountMax; ++i) {
|
||||
_frameBuffer[i] = new T[_frameCountMax];
|
||||
}
|
||||
}
|
||||
|
||||
~AudioFrameBuffer() {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void AudioFrameBuffer< T >::deallocateFrames() {
|
||||
if (_frameBuffer) {
|
||||
for (uint32_t i = 0; i < _channelCountMax; ++i) {
|
||||
delete _frameBuffer[i];
|
||||
}
|
||||
delete _frameBuffer;
|
||||
}
|
||||
_frameBuffer = NULL;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void AudioFrameBuffer< T >::initialize(const uint32_t channelCount, const uint32_t frameCount) {
|
||||
if (_frameBuffer) {
|
||||
finalize();
|
||||
}
|
||||
_channelCount = channelCount;
|
||||
_channelCountMax = channelCount;
|
||||
_frameCount = frameCount;
|
||||
_frameCountMax = frameCount;
|
||||
allocateFrames();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void AudioFrameBuffer< T >::finalize() {
|
||||
deallocateFrames();
|
||||
_channelCount = 0;
|
||||
_channelCountMax = 0;
|
||||
_frameCount = 0;
|
||||
_frameCountMax = 0;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline T**& AudioFrameBuffer< T >::getFrameData() {
|
||||
return _frameBuffer;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline uint32_t AudioFrameBuffer< T >::getChannelCount() {
|
||||
return _channelCount;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline uint32_t AudioFrameBuffer< T >::getFrameCount() {
|
||||
return _frameCount;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void AudioFrameBuffer< T >::zeroFrames() {
|
||||
if (!_frameBuffer) {
|
||||
return;
|
||||
}
|
||||
for (uint32_t i = 0; i < _channelCountMax; ++i) {
|
||||
memset(_frameBuffer[i], 0, sizeof(T)*_frameCountMax);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename S >
|
||||
inline void AudioFrameBuffer< T >::copyFrames(uint32_t channelCount, const uint32_t frameCount, S* frames, const bool copyOut) {
|
||||
if ( !_frameBuffer || !frames) {
|
||||
return;
|
||||
}
|
||||
|
||||
void initialize(const uint16_t channelCount, const uint16_t frameCount) {
|
||||
if (_frameBuffer) {
|
||||
finalize();
|
||||
}
|
||||
_channelCount = channelCount;
|
||||
_channelCountMax = channelCount;
|
||||
if (channelCount <=_channelCountMax && frameCount <=_frameCountMax) {
|
||||
// We always allow copying fewer frames than we have allocated
|
||||
_frameCount = frameCount;
|
||||
_frameCountMax = frameCount;
|
||||
allocateFrames();
|
||||
_channelCount = channelCount;
|
||||
} else {
|
||||
qDebug() << "Audio framing error: _channelCount="
|
||||
<< _channelCount
|
||||
<< "channelCountMax="
|
||||
<< _channelCountMax
|
||||
<< "_frameCount="
|
||||
<< _frameCount
|
||||
<< "frameCountMax="
|
||||
<< _frameCountMax;
|
||||
|
||||
_channelCount = std::min(_channelCount,_channelCountMax);
|
||||
_frameCount = std::min(_frameCount,_frameCountMax);
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
deallocateFrames();
|
||||
_channelCount = 0;
|
||||
_channelCountMax = 0;
|
||||
_frameCount = 0;
|
||||
_frameCountMax = 0;
|
||||
}
|
||||
|
||||
T**& getFrameData() {
|
||||
return _frameBuffer;
|
||||
}
|
||||
bool frameAlignment16 = (_frameCount & 0x0F) == 0;
|
||||
|
||||
uint16_t getChannelCount() {
|
||||
return _channelCount;
|
||||
}
|
||||
|
||||
uint16_t getFrameCount() {
|
||||
return _frameCount;
|
||||
}
|
||||
|
||||
void zeroFrames() {
|
||||
if (!_frameBuffer) {
|
||||
return;
|
||||
}
|
||||
for (uint16_t i = 0; i < _channelCountMax; ++i) {
|
||||
memset(_frameBuffer[i], 0, sizeof(T)*_frameCountMax);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename S >
|
||||
void copyFrames(uint16_t channelCount, const uint16_t frameCount, S* frames, const bool copyOut = false) {
|
||||
if ( !_frameBuffer || !frames) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (channelCount <=_channelCountMax && frameCount <=_frameCountMax) {
|
||||
// We always allow copying fewer frames than we have allocated
|
||||
_frameCount = frameCount;
|
||||
_channelCount = channelCount;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// However we do not attempt to copy more frames than we've allocated ;-) This is a framing error caused by either
|
||||
// a/ the platform audio driver not correctly queuing and regularly smoothing device IO capture frames -or-
|
||||
// b/ our IO processing thread (currently running on a Qt GUI thread) has been delayed/scheduled too late.
|
||||
//
|
||||
// The fix is not to make the problem worse by allocating additional frames on this thread, rather, it is to handle
|
||||
// dynamic re-sizing off the IO processing thread. While a/ is not in our control, we will address the off thread
|
||||
// re-sizing,, as well as b/, in later releases.
|
||||
//
|
||||
// For now, we log this condition, and do our best to recover by copying as many frames as we have allocated.
|
||||
// Unfortunately, this will result (temporarily), in an audible discontinuity.
|
||||
//
|
||||
// If you repeatedly receive this error, contact craig@highfidelity.io and send me what audio device you are using,
|
||||
// what audio-stack you are using (pulse/alsa, core audio, ...), what OS, and what the reported frame/channel
|
||||
// counts are. In addition, any information about what you were doing at the time of the discontinuity, would be
|
||||
// useful (e.g., accessing any client features/menus)
|
||||
//
|
||||
qDebug() << "Audio framing error: _channelCount="
|
||||
<< _channelCount
|
||||
<< "channelCountMax="
|
||||
<< _channelCountMax
|
||||
<< "_frameCount="
|
||||
<< _frameCount
|
||||
<< "frameCountMax="
|
||||
<< _frameCountMax;
|
||||
|
||||
|
||||
_channelCount = std::min(_channelCount,_channelCountMax);
|
||||
_frameCount = std::min(_frameCount,_frameCountMax);
|
||||
}
|
||||
|
||||
if (copyOut) {
|
||||
S* dst = frames;
|
||||
if (copyOut) {
|
||||
S* dst = frames;
|
||||
|
||||
if(typeid(T) == typeid(S)) { // source and destination types are the same, just copy out
|
||||
|
||||
if(typeid(T) == typeid(S)) { // source and destination types are the same
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
if (frameAlignment16 && (_channelCount == 1 || _channelCount == 2)) {
|
||||
|
||||
if (_channelCount == 1) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
*dst++ = _frameBuffer[0][i + 0];
|
||||
*dst++ = _frameBuffer[0][i + 1];
|
||||
*dst++ = _frameBuffer[0][i + 2];
|
||||
*dst++ = _frameBuffer[0][i + 3];
|
||||
*dst++ = _frameBuffer[0][i + 4];
|
||||
*dst++ = _frameBuffer[0][i + 5];
|
||||
*dst++ = _frameBuffer[0][i + 6];
|
||||
*dst++ = _frameBuffer[0][i + 7];
|
||||
*dst++ = _frameBuffer[0][i + 8];
|
||||
*dst++ = _frameBuffer[0][i + 9];
|
||||
*dst++ = _frameBuffer[0][i + 10];
|
||||
*dst++ = _frameBuffer[0][i + 11];
|
||||
*dst++ = _frameBuffer[0][i + 12];
|
||||
*dst++ = _frameBuffer[0][i + 13];
|
||||
*dst++ = _frameBuffer[0][i + 14];
|
||||
*dst++ = _frameBuffer[0][i + 15];
|
||||
}
|
||||
} else if (_channelCount == 2) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
*dst++ = _frameBuffer[0][i + 0];
|
||||
*dst++ = _frameBuffer[1][i + 0];
|
||||
*dst++ = _frameBuffer[0][i + 1];
|
||||
*dst++ = _frameBuffer[1][i + 1];
|
||||
*dst++ = _frameBuffer[0][i + 2];
|
||||
*dst++ = _frameBuffer[1][i + 2];
|
||||
*dst++ = _frameBuffer[0][i + 3];
|
||||
*dst++ = _frameBuffer[1][i + 3];
|
||||
*dst++ = _frameBuffer[0][i + 4];
|
||||
*dst++ = _frameBuffer[1][i + 4];
|
||||
*dst++ = _frameBuffer[0][i + 5];
|
||||
*dst++ = _frameBuffer[1][i + 5];
|
||||
*dst++ = _frameBuffer[0][i + 6];
|
||||
*dst++ = _frameBuffer[1][i + 6];
|
||||
*dst++ = _frameBuffer[0][i + 7];
|
||||
*dst++ = _frameBuffer[1][i + 7];
|
||||
*dst++ = _frameBuffer[0][i + 8];
|
||||
*dst++ = _frameBuffer[1][i + 8];
|
||||
*dst++ = _frameBuffer[0][i + 9];
|
||||
*dst++ = _frameBuffer[1][i + 9];
|
||||
*dst++ = _frameBuffer[0][i + 10];
|
||||
*dst++ = _frameBuffer[1][i + 10];
|
||||
*dst++ = _frameBuffer[0][i + 11];
|
||||
*dst++ = _frameBuffer[1][i + 11];
|
||||
*dst++ = _frameBuffer[0][i + 12];
|
||||
*dst++ = _frameBuffer[1][i + 12];
|
||||
*dst++ = _frameBuffer[0][i + 13];
|
||||
*dst++ = _frameBuffer[1][i + 13];
|
||||
*dst++ = _frameBuffer[0][i + 14];
|
||||
*dst++ = _frameBuffer[1][i + 14];
|
||||
*dst++ = _frameBuffer[0][i + 15];
|
||||
*dst++ = _frameBuffer[1][i + 15];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < _frameCount; ++i) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
*dst++ = _frameBuffer[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(typeid(T) == typeid(float32_t) &&
|
||||
typeid(S) == typeid(int16_t)) {
|
||||
} else {
|
||||
if(typeid(T) == typeid(float32_t) &&
|
||||
typeid(S) == typeid(int16_t)) { // source and destination aare not the same, convert from float32_t to int16_t and copy out
|
||||
|
||||
const int scale = (2 << ((8 * sizeof(S)) - 1));
|
||||
|
||||
if (frameAlignment16 && (_channelCount == 1 || _channelCount == 2)) {
|
||||
|
||||
const int scale = (2 << ((8 * sizeof(S)) - 1));
|
||||
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
if (_channelCount == 1) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
*dst++ = (S)(_frameBuffer[0][i + 0] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 1] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 2] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 3] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 4] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 5] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 6] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 7] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 8] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 9] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 10] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 11] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 12] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 13] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 14] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 15] * scale);
|
||||
}
|
||||
} else if (_channelCount == 2) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
*dst++ = (S)(_frameBuffer[0][i + 0] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 0] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 1] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 1] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 2] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 2] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 3] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 3] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 4] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 4] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 5] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 5] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 6] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 6] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 7] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 7] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 8] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 8] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 9] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 9] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 10] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 10] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 11] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 11] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 12] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 12] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 13] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 13] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 14] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 14] * scale);
|
||||
*dst++ = (S)(_frameBuffer[0][i + 15] * scale);
|
||||
*dst++ = (S)(_frameBuffer[1][i + 15] * scale);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < _frameCount; ++i) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
*dst++ = (S)(_frameBuffer[j][i] * scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0); // currently unsupported conversion
|
||||
}
|
||||
} else {
|
||||
assert(0); // currently unsupported conversion
|
||||
}
|
||||
}
|
||||
else { // copyIn
|
||||
S* src = frames;
|
||||
} else { // copyIn
|
||||
S* src = frames;
|
||||
|
||||
if(typeid(T) == typeid(S)) { // source and destination types are the same, copy in
|
||||
|
||||
if(typeid(T) == typeid(S)) { // source and destination types are the same
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
if (frameAlignment16 && (_channelCount == 1 || _channelCount == 2)) {
|
||||
|
||||
if (_channelCount == 1) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
_frameBuffer[0][i + 0] = *src++;
|
||||
_frameBuffer[0][i + 1] = *src++;
|
||||
_frameBuffer[0][i + 2] = *src++;
|
||||
_frameBuffer[0][i + 3] = *src++;
|
||||
_frameBuffer[0][i + 4] = *src++;
|
||||
_frameBuffer[0][i + 5] = *src++;
|
||||
_frameBuffer[0][i + 6] = *src++;
|
||||
_frameBuffer[0][i + 7] = *src++;
|
||||
_frameBuffer[0][i + 8] = *src++;
|
||||
_frameBuffer[0][i + 9] = *src++;
|
||||
_frameBuffer[0][i + 10] = *src++;
|
||||
_frameBuffer[0][i + 11] = *src++;
|
||||
_frameBuffer[0][i + 12] = *src++;
|
||||
_frameBuffer[0][i + 13] = *src++;
|
||||
_frameBuffer[0][i + 14] = *src++;
|
||||
_frameBuffer[0][i + 15] = *src++;
|
||||
}
|
||||
} else if (_channelCount == 2) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
_frameBuffer[0][i + 0] = *src++;
|
||||
_frameBuffer[1][i + 0] = *src++;
|
||||
_frameBuffer[0][i + 1] = *src++;
|
||||
_frameBuffer[1][i + 1] = *src++;
|
||||
_frameBuffer[0][i + 2] = *src++;
|
||||
_frameBuffer[1][i + 2] = *src++;
|
||||
_frameBuffer[0][i + 3] = *src++;
|
||||
_frameBuffer[1][i + 3] = *src++;
|
||||
_frameBuffer[0][i + 4] = *src++;
|
||||
_frameBuffer[1][i + 4] = *src++;
|
||||
_frameBuffer[0][i + 5] = *src++;
|
||||
_frameBuffer[1][i + 5] = *src++;
|
||||
_frameBuffer[0][i + 6] = *src++;
|
||||
_frameBuffer[1][i + 6] = *src++;
|
||||
_frameBuffer[0][i + 7] = *src++;
|
||||
_frameBuffer[1][i + 7] = *src++;
|
||||
_frameBuffer[0][i + 8] = *src++;
|
||||
_frameBuffer[1][i + 8] = *src++;
|
||||
_frameBuffer[0][i + 9] = *src++;
|
||||
_frameBuffer[1][i + 9] = *src++;
|
||||
_frameBuffer[0][i + 10] = *src++;
|
||||
_frameBuffer[1][i + 10] = *src++;
|
||||
_frameBuffer[0][i + 11] = *src++;
|
||||
_frameBuffer[1][i + 11] = *src++;
|
||||
_frameBuffer[0][i + 12] = *src++;
|
||||
_frameBuffer[1][i + 12] = *src++;
|
||||
_frameBuffer[0][i + 13] = *src++;
|
||||
_frameBuffer[1][i + 13] = *src++;
|
||||
_frameBuffer[0][i + 14] = *src++;
|
||||
_frameBuffer[1][i + 14] = *src++;
|
||||
_frameBuffer[0][i + 15] = *src++;
|
||||
_frameBuffer[1][i + 15] = *src++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < _frameCount; ++i) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
_frameBuffer[j][i] = *src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(typeid(T) == typeid(float32_t) &&
|
||||
typeid(S) == typeid(int16_t)) {
|
||||
} else {
|
||||
if(typeid(T) == typeid(float32_t) &&
|
||||
typeid(S) == typeid(int16_t)) { // source and destination aare not the same, convert from int16_t to float32_t and copy in
|
||||
|
||||
const int scale = (2 << ((8 * sizeof(S)) - 1));
|
||||
|
||||
if (frameAlignment16 && (_channelCount == 1 || _channelCount == 2)) {
|
||||
|
||||
const int scale = (2 << ((8 * sizeof(S)) - 1));
|
||||
|
||||
for (int i = 0; i < _frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
if (_channelCount == 1) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
_frameBuffer[0][i + 0] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 1] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 2] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 3] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 4] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 5] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 6] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 7] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 8] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 9] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 10] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 11] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 12] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 13] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 14] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 15] = ((T)(*src++)) / scale;
|
||||
}
|
||||
} else if (_channelCount == 2) {
|
||||
for (uint32_t i = 0; i < _frameCount; i += 16) {
|
||||
_frameBuffer[0][i + 0] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 0] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 1] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 1] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 2] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 2] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 3] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 3] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 4] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 4] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 5] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 5] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 6] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 6] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 7] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 7] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 8] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 8] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 9] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 9] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 10] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 10] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 11] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 11] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 12] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 12] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 13] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 13] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 14] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 14] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[0][i + 15] = ((T)(*src++)) / scale;
|
||||
_frameBuffer[1][i + 15] = ((T)(*src++)) / scale;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < _frameCount; ++i) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
_frameBuffer[j][i] = ((T)(*src++)) / scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0); // currently unsupported conversion
|
||||
}
|
||||
} else {
|
||||
assert(0); // currently unsupported conversion
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
typedef AudioFrameBuffer< float32_t > AudioBufferFloat32;
|
||||
typedef AudioFrameBuffer< int32_t > AudioBufferSInt32;
|
||||
|
|
112
libraries/audio/src/AudioEditBuffer.h
Normal file
112
libraries/audio/src/AudioEditBuffer.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
//
|
||||
// AudioEditBuffer.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 8/29/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
|
||||
//
|
||||
|
||||
#ifndef hifi_AudioEditBuffer_h
|
||||
#define hifi_AudioEditBuffer_h
|
||||
|
||||
template< typename T >
|
||||
class AudioEditBuffer : public AudioFrameBuffer<T> {
|
||||
|
||||
public:
|
||||
|
||||
AudioEditBuffer();
|
||||
AudioEditBuffer(const uint32_t channelCount, const uint32_t frameCount);
|
||||
~AudioEditBuffer();
|
||||
|
||||
bool getZeroCrossing(uint32_t start, bool direction, float32_t epsilon, uint32_t& zero);
|
||||
|
||||
void linearFade(uint32_t start, uint32_t stop, bool slope);
|
||||
void exponentialFade(uint32_t start, uint32_t stop, bool slope);
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
AudioEditBuffer<T>::AudioEditBuffer() :
|
||||
AudioFrameBuffer<T>() {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
AudioEditBuffer<T>::AudioEditBuffer(const uint32_t channelCount, const uint32_t frameCount) :
|
||||
AudioFrameBuffer<T>(channelCount, frameCount) {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
AudioEditBuffer<T>::~AudioEditBuffer() {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline bool AudioEditBuffer<T>::getZeroCrossing(uint32_t start, bool direction, float32_t epsilon, uint32_t& zero) {
|
||||
|
||||
zero = this->_frameCount;
|
||||
|
||||
if (direction) { // scan from the left
|
||||
if (start < this->_frameCount) {
|
||||
for (uint32_t i = start; i < this->_frameCount; ++i) {
|
||||
for (uint32_t j = 0; j < this->_channelCount; ++j) {
|
||||
if (this->_frameBuffer[j][i] >= -epsilon && this->_frameBuffer[j][i] <= epsilon) {
|
||||
zero = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // scan from the right
|
||||
if (start != 0 && start < this->_frameCount) {
|
||||
for (uint32_t i = start; i != 0; --i) {
|
||||
for (uint32_t j = 0; j < this->_channelCount; ++j) {
|
||||
if (this->_frameBuffer[j][i] >= -epsilon && this->_frameBuffer[j][i] <= epsilon) {
|
||||
zero = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void AudioEditBuffer<T>::linearFade(uint32_t start, uint32_t stop, bool slope) {
|
||||
|
||||
if (start >= stop || start > this->_frameCount || stop > this->_frameCount ) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t count = stop - start;
|
||||
float32_t delta;
|
||||
float32_t gain;
|
||||
|
||||
if (slope) { // 0.0 to 1.0f in delta increments
|
||||
delta = 1.0f / (float32_t)count;
|
||||
gain = 0.0f;
|
||||
} else { // 1.0f to 0.0f in delta increments
|
||||
delta = -1.0f / (float32_t)count;
|
||||
gain = 1.0f;
|
||||
}
|
||||
|
||||
for (uint32_t i = start; i < stop; ++i) {
|
||||
for (uint32_t j = 0; j < this->_channelCount; ++j) {
|
||||
this->_frameBuffer[j][i] *= gain;
|
||||
gain += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void AudioEditBuffer<T>::exponentialFade(uint32_t start, uint32_t stop, bool slope) {
|
||||
// TBD
|
||||
}
|
||||
|
||||
typedef AudioEditBuffer< float32_t > AudioEditBufferFloat32;
|
||||
typedef AudioEditBuffer< int32_t > AudioEditBufferSInt32;
|
||||
|
||||
#endif // hifi_AudioEditBuffer_h
|
||||
|
|
@ -21,16 +21,16 @@ class AudioBiquad {
|
|||
//
|
||||
// private data
|
||||
//
|
||||
float _a0; // gain
|
||||
float _a1; // feedforward 1
|
||||
float _a2; // feedforward 2
|
||||
float _b1; // feedback 1
|
||||
float _b2; // feedback 2
|
||||
float32_t _a0; // gain
|
||||
float32_t _a1; // feedforward 1
|
||||
float32_t _a2; // feedforward 2
|
||||
float32_t _b1; // feedback 1
|
||||
float32_t _b2; // feedback 2
|
||||
|
||||
float _xm1;
|
||||
float _xm2;
|
||||
float _ym1;
|
||||
float _ym2;
|
||||
float32_t _xm1;
|
||||
float32_t _xm2;
|
||||
float32_t _ym1;
|
||||
float32_t _ym2;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -51,20 +51,20 @@ public:
|
|||
//
|
||||
// public interface
|
||||
//
|
||||
void setParameters(const float a0, const float a1, const float a2, const float b1, const float b2) {
|
||||
void setParameters(const float32_t a0, const float32_t a1, const float32_t a2, const float32_t b1, const float32_t b2) {
|
||||
_a0 = a0; _a1 = a1; _a2 = a2; _b1 = b1; _b2 = b2;
|
||||
}
|
||||
|
||||
void getParameters(float& a0, float& a1, float& a2, float& b1, float& b2) {
|
||||
void getParameters(float32_t& a0, float32_t& a1, float32_t& a2, float32_t& b1, float32_t& b2) {
|
||||
a0 = _a0; a1 = _a1; a2 = _a2; b1 = _b1; b2 = _b2;
|
||||
}
|
||||
|
||||
void render(const float* in, float* out, const int frames) {
|
||||
void render(const float32_t* in, float32_t* out, const uint32_t frames) {
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float32_t x;
|
||||
float32_t y;
|
||||
|
||||
for (int i = 0; i < frames; ++i) {
|
||||
for (uint32_t i = 0; i < frames; ++i) {
|
||||
|
||||
x = *in++;
|
||||
|
||||
|
@ -105,10 +105,10 @@ protected:
|
|||
// data
|
||||
//
|
||||
AudioBiquad _kernel;
|
||||
float _sampleRate;
|
||||
float _frequency;
|
||||
float _gain;
|
||||
float _slope;
|
||||
float32_t _sampleRate;
|
||||
float32_t _frequency;
|
||||
float32_t _gain;
|
||||
float32_t _slope;
|
||||
|
||||
//
|
||||
// helpers
|
||||
|
@ -131,7 +131,7 @@ public:
|
|||
//
|
||||
// public interface
|
||||
//
|
||||
void setParameters(const float sampleRate, const float frequency, const float gain, const float slope) {
|
||||
void setParameters(const float32_t sampleRate, const float32_t frequency, const float32_t gain, const float32_t slope) {
|
||||
|
||||
_sampleRate = std::max(sampleRate, 1.0f);
|
||||
_frequency = std::max(frequency, 2.0f);
|
||||
|
@ -141,11 +141,11 @@ public:
|
|||
updateKernel();
|
||||
}
|
||||
|
||||
void getParameters(float& sampleRate, float& frequency, float& gain, float& slope) {
|
||||
void getParameters(float32_t& sampleRate, float32_t& frequency, float32_t& gain, float32_t& slope) {
|
||||
sampleRate = _sampleRate; frequency = _frequency; gain = _gain; slope = _slope;
|
||||
}
|
||||
|
||||
void render(const float* in, float* out, const int frames) {
|
||||
void render(const float32_t* in, float32_t* out, const uint32_t frames) {
|
||||
_kernel.render(in,out,frames);
|
||||
}
|
||||
|
||||
|
@ -166,14 +166,14 @@ public:
|
|||
//
|
||||
void updateKernel() {
|
||||
|
||||
const float a = _gain;
|
||||
const float aAdd1 = a + 1.0f;
|
||||
const float aSub1 = a - 1.0f;
|
||||
const float omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float aAdd1TimesCosOmega = aAdd1 * cosf(omega);
|
||||
const float aSub1TimesCosOmega = aSub1 * cosf(omega);
|
||||
const float alpha = 0.5f * sinf(omega) / _slope;
|
||||
const float zeta = 2.0f * sqrtf(a) * alpha;
|
||||
const float32_t a = _gain;
|
||||
const float32_t aAdd1 = a + 1.0f;
|
||||
const float32_t aSub1 = a - 1.0f;
|
||||
const float32_t omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float32_t aAdd1TimesCosOmega = aAdd1 * cosf(omega);
|
||||
const float32_t aSub1TimesCosOmega = aSub1 * cosf(omega);
|
||||
const float32_t alpha = 0.5f * sinf(omega) / _slope;
|
||||
const float32_t zeta = 2.0f * sqrtf(a) * alpha;
|
||||
/*
|
||||
b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha )
|
||||
b1 = 2*A*( (A-1) - (A+1)*cos(w0) )
|
||||
|
@ -182,14 +182,14 @@ public:
|
|||
a1 = -2*( (A-1) + (A+1)*cos(w0) )
|
||||
a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha
|
||||
*/
|
||||
const float b0 = +1.0f * (aAdd1 - aSub1TimesCosOmega + zeta) * a;
|
||||
const float b1 = +2.0f * (aSub1 - aAdd1TimesCosOmega + ZERO) * a;
|
||||
const float b2 = +1.0f * (aAdd1 - aSub1TimesCosOmega - zeta) * a;
|
||||
const float a0 = +1.0f * (aAdd1 + aSub1TimesCosOmega + zeta);
|
||||
const float a1 = -2.0f * (aSub1 + aAdd1TimesCosOmega + ZERO);
|
||||
const float a2 = +1.0f * (aAdd1 + aSub1TimesCosOmega - zeta);
|
||||
const float32_t b0 = +1.0f * (aAdd1 - aSub1TimesCosOmega + zeta) * a;
|
||||
const float32_t b1 = +2.0f * (aSub1 - aAdd1TimesCosOmega + ZERO) * a;
|
||||
const float32_t b2 = +1.0f * (aAdd1 - aSub1TimesCosOmega - zeta) * a;
|
||||
const float32_t a0 = +1.0f * (aAdd1 + aSub1TimesCosOmega + zeta);
|
||||
const float32_t a1 = -2.0f * (aSub1 + aAdd1TimesCosOmega + ZERO);
|
||||
const float32_t a2 = +1.0f * (aAdd1 + aSub1TimesCosOmega - zeta);
|
||||
|
||||
const float normA0 = 1.0f / a0;
|
||||
const float32_t normA0 = 1.0f / a0;
|
||||
|
||||
_kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
|
||||
}
|
||||
|
@ -207,14 +207,14 @@ public:
|
|||
//
|
||||
void updateKernel() {
|
||||
|
||||
const float a = _gain;
|
||||
const float aAdd1 = a + 1.0f;
|
||||
const float aSub1 = a - 1.0f;
|
||||
const float omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float aAdd1TimesCosOmega = aAdd1 * cosf(omega);
|
||||
const float aSub1TimesCosOmega = aSub1 * cosf(omega);
|
||||
const float alpha = 0.5f * sinf(omega) / _slope;
|
||||
const float zeta = 2.0f * sqrtf(a) * alpha;
|
||||
const float32_t a = _gain;
|
||||
const float32_t aAdd1 = a + 1.0f;
|
||||
const float32_t aSub1 = a - 1.0f;
|
||||
const float32_t omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float32_t aAdd1TimesCosOmega = aAdd1 * cosf(omega);
|
||||
const float32_t aSub1TimesCosOmega = aSub1 * cosf(omega);
|
||||
const float32_t alpha = 0.5f * sinf(omega) / _slope;
|
||||
const float32_t zeta = 2.0f * sqrtf(a) * alpha;
|
||||
/*
|
||||
b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha )
|
||||
b1 = -2*A*( (A-1) + (A+1)*cos(w0) )
|
||||
|
@ -223,14 +223,14 @@ public:
|
|||
a1 = 2*( (A-1) - (A+1)*cos(w0) )
|
||||
a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha
|
||||
*/
|
||||
const float b0 = +1.0f * (aAdd1 + aSub1TimesCosOmega + zeta) * a;
|
||||
const float b1 = -2.0f * (aSub1 + aAdd1TimesCosOmega + ZERO) * a;
|
||||
const float b2 = +1.0f * (aAdd1 + aSub1TimesCosOmega - zeta) * a;
|
||||
const float a0 = +1.0f * (aAdd1 - aSub1TimesCosOmega + zeta);
|
||||
const float a1 = +2.0f * (aSub1 - aAdd1TimesCosOmega + ZERO);
|
||||
const float a2 = +1.0f * (aAdd1 - aSub1TimesCosOmega - zeta);
|
||||
const float32_t b0 = +1.0f * (aAdd1 + aSub1TimesCosOmega + zeta) * a;
|
||||
const float32_t b1 = -2.0f * (aSub1 + aAdd1TimesCosOmega + ZERO) * a;
|
||||
const float32_t b2 = +1.0f * (aAdd1 + aSub1TimesCosOmega - zeta) * a;
|
||||
const float32_t a0 = +1.0f * (aAdd1 - aSub1TimesCosOmega + zeta);
|
||||
const float32_t a1 = +2.0f * (aSub1 - aAdd1TimesCosOmega + ZERO);
|
||||
const float32_t a2 = +1.0f * (aAdd1 - aSub1TimesCosOmega - zeta);
|
||||
|
||||
const float normA0 = 1.0f / a0;
|
||||
const float32_t normA0 = 1.0f / a0;
|
||||
|
||||
_kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
|
||||
}
|
||||
|
@ -248,9 +248,9 @@ public:
|
|||
//
|
||||
void updateKernel() {
|
||||
|
||||
const float omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float cosOmega = cosf(omega);
|
||||
const float alpha = 0.5f * sinf(omega) / _slope;
|
||||
const float32_t omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float32_t cosOmega = cosf(omega);
|
||||
const float32_t alpha = 0.5f * sinf(omega) / _slope;
|
||||
/*
|
||||
b0 = 1 - alpha
|
||||
b1 = -2*cos(w0)
|
||||
|
@ -259,14 +259,14 @@ public:
|
|||
a1 = -2*cos(w0)
|
||||
a2 = 1 - alpha
|
||||
*/
|
||||
const float b0 = +1.0f - alpha;
|
||||
const float b1 = -2.0f * cosOmega;
|
||||
const float b2 = +1.0f + alpha;
|
||||
const float a0 = +1.0f + alpha;
|
||||
const float a1 = -2.0f * cosOmega;
|
||||
const float a2 = +1.0f - alpha;
|
||||
const float32_t b0 = +1.0f - alpha;
|
||||
const float32_t b1 = -2.0f * cosOmega;
|
||||
const float32_t b2 = +1.0f + alpha;
|
||||
const float32_t a0 = +1.0f + alpha;
|
||||
const float32_t a1 = -2.0f * cosOmega;
|
||||
const float32_t a2 = +1.0f - alpha;
|
||||
|
||||
const float normA0 = 1.0f / a0;
|
||||
const float32_t normA0 = 1.0f / a0;
|
||||
|
||||
_kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
|
||||
}
|
||||
|
@ -284,12 +284,12 @@ public:
|
|||
//
|
||||
void updateKernel() {
|
||||
|
||||
const float a = _gain;
|
||||
const float omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float cosOmega = cosf(omega);
|
||||
const float alpha = 0.5f * sinf(omega) / _slope;
|
||||
const float alphaMulA = alpha * a;
|
||||
const float alphaDivA = alpha / a;
|
||||
const float32_t a = _gain;
|
||||
const float32_t omega = TWO_PI * _frequency / _sampleRate;
|
||||
const float32_t cosOmega = cosf(omega);
|
||||
const float32_t alpha = 0.5f * sinf(omega) / _slope;
|
||||
const float32_t alphaMulA = alpha * a;
|
||||
const float32_t alphaDivA = alpha / a;
|
||||
/*
|
||||
b0 = 1 + alpha*A
|
||||
b1 = -2*cos(w0)
|
||||
|
@ -298,14 +298,14 @@ public:
|
|||
a1 = -2*cos(w0)
|
||||
a2 = 1 - alpha/A
|
||||
*/
|
||||
const float b0 = +1.0f + alphaMulA;
|
||||
const float b1 = -2.0f * cosOmega;
|
||||
const float b2 = +1.0f - alphaMulA;
|
||||
const float a0 = +1.0f + alphaDivA;
|
||||
const float a1 = -2.0f * cosOmega;
|
||||
const float a2 = +1.0f - alphaDivA;
|
||||
const float32_t b0 = +1.0f + alphaMulA;
|
||||
const float32_t b1 = -2.0f * cosOmega;
|
||||
const float32_t b2 = +1.0f - alphaMulA;
|
||||
const float32_t a0 = +1.0f + alphaDivA;
|
||||
const float32_t a1 = -2.0f * cosOmega;
|
||||
const float32_t a2 = +1.0f - alphaDivA;
|
||||
|
||||
const float normA0 = 1.0f / a0;
|
||||
const float32_t normA0 = 1.0f / a0;
|
||||
|
||||
_kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
|
||||
}
|
||||
|
|
|
@ -15,24 +15,24 @@
|
|||
//
|
||||
// Helper/convenience class that implements a bank of Filter objects
|
||||
//
|
||||
template< typename T, const int N, const int C >
|
||||
template< typename T, const uint32_t N, const uint32_t C >
|
||||
class AudioFilterBank {
|
||||
|
||||
//
|
||||
// types
|
||||
//
|
||||
struct FilterParameter {
|
||||
float _p1;
|
||||
float _p2;
|
||||
float _p3;
|
||||
float32_t _p1;
|
||||
float32_t _p2;
|
||||
float32_t _p3;
|
||||
};
|
||||
|
||||
//
|
||||
// private static data
|
||||
//
|
||||
static const int _filterCount = N;
|
||||
static const int _channelCount = C;
|
||||
static const int _profileCount = 4;
|
||||
static const uint32_t _filterCount = N;
|
||||
static const uint32_t _channelCount = C;
|
||||
static const uint32_t _profileCount = 4;
|
||||
|
||||
static FilterParameter _profiles[ _profileCount ][ _filterCount ];
|
||||
|
||||
|
@ -40,9 +40,9 @@ class AudioFilterBank {
|
|||
// private data
|
||||
//
|
||||
T _filters[ _filterCount ][ _channelCount ];
|
||||
float* _buffer[ _channelCount ];
|
||||
float _sampleRate;
|
||||
uint16_t _frameCount;
|
||||
float32_t* _buffer[ _channelCount ];
|
||||
float32_t _sampleRate;
|
||||
uint32_t _frameCount;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -64,11 +64,11 @@ public:
|
|||
//
|
||||
// public interface
|
||||
//
|
||||
void initialize(const float sampleRate, const int frameCount = 0) {
|
||||
void initialize(const float32_t sampleRate, const uint32_t frameCount = 0) {
|
||||
finalize();
|
||||
|
||||
for (int i = 0; i < _channelCount; ++i) {
|
||||
_buffer[i] = (float*)malloc(frameCount * sizeof(float));
|
||||
for (uint32_t i = 0; i < _channelCount; ++i) {
|
||||
_buffer[i] = (float32_t*)malloc(frameCount * sizeof(float32_t));
|
||||
}
|
||||
|
||||
_sampleRate = sampleRate;
|
||||
|
@ -79,7 +79,7 @@ public:
|
|||
}
|
||||
|
||||
void finalize() {
|
||||
for (int i = 0; i < _channelCount; ++i) {
|
||||
for (uint32_t i = 0; i < _channelCount; ++i) {
|
||||
if (_buffer[i]) {
|
||||
free (_buffer[i]);
|
||||
_buffer[i] = NULL;
|
||||
|
@ -90,52 +90,53 @@ public:
|
|||
void loadProfile(int profileIndex) {
|
||||
if (profileIndex >= 0 && profileIndex < _profileCount) {
|
||||
|
||||
for (int i = 0; i < _filterCount; ++i) {
|
||||
for (uint32_t i = 0; i < _filterCount; ++i) {
|
||||
FilterParameter p = _profiles[profileIndex][i];
|
||||
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
_filters[i][j].setParameters(_sampleRate,p._p1,p._p2,p._p3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setParameters(int filterStage, int filterChannel, const float sampleRate, const float frequency, const float gain,
|
||||
const float slope) {
|
||||
void setParameters(uint32_t filterStage, uint32_t filterChannel, const float32_t sampleRate, const float32_t frequency,
|
||||
const float32_t gain, const float32_t slope) {
|
||||
if (filterStage >= 0 && filterStage < _filterCount && filterChannel >= 0 && filterChannel < _channelCount) {
|
||||
_filters[filterStage][filterChannel].setParameters(sampleRate,frequency,gain,slope);
|
||||
}
|
||||
}
|
||||
|
||||
void getParameters(int filterStage, int filterChannel, float& sampleRate, float& frequency, float& gain, float& slope) {
|
||||
void getParameters(uint32_t filterStage, uint32_t filterChannel, float32_t& sampleRate, float32_t& frequency,
|
||||
float32_t& gain, float32_t& slope) {
|
||||
if (filterStage >= 0 && filterStage < _filterCount && filterChannel >= 0 && filterChannel < _channelCount) {
|
||||
_filters[filterStage][filterChannel].getParameters(sampleRate,frequency,gain,slope);
|
||||
}
|
||||
}
|
||||
|
||||
void render(const int16_t* in, int16_t* out, const int frameCount) {
|
||||
void render(const int16_t* in, int16_t* out, const uint32_t frameCount) {
|
||||
if (!_buffer || (frameCount > _frameCount))
|
||||
return;
|
||||
|
||||
const int scale = (2 << ((8 * sizeof(int16_t)) - 1));
|
||||
|
||||
// de-interleave and convert int16_t to float32 (normalized to -1. ... 1.)
|
||||
for (int i = 0; i < frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
for (uint32_t i = 0; i < frameCount; ++i) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
_buffer[j][i] = ((float)(*in++)) / scale;
|
||||
}
|
||||
}
|
||||
|
||||
// now step through each filter
|
||||
for (int i = 0; i < _channelCount; ++i) {
|
||||
for (int j = 0; j < _filterCount; ++j) {
|
||||
for (uint32_t i = 0; i < _channelCount; ++i) {
|
||||
for (uint32_t j = 0; j < _filterCount; ++j) {
|
||||
_filters[j][i].render( &_buffer[i][0], &_buffer[i][0], frameCount );
|
||||
}
|
||||
}
|
||||
|
||||
// convert float32 to int16_t and interleave
|
||||
for (int i = 0; i < frameCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
for (uint32_t i = 0; i < frameCount; ++i) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
*out++ = (int16_t)(_buffer[j][i] * scale);
|
||||
}
|
||||
}
|
||||
|
@ -144,16 +145,16 @@ public:
|
|||
void render(AudioBufferFloat32& frameBuffer) {
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (int i = 0; i < _filterCount; ++i) {
|
||||
for (uint32_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (uint32_t i = 0; i < _filterCount; ++i) {
|
||||
_filters[i][j].render( samples[j], samples[j], frameBuffer.getFrameCount() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
for (int i = 0; i < _filterCount; ++i) {
|
||||
for (int j = 0; j < _channelCount; ++j) {
|
||||
for (uint32_t i = 0; i < _filterCount; ++i) {
|
||||
for (uint32_t j = 0; j < _channelCount; ++j) {
|
||||
_filters[i][j].reset();
|
||||
}
|
||||
}
|
||||
|
|
48
libraries/audio/src/AudioGain.cpp
Normal file
48
libraries/audio/src/AudioGain.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// AudioGain.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 9/10/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
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <SharedUtil.h>
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "AudioFormat.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioGain.h"
|
||||
|
||||
AudioGain::AudioGain() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
AudioGain::~AudioGain() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
void AudioGain::initialize() {
|
||||
setParameters(1.0f,0.0f);
|
||||
}
|
||||
|
||||
void AudioGain::finalize() {
|
||||
}
|
||||
|
||||
void AudioGain::reset() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void AudioGain::setParameters(const float gain, const float mute) {
|
||||
_gain = std::min(std::max(gain, 0.0f), 1.0f);
|
||||
_mute = mute != 0.0f;
|
||||
|
||||
}
|
||||
|
||||
void AudioGain::getParameters(float& gain, float& mute) {
|
||||
gain = _gain;
|
||||
mute = _mute ? 1.0f : 0.0f;
|
||||
}
|
|
@ -18,120 +18,100 @@ class AudioGain
|
|||
bool _mute;
|
||||
|
||||
public:
|
||||
AudioGain() {
|
||||
initialize();
|
||||
}
|
||||
AudioGain();
|
||||
~AudioGain();
|
||||
|
||||
~AudioGain() {
|
||||
finalize();
|
||||
}
|
||||
void initialize();
|
||||
void finalize();
|
||||
void reset();
|
||||
|
||||
void initialize() {
|
||||
setParameters(1.0f,0.0f);
|
||||
}
|
||||
void setParameters(const float gain, const float mute);
|
||||
void getParameters(float& gain, float& mute);
|
||||
|
||||
void finalize() {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void setParameters(const float gain, const float mute) {
|
||||
_gain = std::min(std::max(gain, 0.0f), 1.0f);
|
||||
_mute = mute != 0.0f;
|
||||
|
||||
}
|
||||
|
||||
void getParameters(float& gain, float& mute) {
|
||||
gain = _gain;
|
||||
mute = _mute ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
void render(AudioBufferFloat32& frameBuffer) {
|
||||
if (_mute) {
|
||||
frameBuffer.zeroFrames();
|
||||
return;
|
||||
}
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
|
||||
bool frameAlignment16 = (frameBuffer.getFrameCount() & 0x0F) == 0;
|
||||
if (frameAlignment16) {
|
||||
|
||||
if (frameBuffer.getChannelCount() == 1) {
|
||||
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); i += 16) {
|
||||
samples[0][i + 0] *= _gain;
|
||||
samples[0][i + 1] *= _gain;
|
||||
samples[0][i + 2] *= _gain;
|
||||
samples[0][i + 3] *= _gain;
|
||||
samples[0][i + 4] *= _gain;
|
||||
samples[0][i + 5] *= _gain;
|
||||
samples[0][i + 6] *= _gain;
|
||||
samples[0][i + 7] *= _gain;
|
||||
samples[0][i + 8] *= _gain;
|
||||
samples[0][i + 9] *= _gain;
|
||||
samples[0][i + 10] *= _gain;
|
||||
samples[0][i + 11] *= _gain;
|
||||
samples[0][i + 12] *= _gain;
|
||||
samples[0][i + 13] *= _gain;
|
||||
samples[0][i + 14] *= _gain;
|
||||
samples[0][i + 15] *= _gain;
|
||||
}
|
||||
}
|
||||
else if (frameBuffer.getChannelCount() == 2) {
|
||||
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); i += 16) {
|
||||
samples[0][i + 0] *= _gain;
|
||||
samples[0][i + 1] *= _gain;
|
||||
samples[0][i + 2] *= _gain;
|
||||
samples[0][i + 3] *= _gain;
|
||||
samples[0][i + 4] *= _gain;
|
||||
samples[0][i + 5] *= _gain;
|
||||
samples[0][i + 6] *= _gain;
|
||||
samples[0][i + 7] *= _gain;
|
||||
samples[0][i + 8] *= _gain;
|
||||
samples[0][i + 9] *= _gain;
|
||||
samples[0][i + 10] *= _gain;
|
||||
samples[0][i + 11] *= _gain;
|
||||
samples[0][i + 12] *= _gain;
|
||||
samples[0][i + 13] *= _gain;
|
||||
samples[0][i + 14] *= _gain;
|
||||
samples[0][i + 15] *= _gain;
|
||||
samples[1][i + 0] *= _gain;
|
||||
samples[1][i + 1] *= _gain;
|
||||
samples[1][i + 2] *= _gain;
|
||||
samples[1][i + 3] *= _gain;
|
||||
samples[1][i + 4] *= _gain;
|
||||
samples[1][i + 5] *= _gain;
|
||||
samples[1][i + 6] *= _gain;
|
||||
samples[1][i + 7] *= _gain;
|
||||
samples[1][i + 8] *= _gain;
|
||||
samples[1][i + 9] *= _gain;
|
||||
samples[1][i + 10] *= _gain;
|
||||
samples[1][i + 11] *= _gain;
|
||||
samples[1][i + 12] *= _gain;
|
||||
samples[1][i + 13] *= _gain;
|
||||
samples[1][i + 14] *= _gain;
|
||||
samples[1][i + 15] *= _gain;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert("unsupported channel format");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); i += 1) {
|
||||
samples[j][i] *= _gain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void render(AudioBufferFloat32& frameBuffer);
|
||||
};
|
||||
|
||||
|
||||
inline void AudioGain::render(AudioBufferFloat32& frameBuffer) {
|
||||
if (_mute) {
|
||||
frameBuffer.zeroFrames();
|
||||
return;
|
||||
}
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
|
||||
bool frameAlignment16 = (frameBuffer.getFrameCount() & 0x0F) == 0;
|
||||
if (frameAlignment16) {
|
||||
|
||||
if (frameBuffer.getChannelCount() == 1) {
|
||||
|
||||
for (uint32_t i = 0; i < frameBuffer.getFrameCount(); i += 16) {
|
||||
samples[0][i + 0] *= _gain;
|
||||
samples[0][i + 1] *= _gain;
|
||||
samples[0][i + 2] *= _gain;
|
||||
samples[0][i + 3] *= _gain;
|
||||
samples[0][i + 4] *= _gain;
|
||||
samples[0][i + 5] *= _gain;
|
||||
samples[0][i + 6] *= _gain;
|
||||
samples[0][i + 7] *= _gain;
|
||||
samples[0][i + 8] *= _gain;
|
||||
samples[0][i + 9] *= _gain;
|
||||
samples[0][i + 10] *= _gain;
|
||||
samples[0][i + 11] *= _gain;
|
||||
samples[0][i + 12] *= _gain;
|
||||
samples[0][i + 13] *= _gain;
|
||||
samples[0][i + 14] *= _gain;
|
||||
samples[0][i + 15] *= _gain;
|
||||
}
|
||||
} else if (frameBuffer.getChannelCount() == 2) {
|
||||
|
||||
for (uint32_t i = 0; i < frameBuffer.getFrameCount(); i += 16) {
|
||||
samples[0][i + 0] *= _gain;
|
||||
samples[0][i + 1] *= _gain;
|
||||
samples[0][i + 2] *= _gain;
|
||||
samples[0][i + 3] *= _gain;
|
||||
samples[0][i + 4] *= _gain;
|
||||
samples[0][i + 5] *= _gain;
|
||||
samples[0][i + 6] *= _gain;
|
||||
samples[0][i + 7] *= _gain;
|
||||
samples[0][i + 8] *= _gain;
|
||||
samples[0][i + 9] *= _gain;
|
||||
samples[0][i + 10] *= _gain;
|
||||
samples[0][i + 11] *= _gain;
|
||||
samples[0][i + 12] *= _gain;
|
||||
samples[0][i + 13] *= _gain;
|
||||
samples[0][i + 14] *= _gain;
|
||||
samples[0][i + 15] *= _gain;
|
||||
samples[1][i + 0] *= _gain;
|
||||
samples[1][i + 1] *= _gain;
|
||||
samples[1][i + 2] *= _gain;
|
||||
samples[1][i + 3] *= _gain;
|
||||
samples[1][i + 4] *= _gain;
|
||||
samples[1][i + 5] *= _gain;
|
||||
samples[1][i + 6] *= _gain;
|
||||
samples[1][i + 7] *= _gain;
|
||||
samples[1][i + 8] *= _gain;
|
||||
samples[1][i + 9] *= _gain;
|
||||
samples[1][i + 10] *= _gain;
|
||||
samples[1][i + 11] *= _gain;
|
||||
samples[1][i + 12] *= _gain;
|
||||
samples[1][i + 13] *= _gain;
|
||||
samples[1][i + 14] *= _gain;
|
||||
samples[1][i + 15] *= _gain;
|
||||
}
|
||||
} else {
|
||||
assert("unsupported channel format");
|
||||
}
|
||||
} else {
|
||||
|
||||
for (uint32_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (uint32_t i = 0; i < frameBuffer.getFrameCount(); i += 1) {
|
||||
samples[j][i] *= _gain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AudioGain_h
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
//
|
||||
// AudioSourceTone.cpp
|
||||
// AudioPan.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Craig Hansen-Sturm on 8/10/14.
|
||||
// Created by Craig Hansen-Sturm on 9/10/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
@ -21,3 +21,32 @@ float32_t AudioPan::ONE_MINUS_EPSILON = 1.0f - EPSILON;
|
|||
float32_t AudioPan::ZERO_PLUS_EPSILON = 0.0f + EPSILON;
|
||||
float32_t AudioPan::ONE_HALF_MINUS_EPSILON = 0.5f - EPSILON;
|
||||
float32_t AudioPan::ONE_HALF_PLUS_EPSILON = 0.5f + EPSILON;
|
||||
|
||||
AudioPan::AudioPan() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
AudioPan::~AudioPan() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
void AudioPan::initialize() {
|
||||
setParameters(0.5f);
|
||||
}
|
||||
|
||||
void AudioPan::finalize() {
|
||||
}
|
||||
|
||||
void AudioPan::reset() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void AudioPan::setParameters(const float32_t pan) {
|
||||
// pan ranges between 0.0 and 1.0f inclusive. 0.5f is midpoint between full left and full right
|
||||
_pan = std::min(std::max(pan, 0.0f), 1.0f);
|
||||
updateCoefficients();
|
||||
}
|
||||
|
||||
void AudioPan::getParameters(float32_t& pan) {
|
||||
pan = _pan;
|
||||
}
|
||||
|
|
|
@ -23,119 +23,100 @@ class AudioPan
|
|||
static float32_t ONE_HALF_MINUS_EPSILON;
|
||||
static float32_t ONE_HALF_PLUS_EPSILON;
|
||||
|
||||
void updateCoefficients() {
|
||||
|
||||
// implement constant power sin^2 + cos^2 = 1 panning law
|
||||
|
||||
if (_pan >= ONE_MINUS_EPSILON) { // full right
|
||||
_gainLeft = 0.0f;
|
||||
_gainRight = 1.0f;
|
||||
}
|
||||
else if (_pan <= ZERO_PLUS_EPSILON) { // full left
|
||||
_gainLeft = 1.0f;
|
||||
_gainRight = 0.0f;
|
||||
}
|
||||
else if ((_pan >= ONE_HALF_MINUS_EPSILON) && (_pan <= ONE_HALF_PLUS_EPSILON)) { // center
|
||||
_gainLeft = 1.0f / SQUARE_ROOT_OF_2;
|
||||
_gainRight = 1.0f / SQUARE_ROOT_OF_2;
|
||||
}
|
||||
else { // intermediate cases
|
||||
_gainLeft = cosf( TWO_PI * _pan );
|
||||
_gainRight = sinf( TWO_PI * _pan );
|
||||
}
|
||||
}
|
||||
void updateCoefficients();
|
||||
|
||||
public:
|
||||
AudioPan() {
|
||||
initialize();
|
||||
}
|
||||
AudioPan();
|
||||
~AudioPan();
|
||||
|
||||
~AudioPan() {
|
||||
finalize();
|
||||
}
|
||||
void initialize();
|
||||
void finalize();
|
||||
void reset();
|
||||
|
||||
void initialize() {
|
||||
setParameters(0.5f);
|
||||
}
|
||||
void setParameters(const float32_t pan);
|
||||
void getParameters(float32_t& pan);
|
||||
|
||||
void finalize() {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void setParameters(const float32_t pan) {
|
||||
// pan ranges between 0.0 and 1.0f inclusive. 0.5f is midpoint between full left and full right
|
||||
_pan = std::min(std::max(pan, 0.0f), 1.0f);
|
||||
updateCoefficients();
|
||||
}
|
||||
|
||||
void getParameters(float32_t& pan) {
|
||||
pan = _pan;
|
||||
}
|
||||
|
||||
void render(AudioBufferFloat32& frameBuffer) {
|
||||
|
||||
if (frameBuffer.getChannelCount() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
|
||||
bool frameAlignment16 = (frameBuffer.getFrameCount() & 0x0F) == 0;
|
||||
if (frameAlignment16) {
|
||||
|
||||
if (frameBuffer.getChannelCount() == 2) {
|
||||
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); i += 16) {
|
||||
samples[0][i + 0] *= _gainLeft;
|
||||
samples[0][i + 1] *= _gainLeft;
|
||||
samples[0][i + 2] *= _gainLeft;
|
||||
samples[0][i + 3] *= _gainLeft;
|
||||
samples[0][i + 4] *= _gainLeft;
|
||||
samples[0][i + 5] *= _gainLeft;
|
||||
samples[0][i + 6] *= _gainLeft;
|
||||
samples[0][i + 7] *= _gainLeft;
|
||||
samples[0][i + 8] *= _gainLeft;
|
||||
samples[0][i + 9] *= _gainLeft;
|
||||
samples[0][i + 10] *= _gainLeft;
|
||||
samples[0][i + 11] *= _gainLeft;
|
||||
samples[0][i + 12] *= _gainLeft;
|
||||
samples[0][i + 13] *= _gainLeft;
|
||||
samples[0][i + 14] *= _gainLeft;
|
||||
samples[0][i + 15] *= _gainLeft;
|
||||
samples[1][i + 0] *= _gainRight;
|
||||
samples[1][i + 1] *= _gainRight;
|
||||
samples[1][i + 2] *= _gainRight;
|
||||
samples[1][i + 3] *= _gainRight;
|
||||
samples[1][i + 4] *= _gainRight;
|
||||
samples[1][i + 5] *= _gainRight;
|
||||
samples[1][i + 6] *= _gainRight;
|
||||
samples[1][i + 7] *= _gainRight;
|
||||
samples[1][i + 8] *= _gainRight;
|
||||
samples[1][i + 9] *= _gainRight;
|
||||
samples[1][i + 10] *= _gainRight;
|
||||
samples[1][i + 11] *= _gainRight;
|
||||
samples[1][i + 12] *= _gainRight;
|
||||
samples[1][i + 13] *= _gainRight;
|
||||
samples[1][i + 14] *= _gainRight;
|
||||
samples[1][i + 15] *= _gainRight;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert("unsupported channel format");
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); i += 1) {
|
||||
samples[0][i] *= _gainLeft;
|
||||
samples[1][i] *= _gainRight;
|
||||
}
|
||||
}
|
||||
}
|
||||
void render(AudioBufferFloat32& frameBuffer);
|
||||
};
|
||||
|
||||
|
||||
inline void AudioPan::render(AudioBufferFloat32& frameBuffer) {
|
||||
|
||||
if (frameBuffer.getChannelCount() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
|
||||
bool frameAlignment16 = (frameBuffer.getFrameCount() & 0x0F) == 0;
|
||||
if (frameAlignment16) {
|
||||
|
||||
if (frameBuffer.getChannelCount() == 2) {
|
||||
|
||||
for (uint32_t i = 0; i < frameBuffer.getFrameCount(); i += 16) {
|
||||
samples[0][i + 0] *= _gainLeft;
|
||||
samples[0][i + 1] *= _gainLeft;
|
||||
samples[0][i + 2] *= _gainLeft;
|
||||
samples[0][i + 3] *= _gainLeft;
|
||||
samples[0][i + 4] *= _gainLeft;
|
||||
samples[0][i + 5] *= _gainLeft;
|
||||
samples[0][i + 6] *= _gainLeft;
|
||||
samples[0][i + 7] *= _gainLeft;
|
||||
samples[0][i + 8] *= _gainLeft;
|
||||
samples[0][i + 9] *= _gainLeft;
|
||||
samples[0][i + 10] *= _gainLeft;
|
||||
samples[0][i + 11] *= _gainLeft;
|
||||
samples[0][i + 12] *= _gainLeft;
|
||||
samples[0][i + 13] *= _gainLeft;
|
||||
samples[0][i + 14] *= _gainLeft;
|
||||
samples[0][i + 15] *= _gainLeft;
|
||||
samples[1][i + 0] *= _gainRight;
|
||||
samples[1][i + 1] *= _gainRight;
|
||||
samples[1][i + 2] *= _gainRight;
|
||||
samples[1][i + 3] *= _gainRight;
|
||||
samples[1][i + 4] *= _gainRight;
|
||||
samples[1][i + 5] *= _gainRight;
|
||||
samples[1][i + 6] *= _gainRight;
|
||||
samples[1][i + 7] *= _gainRight;
|
||||
samples[1][i + 8] *= _gainRight;
|
||||
samples[1][i + 9] *= _gainRight;
|
||||
samples[1][i + 10] *= _gainRight;
|
||||
samples[1][i + 11] *= _gainRight;
|
||||
samples[1][i + 12] *= _gainRight;
|
||||
samples[1][i + 13] *= _gainRight;
|
||||
samples[1][i + 14] *= _gainRight;
|
||||
samples[1][i + 15] *= _gainRight;
|
||||
}
|
||||
} else {
|
||||
assert("unsupported channel format");
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < frameBuffer.getFrameCount(); i += 1) {
|
||||
samples[0][i] *= _gainLeft;
|
||||
samples[1][i] *= _gainRight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void AudioPan::updateCoefficients() {
|
||||
|
||||
// implement constant power sin^2 + cos^2 = 1 panning law
|
||||
|
||||
if (_pan >= ONE_MINUS_EPSILON) { // full right
|
||||
_gainLeft = 0.0f;
|
||||
_gainRight = 1.0f;
|
||||
} else if (_pan <= ZERO_PLUS_EPSILON) { // full left
|
||||
_gainLeft = 1.0f;
|
||||
_gainRight = 0.0f;
|
||||
} else if ((_pan >= ONE_HALF_MINUS_EPSILON) && (_pan <= ONE_HALF_PLUS_EPSILON)) { // center
|
||||
_gainLeft = 1.0f / SQUARE_ROOT_OF_2;
|
||||
_gainRight = 1.0f / SQUARE_ROOT_OF_2;
|
||||
} else { // intermediate cases
|
||||
_gainLeft = cosf( TWO_PI * _pan );
|
||||
_gainRight = sinf( TWO_PI * _pan );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AudioPan_h
|
||||
|
||||
|
||||
|
|
|
@ -70,8 +70,8 @@ public:
|
|||
uint32_t randomNumber;
|
||||
|
||||
float32_t** samples = frameBuffer.getFrameData();
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); ++i) {
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (uint32_t i = 0; i < frameBuffer.getFrameCount(); ++i) {
|
||||
for (uint32_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
|
||||
_index = (_index + 1) & _indexMask; // increment and mask index.
|
||||
if (_index != 0) { // if index is zero, don't update any random values.
|
||||
|
|
|
@ -44,7 +44,7 @@ inline void AudioSourceTone::render(AudioBufferFloat32& frameBuffer) {
|
|||
float32_t** samples = frameBuffer.getFrameData();
|
||||
float32_t yq;
|
||||
float32_t y;
|
||||
for (uint16_t i = 0; i < frameBuffer.getFrameCount(); ++i) {
|
||||
for (uint32_t i = 0; i < frameBuffer.getFrameCount(); ++i) {
|
||||
|
||||
yq = _yq1 - (_epsilon * _y1);
|
||||
y = _y1 + (_epsilon * yq);
|
||||
|
@ -53,7 +53,7 @@ inline void AudioSourceTone::render(AudioBufferFloat32& frameBuffer) {
|
|||
_yq1 = yq;
|
||||
_y1 = y;
|
||||
|
||||
for (uint16_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
for (uint32_t j = 0; j < frameBuffer.getChannelCount(); ++j) {
|
||||
samples[j][i] = _amplitude * y;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include <SharedUtil.h>
|
||||
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "AudioFormat.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioEditBuffer.h"
|
||||
#include "Sound.h"
|
||||
|
||||
// procedural audio version of Sound
|
||||
|
@ -120,6 +123,7 @@ void Sound::replyFinished() {
|
|||
// Process as RAW file
|
||||
downSample(rawAudioByteArray);
|
||||
}
|
||||
trimFrames();
|
||||
} else {
|
||||
qDebug() << "Network reply without 'Content-Type'.";
|
||||
}
|
||||
|
@ -133,7 +137,6 @@ void Sound::replyError(QNetworkReply::NetworkError code) {
|
|||
}
|
||||
|
||||
void Sound::downSample(const QByteArray& rawAudioByteArray) {
|
||||
|
||||
// assume that this was a RAW file and is now an array of samples that are
|
||||
// signed, 16-bit, 48Khz, mono
|
||||
|
||||
|
@ -155,6 +158,26 @@ void Sound::downSample(const QByteArray& rawAudioByteArray) {
|
|||
}
|
||||
}
|
||||
|
||||
void Sound::trimFrames() {
|
||||
|
||||
const uint32_t inputFrameCount = _byteArray.size() / sizeof(int16_t);
|
||||
const uint32_t trimCount = 1024; // number of leading and trailing frames to trim
|
||||
|
||||
if (inputFrameCount <= (2 * trimCount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t* inputFrameData = (int16_t*)_byteArray.data();
|
||||
|
||||
AudioEditBufferFloat32 editBuffer(1, inputFrameCount);
|
||||
editBuffer.copyFrames(1, inputFrameCount, inputFrameData, false /*copy in*/);
|
||||
|
||||
editBuffer.linearFade(0, trimCount, true);
|
||||
editBuffer.linearFade(inputFrameCount - trimCount, inputFrameCount, false);
|
||||
|
||||
editBuffer.copyFrames(1, inputFrameCount, inputFrameData, true /*copy out*/);
|
||||
}
|
||||
|
||||
//
|
||||
// Format description from https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
|
||||
//
|
||||
|
|
|
@ -33,6 +33,7 @@ private:
|
|||
QByteArray _byteArray;
|
||||
bool _hasDownloaded;
|
||||
|
||||
void trimFrames();
|
||||
void downSample(const QByteArray& rawAudioByteArray);
|
||||
void interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& outputAudioByteArray);
|
||||
|
||||
|
|
|
@ -656,6 +656,7 @@ class Material {
|
|||
public:
|
||||
glm::vec3 diffuse;
|
||||
glm::vec3 specular;
|
||||
glm::vec3 emissive;
|
||||
float shininess;
|
||||
float opacity;
|
||||
};
|
||||
|
@ -1281,7 +1282,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
textureContent.insert(filename, content);
|
||||
}
|
||||
} else if (object.name == "Material") {
|
||||
Material material = { glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), 96.0f, 1.0f };
|
||||
Material material = { glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(), 96.0f, 1.0f };
|
||||
foreach (const FBXNode& subobject, object.children) {
|
||||
bool properties = false;
|
||||
QByteArray propertyName;
|
||||
|
@ -1305,6 +1306,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
} else if (property.properties.at(0) == "SpecularColor") {
|
||||
material.specular = getVec3(property.properties, index);
|
||||
|
||||
} else if (property.properties.at(0) == "Emissive") {
|
||||
material.emissive = getVec3(property.properties, index);
|
||||
|
||||
} else if (property.properties.at(0) == "Shininess") {
|
||||
material.shininess = property.properties.at(index).value<double>();
|
||||
|
||||
|
@ -1605,6 +1609,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
FBXMeshPart& part = extracted.mesh.parts[j];
|
||||
part.diffuseColor = material.diffuse;
|
||||
part.specularColor = material.specular;
|
||||
part.emissiveColor = material.emissive;
|
||||
part.shininess = material.shininess;
|
||||
part.opacity = material.opacity;
|
||||
if (!diffuseTexture.filename.isNull()) {
|
||||
|
|
|
@ -108,6 +108,7 @@ public:
|
|||
|
||||
glm::vec3 diffuseColor;
|
||||
glm::vec3 specularColor;
|
||||
glm::vec3 emissiveColor;
|
||||
float shininess;
|
||||
float opacity;
|
||||
|
||||
|
|
Loading…
Reference in a new issue