Implement static pass in the lighting material

in-pass-shadows
Kirill Vainer 8 years ago
parent 9c4fcac876
commit 77e552f551
  1. 24
      jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md
  2. 203
      jme3-core/src/main/resources/Common/MatDefs/Light/StaticLighting.frag
  3. 32
      jme3-core/src/main/resources/Common/MatDefs/Light/StaticLighting.vert
  4. 133
      jme3-core/src/main/resources/Common/ShaderLib/InPassShadows.glsl
  5. 2
      jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java
  6. 7
      jme3-core/src/plugins/java/com/jme3/shader/plugins/GLSLLoader.java

@ -27,6 +27,9 @@ MaterialDef Phong Lighting {
// Specular power/shininess
Float Shininess : 1
// Ambient map
Texture2D AmbientMap
// Diffuse map
Texture2D DiffuseMap
@ -117,6 +120,27 @@ MaterialDef Phong Lighting {
Boolean BackfaceShadows : false
}
Technique {
LightMode StaticPass
VertexShader GLSL100 GLSL150 : Common/MatDefs/Light/StaticLighting.vert
FragmentShader GLSL100 GLSL150 : Common/MatDefs/Light/StaticLighting.frag
WorldParameters {
WorldViewProjectionMatrix
NormalMatrix
WorldViewMatrix
ViewMatrix
CameraPosition
WorldMatrix
ViewProjectionMatrix
}
Defines {
AMBIENTMAP : AmbientMap
}
}
Technique {
LightMode SinglePass

@ -0,0 +1,203 @@
#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/ShaderLib/BlinnPhongLighting.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
#import "Common/ShaderLib/InPassShadows.glsl"
#ifndef NUM_DIR_LIGHTS
#define NUM_DIR_LIGHTS 0
#endif
#ifndef NUM_POINT_LIGHTS
#define NUM_POINT_LIGHTS 0
#endif
#ifndef NUM_SPOT_LIGHTS
#define NUM_SPOT_LIGHTS 0
#endif
#define DIR_SHADOW_LIGHT_START (0)
#define DIR_SHADOW_LIGHT_END (NUM_SHADOW_DIR_LIGHTS * 2)
#define DIR_LIGHT_START (DIR_SHADOW_LIGHT_END)
#define DIR_LIGHT_END (NUM_DIR_LIGHTS * 2)
#define POINT_LIGHT_START (DIR_LIGHT_END)
#define POINT_LIGHT_END (POINT_LIGHT_START + NUM_POINT_LIGHTS * 2)
#define SPOT_SHADOW_LIGHT_START (POINT_LIGHT_END)
#define SPOT_SHADOW_LIGHT_END (SPOT_SHADOW_LIGHT_START + NUM_SHADOW_SPOT_LIGHTS * 3)
#define SPOT_LIGHT_START (SPOT_SHADOW_LIGHT_END)
#define SPOT_LIGHT_END (SPOT_LIGHT_START + NUM_SPOT_LIGHTS * 3)
#define LIGHT_DATA_SIZE (SPOT_LIGHT_END)
uniform sampler2D m_AmbientMap;
uniform float m_AlphaDiscardThreshold;
uniform float m_Shininess;
uniform vec4 g_AmbientLightColor;
#if LIGHT_DATA_SIZE > 0
uniform vec4 g_LightData[LIGHT_DATA_SIZE];
#else
const vec4 g_LightData[1] = vec4[]( vec4(1.0) );
#endif
varying vec3 vPos;
varying vec3 vNormal;
varying vec2 vTexCoord;
struct surface_t {
vec3 position;
vec3 normal;
vec3 viewDir;
vec3 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
};
vec2 Lighting_ProcessLighting(vec3 norm, vec3 viewDir, vec3 lightDir, float attenuation, float shininess) {
float diffuseFactor = max(0.0, dot(norm, lightDir));
vec3 H = normalize(viewDir + lightDir);
float HdotN = max(0.0, dot(H, norm));
float specularFactor = pow(HdotN, shininess);
return vec2(diffuseFactor, diffuseFactor * specularFactor) * vec2(attenuation);
}
vec2 Lighting_ProcessDirectional(int lightIndex, surface_t surface) {
vec3 lightDirection = g_LightData[lightIndex + 1].xyz;
vec2 light = Lighting_ProcessLighting(surface.normal, surface.viewDir, -lightDirection, 1.0, surface.shininess);
return light;
}
float Lighting_ProcessAttenuation(float invRadius, float dist) {
#ifdef SRGB
float atten = (1.0 - invRadius * dist) / (1.0 + invRadius * dist * dist);
return clamp(atten, 0.0, 1.0);
#else
return max(0.0, 1.0 - invRadius * dist);
#endif
}
vec2 Lighting_ProcessPoint(int lightIndex, surface_t surface) {
vec4 lightPosition = g_LightData[lightIndex + 1];
vec3 lightDirection = lightPosition.xyz - surface.position;
float dist = length(lightDirection);
lightDirection /= vec3(dist);
float atten = Lighting_ProcessAttenuation(lightPosition.w, dist);
return Lighting_ProcessLighting(surface.normal, surface.viewDir, lightDirection, atten, surface.shininess);
}
vec2 Lighting_ProcessSpot(int lightIndex, surface_t surface) {
vec4 lightPosition = g_LightData[lightIndex + 1];
vec4 lightDirection = g_LightData[lightIndex + 2];
vec3 lightVector = lightPosition.xyz - surface.position;
float dist = length(lightVector);
lightVector /= vec3(dist);
float atten = Lighting_ProcessAttenuation(lightPosition.w, dist);
atten *= computeSpotFalloff(lightDirection, lightVector);
return Lighting_ProcessLighting(surface.normal, surface.viewDir, lightVector, atten, surface.shininess);
}
void Lighting_ProcessAll(surface_t surface, out vec3 ambient, out vec3 diffuse, out vec3 specular) {
ambient = g_AmbientLightColor.rgb;
diffuse = vec3(0.0);
specular = vec3(0.0);
Shadow_ProcessPssmSlice();
#if LIGHT_DATA_SIZE > 0
int projIndex = 0;
for (int i = DIR_SHADOW_LIGHT_START; i < DIR_SHADOW_LIGHT_END; i += 2) {
vec4 lightColor = g_LightData[i];
vec2 lightDiffSpec = Lighting_ProcessDirectional(i, surface);
float shadow = Shadow_ProcessDirectional(projIndex, lightColor.w);
lightDiffSpec *= vec2(shadow);
diffuse += lightColor.rgb * lightDiffSpec.x;
specular += lightColor.rgb * lightDiffSpec.y;
projIndex += NUM_PSSM_SPLITS;
}
for (int i = DIR_LIGHT_START; i < DIR_LIGHT_END; i += 2) {
vec3 lightColor = g_LightData[i].rgb;
vec2 lightDiffSpec = Lighting_ProcessDirectional(i, surface);
diffuse += lightColor.rgb * lightDiffSpec.x;
specular += lightColor.rgb * lightDiffSpec.y;
}
for (int i = POINT_LIGHT_START; i < POINT_LIGHT_END; i += 2) {
vec3 lightColor = g_LightData[i].rgb;
vec2 lightDiffSpec = Lighting_ProcessPoint(i, surface);
diffuse += lightColor.rgb * lightDiffSpec.x;
specular += lightColor.rgb * lightDiffSpec.y;
}
for (int i = SPOT_SHADOW_LIGHT_START; i < SPOT_SHADOW_LIGHT_END; i += 3) {
vec4 lightColor = g_LightData[i];
vec2 lightDiffSpec = Lighting_ProcessSpot(i, surface);
float shadow = Shadow_ProcessSpot(projIndex, lightColor.w);
lightDiffSpec *= vec2(shadow);
diffuse += lightColor.rgb * lightDiffSpec.x;
specular += lightColor.rgb * lightDiffSpec.y;
projIndex++;
}
for (int i = SPOT_LIGHT_START; i < SPOT_LIGHT_END; i += 3) {
vec3 lightColor = g_LightData[i].rgb;
vec2 lightDiffSpec = Lighting_ProcessSpot(i, surface);
diffuse += lightColor * lightDiffSpec.x;
specular += lightColor * lightDiffSpec.y;
}
#endif
}
surface_t getSurface() {
surface_t s;
s.position = vPos;
s.normal = normalize(vNormal);
if (!gl_FrontFacing) {
s.normal = -s.normal;
}
s.viewDir = normalize(-vPos);
#ifdef AMBIENTMAP
s.ambient = texture2D(m_AmbientMap, vTexCoord).rgb;
#else
s.ambient = vec3(1.0);
#endif
s.diffuse = vec4(1.0);
s.specular = vec4(1.0);
s.shininess = m_Shininess;
return s;
}
void main() {
vec3 ambient, diffuse, specular;
surface_t surface = getSurface();
Lighting_ProcessAll(surface, ambient, diffuse, specular);
vec4 color = vec4(1.0);
color.rgb = surface.ambient.rgb * ambient +
surface.diffuse.rgb * diffuse +
surface.specular.rgb * specular;
#ifdef DISCARD_ALPHA
if (color.a < m_AlphaDiscardThreshold) {
discard;
}
#endif
gl_FragColor = color;
/*
vec4 projCoord = vProjCoord[0];
projCoord.xyz /= projCoord.w;
float shad = shadow2D(g_ShadowMapArray, vec4(projCoord.xy, 0.0, projCoord.z)).r;
vec3 amb = texture2D(m_AmbientMap, vTexCoord).rgb;
gl_FragColor = vec4(amb * vec3(shad), 1.0);
*/
}

@ -0,0 +1,32 @@
#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/ShaderLib/Skinning.glsllib"
#import "Common/ShaderLib/Instancing.glsllib"
#import "Common/ShaderLib/InPassShadows.glsl"
attribute vec3 inPosition;
attribute vec3 inNormal;
attribute vec2 inTexCoord;
attribute vec4 inColor;
varying vec3 vPos;
varying vec3 vNormal;
varying vec2 vTexCoord;
void main() {
vTexCoord = inTexCoord;
vec4 modelSpacePos = vec4(inPosition, 1.0);
vec3 modelSpaceNorm = inNormal;
#ifdef NUM_BONES
Skinning_Compute(modelSpacePos, modelSpaceNorm);
#endif
vPos = TransformWorldView(modelSpacePos).xyz;
vNormal = TransformNormal(modelSpaceNorm);
vec3 shadowPos = TransformWorld(modelSpacePos).xyz;
Shadow_ProcessProjCoord(shadowPos);
gl_Position = TransformWorldViewProjection(modelSpacePos);
}

@ -0,0 +1,133 @@
#ifndef NUM_SHADOW_DIR_LIGHTS
#define NUM_SHADOW_DIR_LIGHTS 0
#endif
#ifndef NUM_SHADOW_POINT_LIGHTS
#define NUM_SHADOW_POINT_LIGHTS 0
#endif
#ifndef NUM_SHADOW_SPOT_LIGHTS
#define NUM_SHADOW_SPOT_LIGHTS 0
#endif
#ifndef NUM_PSSM_SPLITS
#define NUM_PSSM_SPLITS 0
#endif
#define SHADOW_DATA_SIZE (NUM_SHADOW_DIR_LIGHTS * NUM_PSSM_SPLITS + NUM_SHADOW_POINT_LIGHTS * 6 + NUM_SHADOW_SPOT_LIGHTS)
#if SHADOW_DATA_SIZE > 0
varying vec4 vProjCoord[SHADOW_DATA_SIZE];
#ifdef VERTEX_SHADER
uniform mat4 g_ShadowMatrices[SHADOW_DATA_SIZE];
void Shadow_ProcessProjCoord(vec3 worldPos) {
for (int i = 0; i < SHADOW_DATA_SIZE; i++) {
vProjCoord[i] = g_ShadowMatrices[i] * vec4(worldPos, 1.0);
}
}
#else
uniform sampler2DArrayShadow g_ShadowMapArray;
uniform vec4 g_PssmSplits;
int pssmSliceOffset;
void Shadow_ProcessPssmSlice() {
#ifdef NUM_PSSM_SPLITS
float z = gl_FragCoord.z;
if (z < g_PssmSplits[0]) {
pssmSliceOffset = 0;
} else if (z < g_PssmSplits[1]) {
pssmSliceOffset = 1;
} else if (z < g_PssmSplits[2]) {
pssmSliceOffset = 2;
} else {
pssmSliceOffset = 3;
}
#else
pssmSliceOffset = 0;
#endif
}
float Shadow_ProcessDirectional(int startProjIndex, float startArrayLayer) {
float arraySlice = startArrayLayer + float(pssmSliceOffset);
vec3 projCoord = vProjCoord[startProjIndex + pssmSliceOffset].xyz;
return texture(g_ShadowMapArray, vec4(projCoord.xy, arraySlice, projCoord.z));
}
float Shadow_ProcessSpot(int startProjIndex, float startArrayLayer) {
vec4 projCoord = vProjCoord[startProjIndex];
projCoord.xyz /= projCoord.w;
return texture(g_ShadowMapArray, vec4(projCoord.xy, startArrayLayer, projCoord.z));
}
#endif
#elif NUM_PSSM_SPLITS > 0
// A lightweight version of in-pass lighting that only handles directional lights
// Control flow and loop iteration count are static
varying vec4 vProjCoord[NUM_PSSM_SPLITS];
#ifdef VERTEX_SHADER
uniform mat4 g_DirectionalShadowMatrix[NUM_PSSM_SPLITS];
void Shadow_ProcessProjCoord(vec3 worldPos) {
for (int i = 0; i < NUM_PSSM_SPLITS; i++) {
vProjCoord[i] = g_DirectionalShadowMatrix[i] * vec4(worldPos, 1.0);
}
}
#else
uniform sampler2DShadow g_DirectionalShadowMap[NUM_PSSM_SPLITS];
uniform vec4 g_PssmSplits;
const vec2 invTexSize = vec2(1.0 / 1024.0);
float Shadow_SampleOffset(sampler2DShadow shadowMap, vec4 projCoord, vec2 offset) {
return shadow2D(shadowMap, vec3(projCoord.xy + offset * invTexSize, projCoord.z)).r;
}
float Shadow_Sample(sampler2DShadow shadowMap, vec4 projCoord) {
return shadow2D(shadowMap, projCoord.xyz).r;
}
#define GET_SHADOW(i) if (z < g_PssmSplits[i]) return Shadow_Sample(g_DirectionalShadowMap[i], vProjCoord[i]);
void Shadow_ProcessPssmSlice() {
}
float Shadow_ProcessDirectional() {
float z = gl_FragCoord.z;
GET_SHADOW(0);
#if NUM_PSSM_SPLITS > 1
GET_SHADOW(1)
#if NUM_PSSM_SPLITS > 2
GET_SHADOW(2)
#if NUM_PSSM_SPLITS > 3
GET_SHADOW(3)
#endif
#endif
#endif
return 1.0;
}
#endif
#else
#define NUM_SHADOW_DIR_LIGHTS 0
#define NUM_SHADOW_POINT_LIGHTS 0
#define NUM_SHADOW_SPOT_LIGHTS 0
#define NUM_PSSM_SPLITS 0
void Shadow_ProcessProjCoord(vec3 worldPos) {
}
void Shadow_ProcessPssmSlice() {
}
float Shadow_ProcessDirectional(int startLightIndex, float startArrayLayer) {
return 1.0;
}
float Shadow_ProcessSpot(int startLightIndex, float startArrayLayer) {
return 1.0;
}
#endif

@ -646,7 +646,7 @@ public class J3MLoader implements AssetLoader {
technique.setLogic(new SinglePassLightingLogic(technique));
break;
case StaticPass:
technique.setLogic(new StaticPassLightingLogic(technique));
technique.setLogic(new ShadowStaticPassLightingLogic(technique));
break;
case SinglePassAndImageBased:
technique.setLogic(new SinglePassAndImageBasedLightingLogic(technique));

@ -49,7 +49,7 @@ import java.util.*;
public class GLSLLoader implements AssetLoader {
private AssetManager assetManager;
private Map<String, ShaderDependencyNode> dependCache = new HashMap<String, ShaderDependencyNode>();
private final Map<String, ShaderDependencyNode> dependCache = new HashMap<>();
/**
* Used to load {@link ShaderDependencyNode}s.
@ -168,7 +168,7 @@ public class GLSLLoader implements AssetLoader {
return node.getSource();
} else {
StringBuilder sb = new StringBuilder(node.getSource());
List<String> resolvedShaderNodes = new ArrayList<String>();
List<String> resolvedShaderNodes = new ArrayList<>();
for (ShaderDependencyNode dependencyNode : node.getDependencies()) {
resolvedShaderNodes.add(resolveDependencies(dependencyNode, alreadyInjectedSet, extensions));
@ -187,7 +187,8 @@ public class GLSLLoader implements AssetLoader {
// to retrieve the fragment shader, use the content manager
this.assetManager = info.getManager();
Reader reader = new InputStreamReader(info.openStream());
if (info.getKey().getExtension().equals("glsllib")) {
String extension = info.getKey().getExtension();
if (extension.equals("glsllib") || extension.equals("glsl")) {
// NOTE: Loopback, GLSLLIB is loaded by this loader
// and needs data as InputStream
return reader;

Loading…
Cancel
Save