Skip to content

Commit ab19180

Browse files
authored
Merge pull request jMonkeyEngine#2578 from ScottPeterJohnson/sdsm
Implement an Sample-Distribution Shadow Mapping filter
2 parents 77fdf95 + e4cda6f commit ab19180

File tree

25 files changed

+2763
-9
lines changed

25 files changed

+2763
-9
lines changed

jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ public void glGetBufferSubData(int target, long offset, ByteBuffer data) {
163163
throw new UnsupportedOperationException("OpenGL ES 2 does not support glGetBufferSubData");
164164
}
165165

166+
@Override
167+
public void glGetBufferSubData(int target, long offset, IntBuffer data) {
168+
throw new UnsupportedOperationException("OpenGL ES 2 does not support glGetBufferSubData");
169+
}
170+
166171
@Override
167172
public void glClear(int mask) {
168173
GLES20.glClear(mask);

jme3-core/src/main/java/com/jme3/renderer/Renderer.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
import com.jme3.material.RenderState;
3535
import com.jme3.math.ColorRGBA;
36+
import com.jme3.renderer.opengl.GLFence;
3637
import com.jme3.scene.Mesh;
3738
import com.jme3.scene.VertexBuffer;
3839
import com.jme3.shader.bufferobject.BufferObject;
@@ -552,5 +553,11 @@ public default void pushDebugGroup(String name) {
552553

553554
public void setShaderStorageBufferObject(int bindingPoint, BufferObject bufferObject) ;
554555
public void setUniformBufferObject(int bindingPoint, BufferObject bufferObject) ;
555-
556+
557+
public void deleteFence(GLFence fence);
558+
559+
/**
560+
* Registers a NativeObject to be cleaned up by this renderer.
561+
*/
562+
public void registerNativeObject(NativeObject nativeObject);
556563
}

jme3-core/src/main/java/com/jme3/renderer/RendererException.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@ public class RendererException extends RuntimeException {
4747
public RendererException(String message) {
4848
super(message);
4949
}
50+
public RendererException(Exception e) {
51+
super(e);
52+
}
5053
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Copyright (c) 2009-2026 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
package com.jme3.renderer.opengl;
33+
34+
import com.jme3.math.Matrix4f;
35+
import com.jme3.math.Vector2f;
36+
import com.jme3.math.Vector3f;
37+
import com.jme3.math.Vector4f;
38+
import com.jme3.renderer.RendererException;
39+
import com.jme3.util.BufferUtils;
40+
import com.jme3.util.NativeObject;
41+
42+
import java.nio.FloatBuffer;
43+
import java.nio.IntBuffer;
44+
45+
/**
46+
* A compute shader for general-purpose GPU computing (GPGPU).
47+
* <p>
48+
* Compute shaders require OpenGL 4.3 or higher.
49+
*/
50+
public class ComputeShader extends NativeObject {
51+
52+
private final GL4 gl;
53+
private final String source;
54+
/**
55+
* Creates a new compute shader from GLSL source code.
56+
*/
57+
public ComputeShader(GL4 gl, String source) {
58+
super();
59+
this.gl = gl;
60+
this.source = source;
61+
//Load this upfront to surface any problems at init time
62+
createComputeShader();
63+
}
64+
private ComputeShader(ComputeShader source){
65+
super();
66+
this.gl = source.gl;
67+
this.id = source.id;
68+
this.source = null;
69+
}
70+
71+
private void createComputeShader(){
72+
// Create and compile the shader
73+
int shaderId = gl.glCreateShader(GL4.GL_COMPUTE_SHADER);
74+
if (shaderId <= 0) {
75+
throw new RendererException("Failed to create compute shader");
76+
}
77+
78+
IntBuffer intBuf = BufferUtils.createIntBuffer(1);
79+
intBuf.clear();
80+
intBuf.put(0, source.length());
81+
gl.glShaderSource(shaderId, new String[]{source}, intBuf);
82+
gl.glCompileShader(shaderId);
83+
84+
// Check compilation status
85+
gl.glGetShader(shaderId, GL.GL_COMPILE_STATUS, intBuf);
86+
if (intBuf.get(0) != GL.GL_TRUE) {
87+
gl.glGetShader(shaderId, GL.GL_INFO_LOG_LENGTH, intBuf);
88+
String infoLog = gl.glGetShaderInfoLog(shaderId, intBuf.get(0));
89+
gl.glDeleteShader(shaderId);
90+
throw new RendererException("Compute shader compilation failed: " + infoLog);
91+
}
92+
93+
// Create program and link
94+
id = gl.glCreateProgram();
95+
if (id <= 0) {
96+
gl.glDeleteShader(shaderId);
97+
throw new RendererException("Failed to create shader program");
98+
}
99+
100+
gl.glAttachShader(id, shaderId);
101+
gl.glLinkProgram(id);
102+
103+
// Check link status
104+
gl.glGetProgram(id, GL.GL_LINK_STATUS, intBuf);
105+
if (intBuf.get(0) != GL.GL_TRUE) {
106+
gl.glGetProgram(id, GL.GL_INFO_LOG_LENGTH, intBuf);
107+
String infoLog = gl.glGetProgramInfoLog(id, intBuf.get(0));
108+
gl.glDeleteShader(shaderId);
109+
gl.glDeleteProgram(id);
110+
throw new RendererException("Compute shader program linking failed: " + infoLog);
111+
}
112+
113+
// Shader object can be deleted after linking
114+
gl.glDeleteShader(shaderId);
115+
116+
clearUpdateNeeded();
117+
}
118+
119+
/**
120+
* Activates this compute shader for use.
121+
* Must be called before setting uniforms or dispatching.
122+
*/
123+
public void makeActive() {
124+
if(isUpdateNeeded()){
125+
createComputeShader();
126+
}
127+
gl.glUseProgram(id);
128+
}
129+
130+
/**
131+
* Dispatches the compute shader with the specified number of work groups.
132+
*/
133+
public void dispatch(int numGroupsX, int numGroupsY, int numGroupsZ) {
134+
gl.glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
135+
}
136+
137+
public void setUniform(int location, int value) {
138+
gl.glUniform1i(location, value);
139+
}
140+
141+
public void setUniform(int location, float value) {
142+
gl.glUniform1f(location, value);
143+
}
144+
145+
public void setUniform(int location, Vector2f value) {
146+
gl.glUniform2f(location, value.x, value.y);
147+
}
148+
149+
public void setUniform(int location, Vector3f value) {
150+
gl.glUniform3f(location, value.x, value.y, value.z);
151+
}
152+
153+
public void setUniform(int location, Vector4f value) {
154+
gl.glUniform4f(location, value.x, value.y, value.z, value.w);
155+
}
156+
157+
public void setUniform(int location, Matrix4f value) {
158+
FloatBuffer floatBuf16 = BufferUtils.createFloatBuffer(16);
159+
value.fillFloatBuffer(floatBuf16, true);
160+
floatBuf16.clear();
161+
gl.glUniformMatrix4(location, false, floatBuf16);
162+
}
163+
164+
public int getUniformLocation(String name) {
165+
return gl.glGetUniformLocation(id, name);
166+
}
167+
168+
public void bindShaderStorageBuffer(int location, ShaderStorageBufferObject ssbo) {
169+
gl.glBindBufferBase(GL4.GL_SHADER_STORAGE_BUFFER, location, ssbo.getId());
170+
}
171+
172+
@Override
173+
public void resetObject() {
174+
id = INVALID_ID;
175+
setUpdateNeeded();
176+
}
177+
178+
@Override
179+
public void deleteObject(Object rendererObject) {
180+
if(id != INVALID_ID){
181+
gl.glDeleteProgram(id);
182+
}
183+
resetObject();
184+
}
185+
186+
@Override
187+
public NativeObject createDestructableClone() {
188+
return new ComputeShader(this);
189+
}
190+
191+
@Override
192+
public long getUniqueId() {
193+
//Note this is the same type of ID as a regular shader.
194+
return ((long)OBJTYPE_SHADER << 32) | (0xffffffffL & (long)id);
195+
}
196+
}

jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,11 @@ public interface GL {
424424
*/
425425
public void glBufferData(int target, ByteBuffer data, int usage);
426426

427+
/**
428+
* See {@link #glBufferData(int, ByteBuffer, int)}
429+
*/
430+
public void glBufferData(int target, IntBuffer data, int usage);
431+
427432
/**
428433
* <p><a target="_blank" href="http://docs.gl/gl4/glBufferSubData">Reference Page</a></p>
429434
* <p>
@@ -824,6 +829,11 @@ public void glCompressedTexSubImage2D(int target, int level, int xoffset, int yo
824829
*/
825830
public void glGetBufferSubData(int target, long offset, ByteBuffer data);
826831

832+
/**
833+
* See {@link #glGetBufferSubData(int, long, ByteBuffer)}
834+
*/
835+
public void glGetBufferSubData(int target, long offset, IntBuffer data);
836+
827837
/**
828838
* <p><a target="_blank" href="http://docs.gl/gl4/glGetError">Reference Page</a></p>
829839
*

jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,30 @@ public interface GL4 extends GL3 {
4242
public static final int GL_TESS_EVALUATION_SHADER = 0x8E87;
4343
public static final int GL_PATCHES = 0xE;
4444

45+
/**
46+
* Accepted by the {@code shaderType} parameter of CreateShader.
47+
*/
48+
public static final int GL_COMPUTE_SHADER = 0x91B9;
49+
50+
/**
51+
* Accepted by the {@code barriers} parameter of MemoryBarrier.
52+
*/
53+
public static final int GL_SHADER_STORAGE_BARRIER_BIT = 0x00002000;
54+
public static final int GL_TEXTURE_FETCH_BARRIER_BIT = 0x00000008;
55+
56+
/**
57+
* Accepted by the {@code condition} parameter of FenceSync.
58+
*/
59+
public static final int GL_SYNC_GPU_COMMANDS_COMPLETE = 0x9117;
60+
61+
/**
62+
* Returned by ClientWaitSync.
63+
*/
64+
public static final int GL_ALREADY_SIGNALED = 0x911A;
65+
public static final int GL_TIMEOUT_EXPIRED = 0x911B;
66+
public static final int GL_CONDITION_SATISFIED = 0x911C;
67+
public static final int GL_WAIT_FAILED = 0x911D;
68+
4569
/**
4670
* Accepted by the {@code target} parameter of BindBufferBase and BindBufferRange.
4771
*/
@@ -104,7 +128,7 @@ public interface GL4 extends GL3 {
104128
/**
105129
* Binds a single level of a texture to an image unit for the purpose of reading
106130
* and writing it from shaders.
107-
*
131+
*
108132
* @param unit image unit to bind to
109133
* @param texture texture to bind to the image unit
110134
* @param level level of the texture to bind
@@ -114,5 +138,61 @@ public interface GL4 extends GL3 {
114138
* @param format format to use when performing formatted stores
115139
*/
116140
public void glBindImageTexture(int unit, int texture, int level, boolean layered, int layer, int access, int format);
117-
141+
142+
/**
143+
* <p><a target="_blank" href="http://docs.gl/gl4/glDispatchCompute">Reference Page</a></p>
144+
* <p>
145+
* Launches one or more compute work groups.
146+
*
147+
* @param numGroupsX the number of work groups to be launched in the X dimension
148+
* @param numGroupsY the number of work groups to be launched in the Y dimension
149+
* @param numGroupsZ the number of work groups to be launched in the Z dimension
150+
*/
151+
public void glDispatchCompute(int numGroupsX, int numGroupsY, int numGroupsZ);
152+
153+
/**
154+
* <p><a target="_blank" href="http://docs.gl/gl4/glMemoryBarrier">Reference Page</a></p>
155+
* <p>
156+
* Defines a barrier ordering memory transactions.
157+
*
158+
* @param barriers the barriers to insert. One or more of:
159+
* {@link #GL_SHADER_STORAGE_BARRIER_BIT}
160+
* {@link #GL_TEXTURE_FETCH_BARRIER_BIT}
161+
*/
162+
public void glMemoryBarrier(int barriers);
163+
164+
/**
165+
* <p><a target="_blank" href="http://docs.gl/gl4/glFenceSync">Reference Page</a></p>
166+
* <p>
167+
* Creates a new sync object and inserts it into the GL command stream.
168+
*
169+
* @param condition the condition that must be met to set the sync object's state to signaled.
170+
* Must be {@link #GL_SYNC_GPU_COMMANDS_COMPLETE}.
171+
* @param flags must be 0
172+
* @return the sync object handle
173+
*/
174+
public GLFence glFenceSync(int condition, int flags);
175+
176+
/**
177+
* <p><a target="_blank" href="http://docs.gl/gl4/glClientWaitSync">Reference Page</a></p>
178+
* <p>
179+
* Causes the client to block and wait for a sync object to become signaled.
180+
*
181+
* @param sync the sync object to wait on
182+
* @param flags flags controlling command flushing behavior. May be 0 or GL_SYNC_FLUSH_COMMANDS_BIT.
183+
* @param timeout the timeout in nanoseconds for which to wait
184+
* @return one of {@link #GL_ALREADY_SIGNALED}, {@link #GL_TIMEOUT_EXPIRED},
185+
* {@link #GL_CONDITION_SATISFIED}, or {@link #GL_WAIT_FAILED}
186+
*/
187+
public int glClientWaitSync(GLFence sync, int flags, long timeout);
188+
189+
/**
190+
* <p><a target="_blank" href="http://docs.gl/gl4/glDeleteSync">Reference Page</a></p>
191+
* <p>
192+
* Deletes a sync object.
193+
*
194+
* @param sync the sync object to delete
195+
*/
196+
public void glDeleteSync(GLFence sync);
197+
118198
}

0 commit comments

Comments
 (0)