Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,53 @@
public class ComputeShader extends NativeObject {

private final GL4 gl;
// These need not be stored, but it helps with debugging.
private final String source;

/**
* Creates a new compute shader from GLSL source code.
*/
public ComputeShader(GL4 gl, String source) {
super();
this.gl = gl;
this.source = source;
//Load this upfront to surface any problems at init time
// Load this upfront to surface any problems at init time
createComputeShader();
}
private ComputeShader(ComputeShader source){

/**
* Creates a new compute shader from GLSL source code and a set of defines.
*/
public ComputeShader(GL4 gl, String source, String[][] defines) {
Comment thread
jeannekamikaze marked this conversation as resolved.
super();
this.gl = gl;
this.source = addDefines(source, defines);
System.out.println(this.source);
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated
// Load this upfront to surface any problems at init time
createComputeShader();
}

private ComputeShader(ComputeShader source) {
super();
this.gl = source.gl;
this.id = source.id;
this.source = null;
}

private void createComputeShader(){
private String addDefines(String source, String[][] defines) {
String[] sourceLines = (String[])source.split("\\r?\\n");
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated
StringBuilder builder = new StringBuilder();
builder.append(sourceLines[0] + "\n");
for (String[] pair : defines) {
builder.append("#define " + pair[0] + " " + pair[1] + "\n");
}
for (int i = 1; i < sourceLines.length; ++i) {
builder.append(sourceLines[i] + "\n");
}
return builder.toString();
}
Comment thread
riccardobl marked this conversation as resolved.

private void createComputeShader() {
// Create and compile the shader
int shaderId = gl.glCreateShader(GL4.GL_COMPUTE_SHADER);
if (shaderId <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ private void initGL() {

sdsmFitter = new SdsmFitter(gl4, renderer, assetManager);
glInitialized = true;

}

/**
Expand Down
65 changes: 54 additions & 11 deletions jme3-core/src/main/java/com/jme3/shadow/SdsmFitter.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,16 @@ public class SdsmFitter {

private final GL4 gl4;
private final Renderer renderer;
private final AssetManager assetManager;
private int maxFrameLag = 3;

private final ComputeShader depthReduceShader;
private final ComputeShader fitFrustumsShader;
private ComputeShader depthReduceShader;
private ComputeShader fitFrustumsShader;

private ComputeShader depthReduceShaderNoMs;
private ComputeShader fitFrustumsShaderNoMs;
private ComputeShader depthReduceShaderMs;
private ComputeShader fitFrustumsShaderMs;
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated

private final LinkedList<SdsmResultHolder> resultHoldersInFlight = new LinkedList<>();
private final LinkedList<SdsmResultHolder> resultHoldersReady = new LinkedList<>();
Expand Down Expand Up @@ -313,15 +319,38 @@ void cleanup() {
public SdsmFitter(GL4 gl, Renderer renderer, AssetManager assetManager) {
this.gl4 = gl;
this.renderer = renderer;
this.assetManager = assetManager;
}

// Load compute shaders
private ComputeShader buildShader(String source, boolean multisampling) {
ComputeShader shader =
multisampling
? new ComputeShader(gl4, source, new String[][]{{"RESOLVE_DEPTH_MS", "1"}})
: new ComputeShader(gl4, source);
renderer.registerNativeObject(shader);
return shader;
}

private void initShaders(Texture depthTexture) {
String reduceSource = (String)assetManager.loadAsset(REDUCE_DEPTH_SHADER);
String fitSource = (String)assetManager.loadAsset(FIT_FRUSTUMS_SHADER);

if (depthTexture.getImage().getMultiSamples() > 1) {
if (depthReduceShaderMs == null) {
depthReduceShaderMs = buildShader(reduceSource, true);
fitFrustumsShaderMs = buildShader(fitSource, true);
}
depthReduceShader = depthReduceShaderMs;
fitFrustumsShader = fitFrustumsShaderMs;

depthReduceShader = new ComputeShader(gl, reduceSource);
renderer.registerNativeObject(depthReduceShader);
fitFrustumsShader = new ComputeShader(gl, fitSource);
renderer.registerNativeObject(fitFrustumsShader);
} else if (depthTexture.getImage().getMultiSamples() == 1) {
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated
if (depthReduceShaderNoMs == null) {
depthReduceShaderNoMs = buildShader(reduceSource, false);
fitFrustumsShaderNoMs = buildShader(fitSource, false);
}
depthReduceShader = depthReduceShaderNoMs;
fitFrustumsShader = fitFrustumsShaderNoMs;
}
}

/**
Expand All @@ -336,6 +365,10 @@ public SdsmFitter(GL4 gl, Renderer renderer, AssetManager assetManager) {
public void fit(Texture depthTexture, int splitCount, Matrix4f cameraToLight,
float cameraNear, float cameraFar) {

int depthMultiSamples = depthTexture.getImage().getMultiSamples();

initShaders(depthTexture);

SdsmResultHolder holder = getResultHolderForUse();
holder.parameters = new FitParameters(cameraToLight, splitCount, cameraNear, cameraFar);

Expand All @@ -360,6 +393,8 @@ public void fit(Texture depthTexture, int splitCount, Matrix4f cameraToLight,
} catch (TextureUnitException e) {
throw new RendererException(e);
}
int loc = depthReduceShader.getUniformLocation("m_NumSamplesDepth");
depthReduceShader.setUniform(loc, depthMultiSamples);
depthReduceShader.bindShaderStorageBuffer(1, holder.minMaxDepthSsbo);
depthReduceShader.dispatch(xGroups, yGroups, 1);
gl4.glMemoryBarrier(GL4.GL_SHADER_STORAGE_BARRIER_BIT);
Expand All @@ -373,6 +408,8 @@ public void fit(Texture depthTexture, int splitCount, Matrix4f cameraToLight,
} catch (TextureUnitException e) {
throw new RendererException(e);
}
loc = fitFrustumsShader.getUniformLocation("m_NumSamplesDepth");
fitFrustumsShader.setUniform(loc, depthMultiSamples);
fitFrustumsShader.bindShaderStorageBuffer(1, holder.minMaxDepthSsbo);
fitFrustumsShader.bindShaderStorageBuffer(2, holder.fitFrustumSsbo);

Expand Down Expand Up @@ -437,11 +474,17 @@ public void cleanup() {
}
resultHoldersReady.clear();

if (depthReduceShader != null) {
depthReduceShader.deleteObject(renderer);
if (depthReduceShaderMs != null) {
depthReduceShaderMs.deleteObject(renderer);
}
if (fitFrustumsShaderMs != null) {
fitFrustumsShaderMs.deleteObject(renderer);
}
if (depthReduceShaderNoMs != null) {
depthReduceShaderNoMs.deleteObject(renderer);
}
if (fitFrustumsShader != null) {
fitFrustumsShader.deleteObject(renderer);
if (fitFrustumsShaderNoMs != null) {
fitFrustumsShaderNoMs.deleteObject(renderer);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#version 430

#import "Common/ShaderLib/MultiSample.glsllib"

/**
* Computes tight bounding boxes for each shadow cascade via min/max on lightspace locations of depth samples that fall within each cascade.
*/

layout(local_size_x = 16, local_size_y = 16) in;

layout(binding = 0) uniform sampler2D inputDepth;
layout(binding = 0) uniform DEPTHTEXTURE inputDepth;

layout(std430, binding = 1) readonly buffer MinMaxBuffer {
uint gMin;
Expand Down Expand Up @@ -103,7 +105,7 @@ void main() {
ivec2 gid = ivec2(gl_GlobalInvocationID.xy);
ivec2 lid = ivec2(gl_LocalInvocationID.xy);
uint tid = gl_LocalInvocationIndex;
ivec2 inputSize = textureSize(inputDepth, 0);
ivec2 inputSize = getTextureSize(inputDepth);
ivec2 baseCoord = gid * 2;

// Initialize local bounds to infinity
Expand All @@ -126,11 +128,11 @@ void main() {
for (int x = 0; x < 2; x++) {
ivec2 coord = baseCoord + ivec2(x, y);
if (coord.x < inputSize.x && coord.y < inputSize.y) {
float depth = texelFetch(inputDepth, coord, 0).r;
float depth = getDepthMax(inputDepth, coord, m_NumSamplesDepth).r;
// Skip background (depth == 1.0)
if (depth != 1.0) {
// Reconstruct clip-space position from depth
vec2 uv = (vec2(coord) + 0.5) / vec2(textureSize(inputDepth, 0));
vec2 uv = (vec2(coord) + 0.5) / vec2(getTextureSize(inputDepth));
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);

// Transform to light view space
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#version 430

#import "Common/ShaderLib/MultiSample.glsllib"

/**
* Finds the global minimum/maximum values of a depth texture.
*/

layout(local_size_x = 16, local_size_y = 16) in;

layout(binding = 0) uniform sampler2D inputDepth;
layout(binding = 0) uniform DEPTHTEXTURE inputDepth;

layout(std430, binding = 1) buffer MinMaxBuffer {
uint gMin;
Expand All @@ -33,7 +35,7 @@ void main() {
ivec2 gid = ivec2(gl_GlobalInvocationID.xy);
ivec2 lid = ivec2(gl_LocalInvocationID.xy);
uint tid = gl_LocalInvocationIndex;
ivec2 inputSize = textureSize(inputDepth, 0);
ivec2 inputSize = getTextureSize(inputDepth);

// Each thread samples a 2x2 block
ivec2 baseCoord = gid * 2;
Expand All @@ -43,7 +45,7 @@ void main() {
for (int x = 0; x < 2; x++) {
ivec2 coord = baseCoord + ivec2(x, y);
if (coord.x < inputSize.x && coord.y < inputSize.y) {
float depth = texelFetch(inputDepth, coord, 0).r;
float depth = getDepthMax(inputDepth, coord, m_NumSamplesDepth).r;
// Discard depth == 1.0 (background/sky)
if (depth != 1.0) {
minMax.x = min(minMax.x, depth);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/ShaderLib/MultiSample.glsllib"
#import "Common/ShaderLib/Shadows.glsllib"

//Stripped version of the usual shadow fragment shader for SDSM; it intentionally leaves out some features.
uniform sampler2D m_Texture;
uniform sampler2D m_DepthTexture;
uniform COLORTEXTURE m_Texture;
uniform DEPTHTEXTURE m_DepthTexture;
uniform mat4 m_ViewProjectionMatrixInverse;
uniform vec4 m_ViewProjectionMatrixRow2;

Expand Down Expand Up @@ -43,8 +44,8 @@ float determineShadow(int index, vec4 worldPos){
}

void main() {
float depth = texture2D(m_DepthTexture,texCoord).r;
vec4 color = texture2D(m_Texture,texCoord);
float depth = getColor(m_DepthTexture,texCoord).r;
vec4 color = getDepth(m_Texture,texCoord);
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated

//Discard shadow computation on the sky
if(depth == 1.0){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ MaterialDef Post Shadow {
Texture2D DepthTexture

Boolean BackfaceShadows //Not used.
Int NumSamples //Not used.
Int NumSamples
Int NumSamplesDepth
}

Technique {
Expand All @@ -47,6 +48,8 @@ MaterialDef Post Shadow {
FILTER_MODE : FilterMode
PCFEDGE : PCFEdge
SHADOWMAP_SIZE : ShadowMapSize
RESOLVE_MS : NumSamples
RESOLVE_DEPTH_MS : NumSamplesDepth
}
}
}
56 changes: 44 additions & 12 deletions jme3-core/src/main/resources/Common/ShaderLib/MultiSample.glsllib
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ uniform int m_NumSamplesDepth;
// NOTE: Only define multisample functions if multisample is available
#if defined(GL_ARB_texture_multisample) || (defined GL_ES && __VERSION__>=310)
vec4 textureFetch(in sampler2DMS tex,in vec2 texC, in int numSamples){
ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
vec4 color = vec4(0.0);
for (int i = 0; i < numSamples; i++){
color += texelFetch(tex, iTexC, i);
}
return color / float(numSamples);
ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
vec4 color = vec4(0.0);
for (int i = 0; i < numSamples; i++){
color += texelFetch(tex, iTexC, i);
}
return color / float(numSamples);
}

vec4 fetchTextureSample(in sampler2DMS tex,in vec2 texC,in int sampleId){
Expand All @@ -40,25 +40,57 @@ vec4 getColorSingle(in sampler2DMS tex, in vec2 texC){
return texelFetch(tex, iTexC, 0);
}

vec4 getDepth(in sampler2DMS tex,in vec2 texC){
return textureFetch(tex,texC,m_NumSamplesDepth);
vec4 getDepth(in sampler2DMS tex, in vec2 texC){
return textureFetch(tex,texC,m_NumSamplesDepth);

}

#endif
vec4 getDepthMax(in sampler2DMS tex, in ivec2 coord, in int numSamples){
vec4 result = vec4(0.0);
for (int i = 0; i < numSamples; i++){
result = max(result, texelFetch(tex, coord, i));
}
return result;
}

ivec2 getTextureSize(in sampler2DMS tex) {
return textureSize(tex);
}
#endif // Multisampling

vec4 fetchTextureSample(in sampler2D tex,in vec2 texC,in int sampleId){
#if __VERSION__>=430
return texture(tex,texC);
#else
return texture2D(tex,texC);
#endif
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated
}

vec4 getColor(in sampler2D tex, in vec2 texC){
#if __VERSION__>=430
return texture(tex,texC);
#else
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated
return texture2D(tex,texC);
#endif
}

vec4 getColorSingle(in sampler2D tex, in vec2 texC){
return texture2D(tex, texC);
#if __VERSION__>=430
return texture(tex,texC);
Comment thread
jeannekamikaze marked this conversation as resolved.
Outdated
#else
return texture2D(tex,texC);
#endif
}

vec4 getDepth(in sampler2D tex,in vec2 texC){
return texture2D(tex,texC);
vec4 getDepth(in sampler2D tex, in vec2 texC){
ivec2 iTexC = ivec2(texC * vec2(textureSize(tex, 0)));
return texelFetch(tex, iTexC, 0);
Comment thread
riccardobl marked this conversation as resolved.
Outdated
}

vec4 getDepthMax(in sampler2D tex, in ivec2 coord, in int numSamples){
return texelFetch(tex, coord, 0);
}

ivec2 getTextureSize(in sampler2D tex){
return textureSize(tex, 0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ private ShaderDependencyNode loadNode(Reader reader, String nodeName) {
}
} else if (tln.startsWith("#extension ")) {
sbExt.append(ln).append('\n');
} else if (tln.startsWith("#version ")) {
// #version must appear before the extensions, so treat it like one.
sbExt.append(ln).append('\n');
} else {
Comment thread
riccardobl marked this conversation as resolved.
sb.append(ln).append('\n');
}
Expand Down
Loading