Implement static pass in the lighting material
This commit is contained in:
parent
9c4fcac876
commit
77e552f551
@ -27,6 +27,9 @@ MaterialDef Phong Lighting {
|
||||
// Specular power/shininess
|
||||
Float Shininess : 1
|
||||
|
||||
// Ambient map
|
||||
Texture2D AmbientMap
|
||||
|
||||
// Diffuse map
|
||||
Texture2D DiffuseMap
|
||||
|
||||
@ -79,7 +82,7 @@ MaterialDef Phong Lighting {
|
||||
Boolean EnvMapAsSphereMap
|
||||
|
||||
//shadows
|
||||
Int FilterMode
|
||||
Int FilterMode
|
||||
Boolean HardwareShadows
|
||||
|
||||
Texture2D ShadowMap0
|
||||
@ -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
|
||||
|
||||
|
203
jme3-core/src/main/resources/Common/MatDefs/Light/StaticLighting.frag
Executable file
203
jme3-core/src/main/resources/Common/MatDefs/Light/StaticLighting.frag
Executable file
@ -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);
|
||||
*/
|
||||
}
|
32
jme3-core/src/main/resources/Common/MatDefs/Light/StaticLighting.vert
Executable file
32
jme3-core/src/main/resources/Common/MatDefs/Light/StaticLighting.vert
Executable file
@ -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);
|
||||
}
|
133
jme3-core/src/main/resources/Common/ShaderLib/InPassShadows.glsl
Executable file
133
jme3-core/src/main/resources/Common/ShaderLib/InPassShadows.glsl
Executable file
@ -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…
x
Reference in New Issue
Block a user